2015-03-05 13 views
18

Jestem świadomy, że możliwe jest przypisywanie metod kontrolera za pomocą @JsonView(...) w celu statycznego zdefiniowania pojedynczej klasy widoku w Spring MVC. Niestety oznacza to, że potrzebuję innego punktu końcowego dla każdego rodzaju widoku, jaki mógłbym mieć.Dynamiczny wybór JsonView na wiosnę Kontroler MVC

Widzę, że inni ludzie pytali o to before. Chociaż takie podejście może działać, Spring często ma wiele sposobów robienia tego samego. Czasami rozwiązanie może być o wiele prostsze, niż po raz pierwszy pojawia się, jeśli masz trochę wiedzy na temat niektórych wewnętrznych elementów.

Chciałbym mieć punkt kontrolny z pojedynczym kontrolerem, który może dynamicznie wybierać odpowiedni widok na podstawie bieżącej wartości głównej. Czy mogę zwrócić Model za pomocą atrybutu zawierającego odpowiednią klasę widoku lub instancję MappingJacksonValue bezpośrednio?

widzę w org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#writeInternal jest to fragment kodu, który określa, co zobaczyć w użyciu:

if (value instanceof MappingJacksonValue) { 
      MappingJacksonValue container = (MappingJacksonValue) object; 
      value = container.getValue(); 
      serializationView = container.getSerializationView(); 
     } 

który wydaje się pochodzić z org.springframework.web.servlet.mvc.method.annotation.JsonViewResponseBodyAdvice#beforeBodyWriteInternal ale mam problemy z pracy, czy istnieje sposób mogłem bypass to po prostu zwracając konkretną wartość, która zawiera informacje niezbędne dla Jackson2HttpMessageConverter, aby wybrać odpowiedni widok.

Każda pomoc bardzo ceniona.

+0

Można również skonfigurować ContentNegotiatingViewResolver – Richard

Odpowiedz

28

W przypadku, gdy ktoś inny chce osiągnąć to samo, jest to bardzo proste.

Możesz bezpośrednio zwrócić instancję org.springframework.http.converter.json.MappingJacksonValue ze swojego kontrolera, który zawiera zarówno obiekt, który chcesz serializować, jak i klasę widoku.

Zostanie to pobrane za pomocą metody org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#writeInternal i zostanie użyty odpowiedni widok.

To działa tak:

@RequestMapping(value = "/accounts/{id}", method = GET, produces = APPLICATION_JSON_VALUE) 
public MappingJacksonValue getAccount(@PathVariable("id") String accountId, @AuthenticationPrincipal User user) { 
    final Account account = accountService.get(accountId); 
    final MappingJacksonValue result = new MappingJacksonValue(account); 
    final Class<? extends View> view = accountPermissionsService.getViewForUser(user); 
    result.setSerializationView(view); 
    return result; 
} 
5

Tutaj jest odmianą powyższej odpowiedzi, która pomogła mi. Znalazłem problemy zwracające MappingJacksonValue bezpośrednio podczas korzystania z ładunków Spring HATEOAS. Jeśli zwrócę go bezpośrednio z kontrolera kontrolera, z jakiegoś powodu miksy nie będą poprawnie zastosowane, a odsyłacze JSON HAL są renderowane jako łącza. Również Spring ResponseEntity nie jest renderowany, ponieważ powinien pokazywać obiekty w polu danych.

Korzystanie ControllerAdvice aby osiągnąć ten sam pomógł z tym i teraz moje ładunki są renderowane poprawnie, a widoki są stosowane zgodnie z potrzebami

@ControllerAdvice(assignableTypes = MyController.class) 
public class MyControllerAdvice extends AbstractMappingJacksonResponseBodyAdvice { 

    @Override 
    protected void beforeBodyWriteInternal(MappingJacksonValue bodyContainer, MediaType contentType, MethodParameter returnType, 
             ServerHttpRequest req, ServerHttpResponse res) { 
    ServletServerHttpRequest request = (ServletServerHttpRequest)req; 
    String view = request.getServletRequest().getParameter("view"); 
    if ("hello".equals(view)) { 
     bodyContainer.setSerializationView(HelloView.class); 
    } 
    } 
} 
Powiązane problemy