`

SpringMvc配置 导致实事务失效

 
阅读更多

SpringMVC回归MVC本质,简简单单的Restful式函数,没有任何基类之后,应该是传统Request-Response框架中最好用的了。

Tips

1.事务失效的惨案

Spring MVC最打击新人的事情,你必须保证spring-mvc.xml的context:component-scan只扫描Controller,而 applicationContext.xml里的不包含Controller. 否则你定义在applicationContext.xml里的事务就要失效了。方法如下:

spring-mvc.xml:

<context:component-scan base-package="com.mycompany.myproject" use-default-filters="false">
	<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

applicationContext.xml:

<context:component-scan base-package="org.springside.examples.quickstart">
	<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
另外,定义在spring-mvc.xml里的东西,在applicationContext*.xml中是不可见的,想共享的东西最好放在applicationContext.xml那边。
而applicationContext*.xml里的一些BeanPostProccesor,也不会作用到spring-mvc.xml定义/扫描到的Bean上,如果有必要就在spring-mvc.xml里重新定义一次,像Shiro的AOP校验权限。

2.Struts2式的Preparable接口--表单仅包含对象领域部分属性

Struts2有一个很实用的Preparable二次绑定功能: 表单提交时,先绑定一个ID,使用这个ID从数据库里找出对象来,再把表单中的其他属性绑定到这个对象上,对于那些表单中的输入框数量比业务对象的实际属性数少的情况很实用。

其实Spring MVC也有相同的能力, 见quickstart中的UserAdminController.

先用@ModelAttribute标注如下函数。SpringMVC会在执行任何实际处理函数之前,执行该函数并将返回值存为Model Attribute "user"

@ModelAttribute("user")
public User getUser(@RequestParam(value = "id", required = false) Long id) {
	if (id != null) {
		return accountService.getUser(id);
	}
	return null;
}

再在save函数里,以@ModelAttribute标注表单处理函数的参数。SpringMVC就会按名称"user"取出前面的对象,然后才进行真正的Binding。

@RequestMapping(value = "update/{userId}", method = RequestMethod.POST)
public String update(@Valid @ModelAttribute("user") User user) {
	accountService.updateUser(user);
	return "redirect:/admin/user";
}

注意1, 这里有个小坑爹的地方是,这个getUser()会在controller的所有函数前都执行,因此需要进行一下判断RequestParam中是否含id属性的判断,要不你就把update()方法独立到一个Controller中。

注意2, ModelAttribute如果已经占用了"user"这个名字,那些非update()函数的参数里就要躲开这个名字。

另外,你也可以选择不用这个功能,而是自己创建一个Form的DTO,然后用Dozer或手工把属性绑定到领域对象上。


3.Struts2式的FlashAttribute

为了防止用户刷新重复提交,save操作之后一般会redirect到另一个页面,同时带点操作成功的提示信息。因为是Redirect,Request里的attribute不会传递过去,如果放在session中,则需要在显示后及时清理,不然下面每一页都带着这个信息也不对。Spring在3.1才提供了这个能力。

public String save(@ModelAttribute("group") Group group, RedirectAttributes redirectAttributes) {
	accountManager.saveGroup(group);
	redirectAttributes.addFlashAttribute("message", "修改权限组成功");
	return "redirect:/account/group/";
}

4.CheckBox/RadioButtons的绑定

在采用ORM的应用中,如果绑定子对象到页面上,以及在表单提交时如何把checkbox的内容重新绑回父对象是一个头痛的问题。

在showcase示例中,User-Role组合中的Role是一个对象而不是简单的枚举(对于简单的枚举,什么都不用做,直接用checkboxes的taglib就可以了。

<form:checkboxes path="permissionList" items="${allPermissions}" itemLabel="displayName" itemValue="value" />

注意,如果使用BootStrap,SpringMVC自带的checkboxes标签并不合用,详见Twitter Bootstrap章节。

而复杂对象时对象就没这么好彩了,详见showcase中的UserControler首先你需要设定不要自动绑定checkbox结果到对象中

@InitBinder
protected void initBinder(WebDataBinder binder) {
	binder.setDisallowedFields("roleList");
}

然后在输入参数中多注入一个roleList, 自行处理:

@RequestMapping(value = "save/{userId}")
public String update(@Valid @ModelAttribute("user") User user,
		@RequestParam(value = "roleList") List<Long> checkedRoleList) {
	user.getRoleList().clear();
	for (Long roleId : checkedRoleList) {
		Role role = new Role(roleId);
		user.getRoleList().add(role);
	}

	accountService.saveUser(user);
	return "redirect:/account/user";
}

5.输出跨域Ajax所需的JsonP

网上说什么扩展JsonView什么的太复杂了,自己拿Jackson生成一个JsonP的字符串返回就好了。 更多JSONP信息见Ajax章节.

6.Spring MVC与Hibernate Validator的结合

Validation章节,一般情况下使用JQuery Validation Plugin的客户端认证。为了防止恶意用户的攻击,可以再加上Spring MVC与Hibernate Validator的服务端认证。因为是用来防恶意攻击的,因此直接抛出异常,而不会返回输入页面且输出出错信息(如果Controller方法中有BindingResult的参数,就交由方法内部去处理,否则直接往外抛异常)。

  1. 在spring-mvc.xml中,加入hibernate validator的定义
  2. 在User.java的相关属性加入@NotBlank定义
  3. 在UserDetailController的save方法,加入@Valid定义和BindingResult参数。

7. WARNING: "Skipping URI variable 'id' since the request contains a bind value

造成这个Warning的原因是url的path和表单中都有id 变量,这个时候,把url path改成别的名字就好了。

@RequestMapping(value = "save/{userId}")

分享到:
评论

相关推荐

    Spring+SpringMVC配置事务管理无效原因及解决办法详解

    在 application.xml 中配置的事务管理会被 SpringMVC 重复扫描,导致事务管理无效。 解决办法 要解决 Spring+SpringMVC 配置事务管理无效的问题,需要正确配置 Spring 和 SpringMVC 的配置文件。Spring 的配置文件...

    springmvc分布式.txt

    - **可靠性**:单个节点的故障不会导致整个系统失效。 - **可扩展性**:可以通过增加节点来提高系统的处理能力或存储容量。 3. **挑战**: - **一致性问题**:如何确保不同节点之间的数据保持一致。 - **容错性...

    SSM框架整合演示代码

    在SSM整合中,避免了SpringMVC与Spring注解重复扫描导致的事务失效问题,这可能涉及到Spring的扫描范围设置。当两个不同组件扫描相同范围的类时,可能会出现事务管理器无法正确识别事务边界的问题。通过合理配置扫描...

    SSM中事务管理所需的jar包-aspectjweaver

    8. **注意事项**:虽然AspectJ事务管理方便,但需要正确配置并理解其工作原理,否则可能导致事务管理失效或产生意外的结果。此外,由于其运行时编织的特性,可能会带来一定的性能影响。 总结起来,`aspectjweaver....

    SpringMVCHibernate集成及常见问题总结

    - **事务管理**:Spring的事务管理可能因为配置不当导致事务无法正常回滚或提交。 - **缓存问题**:Ehcache的配置可能导致缓存失效、更新不及时等问题。 - **资源文件**:国际化消息文件的路径和编码设置不当可能...

    spring杂谈 作者zhang KaiTao

    在处理自我调用的事务时,需要注意由于事务的传播属性导致的问题,以及使用代理模式可能带来的风险。作者提到了如何解决这些问题并分析了不同实现方式的优缺点。 AOP(面向切面编程)是Spring的另一大亮点。作者...

    SSM框架所需jar包_完整jar包

    SSM框架,全称为Spring、SpringMVC和MyBatis的集成框架,是Java开发Web应用的常用技术栈。这个压缩包提供了SSM框架所需的jar包,包括C3p0连接池、MyBatis 3.4版本以及Spring 5.1.9版本的核心组件。以下是对这些关键...

    跳槽涨薪涨薪必备精选面试题.pdf

    Spring事务管理基于AOP实现,`@Transactional`失效可能因未开启事务、异常未被抛出等原因。 Spring容器启动流程包括加载配置、解析bean定义、实例化bean、依赖注入等。 Spring使用的设计模式包括工厂模式、代理...

    (2024)跳槽涨薪必备精选面试题.pdf

    9. **SpringMVC的工作流程** - 接收客户端请求。 - DispatcherServlet 分发请求。 - HandlerMapping 映射请求到 Controller。 - HandlerAdapter 处理请求。 - ViewResolver 解析视图。 10. **SpringBoot常用...

    java面试知识

    - **内存泄露**:不再使用的对象没有被垃圾回收机制及时回收,导致内存占用持续增加。 - **内存溢出**:当程序申请内存超过系统所能提供的最大内存时,会出现内存溢出错误。 ##### 单例 - **目的**:确保某个类...

Global site tag (gtag.js) - Google Analytics