Spring 1.2升级至5.3:表单控制器Bean配置适配问题咨询
解决Spring 1.2到5.3升级中FormController配置的替换问题
Hey,我太懂你现在升级Spring版本的头疼了——那些在1.2里用得顺风顺水的sessionForm、commandName属性,到5.3里直接报“不可写”错误,这是因为Spring MVC在3.x之后就彻底废弃了传统的FormController体系,转向了注解驱动的控制器模型,老属性自然就不被支持了。
下面给你一套完整的替换方案,完全覆盖你原来Bean配置的所有功能,同时贴合Spring 5.3的最佳实践:
一、核心思路:从XML配置的FormController迁移到注解式控制器
原来的PriceIncreaseFormController继承了Spring老版本的FormController类,现在我们要改成用@Controller注解标注的类,通过注解实现原来的所有配置项。
1. 新的控制器代码(Java类)
替换你原有的web.PriceIncreaseFormController,代码如下:
package web; import bus.PriceIncrease; import bus.ProductManager; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.SessionAttributes; @Controller @SessionAttributes("priceIncrease") // 替代原来的sessionForm=true,将表单对象存入session public class PriceIncreaseFormController { // 构造器注入(Spring 4.3+推荐方式,无需@Autowired) private final ProductManager productManager; private final PriceIncreaseValidator priceIncreaseValidator; public PriceIncreaseFormController(ProductManager productManager, PriceIncreaseValidator priceIncreaseValidator) { this.productManager = productManager; this.priceIncreaseValidator = priceIncreaseValidator; } // 替代原来的commandName和commandClass:创建表单绑定的模型对象 @ModelAttribute("priceIncrease") public PriceIncrease createPriceIncreaseModel() { return new PriceIncrease(); } // 处理表单展示请求(对应原来的formView) @GetMapping("/priceincrease") public String showPriceIncreaseForm() { return "priceincrease"; } // 处理表单提交请求(对应原来的successView和验证逻辑) @PostMapping("/priceincrease") public String processPriceIncreaseSubmit( @ModelAttribute("priceIncrease") PriceIncrease priceIncrease, BindingResult bindingResult, Model model) { // 调用自定义验证器(对应原来的validator属性) priceIncreaseValidator.validate(priceIncrease, bindingResult); if (bindingResult.hasErrors()) { // 验证失败,返回表单页面 return "priceincrease"; } // 执行业务逻辑:调用productManager处理价格上涨(和原来的逻辑一致) productManager.increasePrices(priceIncrease.getPercentage()); // 成功后从session移除表单对象,避免后续请求残留 model.addAttribute("priceIncrease", null); // 用redirect避免重复提交(比直接返回视图更规范) return "redirect:/hello.htm"; } }
2. 调整Spring XML配置
原来的priceIncreaseForm Bean可以完全删除,换成以下配置支持注解驱动:
<!-- 启用Spring MVC注解驱动(必须项) --> <mvc:annotation-driven/> <!-- 扫描控制器所在的包,让Spring自动识别@Controller注解的类 --> <context:component-scan base-package="web"/> <!-- 视图解析器:保留你原来的配置即可,这里给个示例 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <!-- 根据你的实际视图路径调整 --> <property name="suffix" value=".jsp"/> <!-- 根据你的视图类型调整,比如.jsp或.html --> </bean> <!-- 保留原来的验证器和业务Bean配置,这些不需要改 --> <bean id="priceIncreaseValidator" class="bus.PriceIncreaseValidator"/> <bean id="prodMan" class="bus.ProductManager"> <!-- 原来的属性配置(比如数据源等)继续保留 --> </bean>
二、关键配置项的对应关系
给你梳理老配置和新注解/代码的对应逻辑,方便理解:
sessionForm=true→@SessionAttributes("priceIncrease"):将指定名称的模型对象存入session,实现跨请求保留表单数据的功能commandName="priceIncrease"+commandClass="bus.PriceIncrease"→@ModelAttribute("priceIncrease")方法:创建并命名表单绑定的实体对象,和原来的参数绑定逻辑一致validator→ 直接注入PriceIncreaseValidator并在提交方法中调用:验证逻辑和原来完全兼容formView="priceincrease"→@GetMapping方法返回"priceincrease":处理GET请求,返回表单视图successView="hello.htm"→return "redirect:/hello.htm":处理提交成功后的跳转,用redirect避免用户刷新页面导致重复提交productManager依赖 → 构造器注入:Spring 5推荐的依赖注入方式,比原来的XML属性注入更安全
三、额外注意事项
- Java版本要求:Spring 5.3最低要求Java 8,确保你的项目已经升级到Java 8或以上版本
- 验证器兼容:如果你的
PriceIncreaseValidator实现了org.springframework.validation.Validator接口,直接注入即可使用,不需要修改 - 请求路径:确保你的表单提交的路径和
@PostMapping的路径一致(这里是/priceincrease)
内容的提问来源于stack exchange,提问作者user3067524




