Spring MappingJackson2JsonView 视图的怪异问题
时间比较匆忙,可能记录有些乱。
先说明一下问题:我用Spring MVC 4.0+ 编写restful框架, 因为看到了提供有MappingJackson2JsonView类,就没有通过自己转换json, 返回字符串。
但是遇到一个灵异的问题:如果利用javaBean类接收参数,在返回值中,会自动把javaBean的键值对以json格式返回,效果等同于对javaBean参数使用了标签@ModelAttribute
如
会返回
使用 View 是因为以后有需要的话,可能会重写一个JsonView。
翻了一天的源码,看到了如下几个部分(以图片中的代码举例):
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest)
初始container的model里有2个对象,但并没有返回的data Map, 而是一个user和一个BindingResult,user是入参,BindingResult用于validation绑定页面元素。
在
org.springframework.web.servlet.DispatcherServlet#processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception)
方法中通过
org.springframework.web.servlet.view.AbstractView#createMergedOutputModel(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
方法将data Map参数放入model,由ModelAndView对象持有。
然后MappingJackson2JsonView#filterModel 方法会过滤掉BindingResult 以及 指定的filter规则类
protected Object filterModel(Map<String, Object> model) {
Map<String, Object> result = new HashMap<String, Object>(model.size());
Set<String> modelKeys = (!CollectionUtils.isEmpty(this.modelKeys) ? this.modelKeys : model.keySet());
for (Map.Entry<String, Object> entry : model.entrySet()) {
if (!(entry.getValue() instanceof BindingResult) && modelKeys.contains(entry.getKey()) &&
!entry.getKey().equals(JsonView.class.getName()) &&
!entry.getKey().equals(FilterProvider.class.getName())) {
result.put(entry.getKey(), entry.getValue());
}
}
return (this.extractValueFromSingleKeyModel && result.size() == 1 ? result.values().iterator().next() : result);
}
modelKeys 可以通过 MappingJackson2JsonView#setModelKeys方法指定,所以如果希望只返回data Map 需要指定
MappingJackson2JsonView model = new MappingJackson2JsonView();
Map<String, Object> params = new HashMap<String, Object>();
params.put("data", object);
model.setModelKeys(params.keySet());
这种设计默认全部返回,通过Set数组参数 指定需要返回的json对象。如果全部展平为一级的map,是不是就可以不经过转换,而通过此参数指定给客户端返回的参数?
BindingResult 是将校验结果返回给页面展现,包括元素和错误message等信息。restful不需要此信息,所以系统自动忽略。
但是可以通过此规则进行入参校验