我知道可以使用@JsonView(...)
注释控制器方法,以在Spring MVC中静态定义单个视图类。不幸的是,这意味着我可能需要为每种类型的视图提供不同的端点。
我看到其他人问过before。虽然这种方法可行,但Spring通常有很多方法可以做同样的事情。如果您对某些内部结构有一些了解,有时解决方案可能比最初出现的要简单得多。
我想拥有一个可以根据当前主体动态选择合适视图的控制器端点。我是否可以直接返回包含相应视图类或Model
实例的属性的MappingJacksonValue
?
我在org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#writeInternal
中看到有一段代码确定了要使用的视图:
if (value instanceof MappingJacksonValue) {
MappingJacksonValue container = (MappingJacksonValue) object;
value = container.getValue();
serializationView = container.getSerializationView();
}
这似乎来自org.springframework.web.servlet.mvc.method.annotation.JsonViewResponseBodyAdvice#beforeBodyWriteInternal
,但是如果有一种方法可以绕过这个,只需返回一个包含Jackson2HttpMessageConverter
的必要信息的特定值,我就无法解决问题选择正确的观点。
任何帮助都非常感激。
答案 0 :(得分:37)
关于其他人想要达到同样目标的机会,实际上非常简单。
您可以直接从控制器返回一个org.springframework.http.converter.json.MappingJacksonValue
实例,该实例包含您要序列化的对象和视图类。
这将由org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#writeInternal
方法获取,并将使用相应的视图。
它的工作原理如下:
@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;
}
答案 1 :(得分:9)
以上是上述答案的变体,对我有所帮助。我发现在使用Spring HATEOAS有效负载时直接返回MappingJacksonValue
的问题。如果我直接从控制器的处理程序返回它,由于某种原因,Resources
和ResourceSupport
mixins未正确应用,而JSON HAL _links将呈现为链接。此外,Spring ResponseEntity
未呈现,因为它应在有效内容中显示body
和status
个对象。
使用ControllerAdvice
来实现同样的帮助,现在我的有效负载正确呈现并且视图将根据需要应用
@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);
}
}
}