`
ssxxjjii
  • 浏览: 938211 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

springmvc rest框架搭建中遇到的问题-xml转换错误

 
阅读更多

 

.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>

 

 

 

分享到:
评论
1 楼 lokepaqi 2013-05-20  
解决方案2稍微修改一下 locateToBeMarshalled 就可以支持返回多个对象了:

protected Object locateToBeMarshalled(Map<String, Object> model)
			throws ServletException {
		if (this.getModelKey() != null) {
			Object o = model.get(this.getModelKey());
			if (o == null) {
				throw new ServletException(
						"Model contains no object with key [" + modelKey + "]");
			}
			if (!this.getMarshaller().supports(o.getClass())) {
				throw new ServletException("Model object [" + o
						+ "] retrieved via key [" + modelKey
						+ "] is not supported by the Marshaller");
			}
			return o;
		}
		int i = 0;
		List list = new ArrayList();
		for (Object o : model.values()) {
			if (!(o instanceof BindingResult)) {
				i++;
				if (o != null && this.getMarshaller().supports(o.getClass())) {
					list.add(o);
				}
			}
		}
		if (i > 1) {
			return list;
		} else if (list.size() > 0) {
			return list.get(0);
		} else {
			return null;
		}
	}

相关推荐

    SpringMVC-Mybatis-Shiro-redis-0.2-master

    基于SpringMVC Mybatis Shiro Redis 的权限管理系统,该系统已经部署到线上,线上访问地址:http://shiro.itboy.net,登录账号:admin 密码:sojson,,详细教程参考sojson.com/shiro

    SpringMVC-Mybatis-Shiro-redis-master

    【标题】"SpringMVC-Mybatis-Shiro-redis-master" 涉及的是一个集成框架项目,这个项目集成了四个关键的技术组件:SpringMVC、MyBatis、Shiro和Redis。这些技术在现代Java Web开发中扮演着重要角色。 **SpringMVC**...

    springmvc 4.0框架搭建

    最简单的springmvc4.0框架搭建, 绝对可以运行

    SpringMVC 入门 框架搭建demo,

    **SpringMVC 入门与框架搭建** SpringMVC 是 Spring 框架的一个模块,主要负责处理 Web 应用程序中的请求和响应。它是一个轻量级的、基于模型-视图-控制器(MVC)设计模式的 Web 开发框架,提供了强大的数据绑定、...

    springMVC+mybatis搭建框架

    在搭建SpringMVC+MyBatis框架的过程中,我们首先需要配置Spring的ApplicationContext,定义Bean的生命周期和依赖关系。这通常通过XML配置文件完成,但也可以使用Spring Boot的注解驱动配置。接着,我们需要配置...

    SpringMVC-Mybatis-Shiro-redis

    《SpringMVC-Mybatis-Shiro-Redis:构建安全高效的Web应用》 在现代Web开发中,构建一个高效且安全的后端系统是至关重要的。本文将深入探讨一个基于SpringMVC、Mybatis、Shiro和Redis的Web应用架构,这四个组件共同...

    SpringMVC-Mybatis-Shiro-redis-0.2_baichengzhou.tar.gz

    《SpringMVC-Mybatis-Shiro-Redis整合实践详解》 在现代Web开发中,SpringMVC、Mybatis、Shiro以及Redis等技术是构建高效、安全、可扩展的Web应用的重要组件。本文将深入探讨这些技术的集成与应用,以"SpringMVC-...

    SpringMVC构建REST接口的源代码

    SpringMVC 是一个基于 Spring 框架的轻量级 Web 开发模块,它使得开发者可以轻松地构建可复用、可维护的 MVC(Model-View-Controller)应用程序。REST(Representational State Transfer)是一种软件架构风格,常...

    springMVC基础框架搭建

    在浏览器中输入`http://localhost:8080/springMVC-test/hello`,如果一切正常,你应该能看到"hello"页面。 通过以上步骤,你就成功搭建了一个基础的SpringMVC框架。这只是SpringMVC的冰山一角,实际项目中还会涉及...

    SpringMVC完整框架搭建(springMVC+Hibernate)

    SpringMVC是Spring框架的一部分,专门用于处理Web应用程序的请求-响应模型。它是一个轻量级的、基于注解的模型-视图-控制器(MVC)架构,为开发人员提供了一种简单而有效的方式来组织和构建Web应用程序。在本项目中...

    springMVC3学习(八)--全局的异常处理(源码)

    springMVC3学习(八)--全局的异常处理(源码) 文章地址:http://blog.csdn.net/itmyhome1990/article/details/26286435

    Spring4.2+SpringMVC4.2+Mybatis3.3+Mybatis-Plus整合可直接用作后台开发

    Spring4.2 + SpringMVC4.2 + Mybatis3.3 + Mybatis-Plus(Mybatis的插件,封装了CRUD和分页查询等功能) + log4j + shrio权限框架,可直接用于后台的开发。

    mybatis-3.4.5、springMVC-5.0.4、mybatis-spring-1.3.2整合包

    本整合包提供了这三个组件的最新版本,即mybatis-3.4.5、springMVC-5.0.4和mybatis-spring-1.3.2,旨在帮助开发者快速搭建基于这些技术的项目环境。 **MyBatis** 是一个优秀的持久层框架,它支持定制化SQL、存储...

    基于springmvc框架,搭建

    为了使SpringMVC工作,还需要在web.xml中配置DispatcherServlet,并创建Spring的配置文件以启用注解驱动的配置。在web.xml中,添加如下配置: ```xml &lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt; &lt;servlet-class&gt;...

    纯springMVC基础框架

    搭建一个纯SpringMVC框架的过程包括以下步骤: 1. 引入SpringMVC相关的依赖库。 2. 配置web.xml以启动DispatcherServlet。 3. 创建SpringMVC的配置文件,如spring-servlet.xml,配置处理器映射器、适配器、视图解析...

    springmvc框架搭建,已测试

    - 在web.xml中配置DispatcherServlet。 - 编写简单的Hello World示例,测试SpringMVC框架的正确性。 总结,"springmvc框架搭建,已测试"这个项目提供了一个基础的SpringMVC应用实例,涵盖了SpringMVC的核心组件和...

    Spring SpringMVC mybatis框架搭建所需jar包

    在Java开发领域,Spring、SpringMVC和MyBatis是三个非常重要的轻量级框架,它们共同构建了SSM(Spring、SpringMVC、MyBatis)架构,用于开发高效、灵活的企业级Web应用程序。本篇文章将详细阐述这三个框架的核心功能...

    springmvc开发框架搭建实例

    SpringMVC是一款强大的Java web开发框架,由Spring IO团队维护,是Spring生态体系的重要组成部分。本实例将带你深入了解如何搭建一个完整的SpringMVC项目。在提供的压缩包中,包含了一个数据库脚本文件`liun.sql`,...

    springMVC3学习(六)--SimpleFormController(源码)

    springMVC3学习(六)--SimpleFormController(源码) 文章地址:http://blog.csdn.net/itmyhome1990/article/details/25988733

    maven项目SpringMVC框架搭建

    创建maven项目,由maven项目转变成javaweb项目,内涵Servlet+SpringMVC的基本框架,上传资源之所以设置1分分值是因为楼主本身也需要从其它地方下载资源,亦需要支付积分,请见谅.

Global site tag (gtag.js) - Google Analytics