时间比较匆忙,可能记录有些乱。 先说明一下问题:我用 Spring MVC 4.0+ 编写 restful 框架, 因为看到了提供有 MappingJackson2JsonView 类,就没有通过自己转换 json, 返回字符串。 但是遇到一个灵异的问题:如果利用 javaBean 类接收参数,在返回值中,会自动把 j ..

Spring MappingJackson2JsonView 视图的怪异问题

本贴最后更新于 1165 天前,其中的信息可能已经时移世异

时间比较匆忙,可能记录有些乱。

先说明一下问题:我用 Spring MVC 4.0+ 编写 restful 框架, 因为看到了提供有 MappingJackson2JsonView 类,就没有通过自己转换 json, 返回字符串。

但是遇到一个灵异的问题:如果利用 javaBean 类接收参数,在返回值中,会自动把 javaBean 的键值对以 json 格式返回,效果等同于对 javaBean 参数使用了标签 @ModelAttribute


1463130640035

会返回

1463130647186

使用 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 不需要此信息,所以系统自动忽略。

但是可以通过此规则进行入参校验

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    562 引用 • 1187 回帖 • 865 关注
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    21 引用 • 103 回帖 • 185 关注
  • JSON

    JSON (JavaScript Object Notation)是一种轻量级的数据交换格式。易于人类阅读和编写。同时也易于机器解析和生成。

    36 引用 • 159 回帖
3 回帖   
请输入回帖内容...
  • 88250

    挽尊

  • crick77  

    @88250 via Android

  • crick77  

    @88250 我看了一下 手机端的代码显示 很混乱啊