.bean to xml显示的xml不是我往ModelAndView中塞的bean
怎么说呢,
Task task = taskManager.getTaskById(id);
ModelAndView result = new ModelAndView();
result.addObject("task",task);
结果应该是这样的。。。
<task>
<taskname>任务查询</taskname>
<priority>1</priority>
<startdate>2010-10-13 08:30:43</startdate>
</task>
但实际上,却是
<bean-property-binding-result field-error-count="0" global-error-count="0" error-count="0">
...
而demo里是好的啊,我怎么就出问题了呢。。。
调试了spring源代码,在model的map中发现,spring转的bean不是我塞进去的Task对象,而是BindingResult.task,如下:
{org.springframework.validation.BindingResult.task=org.springframework.validation.BeanPropertyBindingResult: 0 errors, task=com.css.pms.demo.entity.Task@1b1dfe5}
我要调试了下rapdi的demo,发现它的model里面的map和我一样啊,为啥它取出来的却是正确的呢?
rapid代码
ModelAndView result = new ModelAndView();
result.addObject("userinfo",userinfo);
{userInfo=com.company.project.model.UserInfo@7da18e[UserId=1,Username=badqiu,Password=123,BirthDate=<null>,Sex=1,Age=2], org.springframework.validation.BindingResult.userInfo=org.springframework.validation.BeanPropertyBindingResult: 0 errors}
在spring源代码处终于发现了问题所在:
在AnnotationMethodHandlerAdapter类的getModelAndView方法中
ModelAndView mav = (ModelAndView) returnValue;//这里的mav中的ModelMap是个LinkedHashMap
mav.getModelMap().mergeAttributes(implicitModel);
但是随后的,AbstractView的public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)方法
Map<String, Object> mergedModel =
new HashMap<String, Object>(this.staticAttributes.size() + (model != null ? model.size() : 0));
mergedModel.putAll(this.staticAttributes);
if (model != null) {
mergedModel.putAll(model);
}
这里又变成了普通的HashMap
在MarshallingView中的locateToBeMarshalled方法中中,是遍历获取第一个对象的
for (Object o : model.values()) {
...
}
但由于此时的model已经不是LinkedHashMap,只是普通的HashMap,导致里面的BindingResult对象和Bean对象的顺序有可能变掉了(hashmap按照字母排?),
至于我的程序取出来的bean是错误的,而rapid的demo里面取出来的是正确的,只是demo的狗屎运,没碰上这个问题。
为了验证,我把我的程序里的result.addObject("task",task);改成result.addObject("userinfo",task);
而demo里的改成相反的,结果,我的xml内容对了,demo的xml内容错了。
解决办法一:在网上找到了老外的解决办法:
原先的result.addObject("task",task);
得变成result.addObject(BindingResult.MODEL_KEY_PREFIX + "task", task); 太丑陋了,不喜欢,同时,加了这个前缀,转成json又出现问题了
解决办法二:老样子,重写spring中配置的org.springframework.web.servlet.view.xml.MarshallingView
改写这个locateToBeMarshalled方法
粗暴的将遇到的BindingResult对象跳过
if(o instanceof BindingResult){
continue;
}
算是暂时解决了。
总结:这次框架的搭建,让我感受到真不容易啊,网上的代码示例比比皆是,但挪到自己身上才发现问题一大堆
BindingResult问题,spring的bug
cglib代理类的问题,凡是beantoxml的工具,都有遇到,xstream,jaxb2,castor,目前只有castor1.2版本解决了这个问题,而最新的1.3.1版本,反而没有去重测这个功能,导致错误。
以上为网上解决方案
--------
我的解决方案
其实很简单在
<bean name="xmlStreamView" class="org.springframework.web.servlet.view.xml.MarshallingView">
<!-- 设置返回前端model中的key -->
<property name="modelKey" value="result"></property>
设置下
modelKey
即可:以后每个model中返回前端的key必选为设置的这个固定key。
spring自动转xml的不足之处,就是ModelMap中不可以放置多个,只能转换一个。
<!-- 配置ContentNegotiatingViewResolver来支持返回多种视图 指定order优先级 先找order 1 找不到找后续的jspView(order 2) --> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="order" value="1"></property> <!-- 忽略accept header <property name="ignoreAcceptHeader" value="true"></property> --> <property name="mediaTypes"> <map> <entry key="json" value="application/json"></entry> <entry key="xml" value="application/xml"></entry> </map> </property> <property name="defaultViews"> <list> <!-- json view <bean name="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"> </bean> --> <bean name="myJsonView" class="com.mypic.spring.expand.MyMappingJacksonJsonView"></bean> <!-- xml view --> <bean name="xmlStreamView" class="org.springframework.web.servlet.view.xml.MarshallingView"> <!-- 设置返回前端model中的key --> <property name="modelKey" value="result"></property> <property name="marshaller"> <bean class="org.springframework.oxm.xstream.XStreamMarshaller"> <!-- 启用annotation --> <property name="autodetectAnnotations" value="true"></property> <!-- 类别名 --> <property name="aliases"> <map> <!-- Account这个类的别名就变成了myBeans,那么转换后的xml中就是myBeans --> <!-- <entry key="myBeans" value="com.hoo.entity.Account"/> --> </map> </property> <!-- 基本属性别名 --> <property name="fieldAliases"> <map> <!-- Account中的brithday这个属性 --> <!-- <entry key="com.hoo.entity.Account.brithday" value="生日"/> --> </map> </property> </bean> </property> </bean> </list> </property> </bean> <!-- JSP ViewResolver --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="order" value="2"></property> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp"></property> </bean>
相关推荐
- **配置文件**:在`web.xml`中配置DispatcherServlet,并指定其上下文配置文件路径。这一步骤对于初始化Spring MVC容器至关重要。 - **创建控制器**:使用@Controller注解标记一个Java类作为控制器,并使用@...
在本篇中,我们将深入探讨如何使用Spring MVC构建RESTful接口,主要关注的是...在"SpringMVC构建REST接口:第四篇 第一个REST风格的接口的源代码"这个主题中,你将找到一个完整的示例,帮助你更好地理解和实践这些知识。
这个项目将涵盖基本的控制器设置、REST端点创建、数据交互和错误处理等关键概念,为后续的Web开发奠定坚实基础。在实际操作中,读者可以按照文件名"spring_mvc"中的内容逐步实践每个步骤,加深理解。
Spring MVC 是一个强大的Java Web开发框架,用于构建高效、可维护的Web应用程序。在本教程中,我们将专注于如何使用Spring MVC 4搭建一个基于RESTful风格的服务。REST(Representational State Transfer)是一种软件...
SpringMVC是一个轻量级的MVC框架,主要用于构建Web应用程序中的表现层。它遵循Model-View-Controller(模型-视图-控制器)的设计模式,使得业务逻辑、用户界面和数据管理之间实现了很好的解耦。 - **设计理念**:...
SpringMVC项目快速搭建 构建Maven项目 日志配置 演示页面 Spring MVC配置 Web配置 简单控制器 运行 Spring MVC的常用注解 @Controller @RequestMapping @ResponseBody @...
- **REST 支持**:Spring MVC 提供了对 RESTful 风格 URL 和 JSON/XML 数据的支持。 #### 二、Spring MVC 的优势 1. **开发效率高**:Spring MVC 基于方法级别的拦截,这意味着每个方法都可以处理一个具体的 HTTP ...
在Spring MVC中,可以通过XML配置或Java配置(@Configuration注解)来定义DispatcherServlet、视图解析器、拦截器、消息转换器等组件。 10. **RESTful支持**: Spring MVC支持创建符合REST原则的Web服务,可以...
Spring MVC 是一个基于 Java 的轻量级 Web 开发框架,它是 Spring 框架的一部分,专为构建可维护、高性能的 MVC(Model-View-Controller)应用程序而设计。在这个压缩包中,包含了一个名为 "springmvc.pdf" 的文件,...
这个"springmvc包"可能包含了Spring MVC的核心组件和配置文件,用于搭建和运行Spring MVC应用程序。 在Spring MVC中,以下是一些关键知识点: 1. **DispatcherServlet**:这是Spring MVC的前端控制器,它是整个...