时间比较匆忙,可能记录有些乱。
先说明一下问题:我用 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 不需要此信息,所以系统自动忽略。
但是可以通过此规则进行入参校验
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于