Spring-SimpleFormController
2015-03-25 14:10
267 查看
Spring-SimpleFormController
SimpleFormController在Controller继承体系位于最底端,是一个功能强大,而且比较复杂的Controller。下面是SimpleFormController的主要继承图谱:(摘自http://www.javaworld.com.tw/jute/post/view?bid=42&id=152356)
SimpleFormController本身的强大和复杂性从上图就可以看出。实际上,SimpleController除了在处理上要经过一个多步的流程,而且在处理不同类型请求时(如post,get)。(希望大家看一下上面的图和bean定义)
下面是SimpleFormController的处理流程,分为post方法和get方法。
get方法处理流程(一般连接的形式为get方法):
按请求转到相应controller;
调用formBackingObject()方法,创建一个command对象的实例(如果设定了commandClass,则不需要override formBackingObject()方法了);
调用initBinder(),注册需要的类型转换器;
调用showForm()方法,返回一个view,即准备呈现给用户的视图,一般情况下这个方法是不需要override的,只需设定formView即可;
调用referenceData()方法。这个方法返回一个Map对象,可以把在view中需要展现的数据放入这个Map中;
转到formView指定的视图。
一般情况下步骤2,3,4的方法是不需要override的,它们只需要在配置文件中进行相关属性的定义即可。而步骤5的referenceData()一般是要在自己的SimpleFormController中进行重新定义的。
post方法处理流程(一般用于处理表单):
按请求转到相应controller;
调用formBackingObject()方法,创建一个command对象的实例(如果设定了commandClass,则不需要override formBackingObject()方法了);
把请求参数注入表单对象;
执行onBind()方法;
执行validator验证。
执行onBindAndValidate()方法;
若有err,则转到formView视图;
执行onSubmit()方法或doSubmitAction()方法。
同处理get方法一样,步骤2的formBackingObject()方法一般是不会去重载的。步骤3也不需要我们做什么。真正需要我们做的是4,5,6,8步。当然4,5,6是可选的,如果有需要,可以去实现它们中的一个或几个,执行的步骤是按上面的顺序。但步骤8的两个方法是必须选一个的(两个都override是没有意义的)。
这里要说明一下onSubmit()方法和doSubmitAction()方法。在SimpleFormController中,有三种形式的onSubmit方法,它们是:
onSubmit(req, res, command, errs);
onSubmit(command, errs);
onSubmit(command);
但是这三种方法不是孤立的,第一个方法在执行中会调用第二个方法,第二个方法在执行中会调用第三个方法。一般在定义自己的SimpleFormController时只是override onSubmit(command)方法。
doSubmitAction()方法是一个有意思的方法,它的完整定义如下:
protected void doSubmitAction(Object obj) throws Exception |
说了这么多,还是看个实例比较形象(SimpleFormController(中))。
下面是一个SimpleFormController的实例,虽然有些地方显得吹毛求疵,但主要是为了表达一个完整的流程。
首先先看配置文件,web.xml就不说了,下面的是/WEB-INF/mvc-config.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <!--InternalResourceViewResolver--> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/jsp/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> <!--SimpleUrlHandlerMapping--> <bean id="urlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/user.htm">userController</prop> </props> </property> </bean> </beans> |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="userValidator" class="com.yangsq.validator.UserValidator"/> <bean id="userController" class="com.yangsq.controller.UserController"> <property name="commandName"> <value>command</value> </property> <property name="commandClass"> <value>com.yangsq.domain.User</value> </property> <property name="validator"> <ref bean="userValidator" /> </property> <property name="formView"> <value>user</value> </property> <property name="successView"> <value>hello</value> </property> </bean> </beans> |
.../>。validator的设定说明了要使用验证器。formView和successView这两个属性设定了转向的页面,它们是父类所具有的,所以不需要在你的controller中再注入了。
下面是验证器:
import org.springframework.validation.Errors; import org.springframework.validation.Validator; import com.yangsq.domain.User; public class UserValidator implements Validator{ public boolean supports(Class clazz) { return clazz.equals(User.class); } public void validate(Object obj, Errors err) { User user = (User) obj; if (user.getPhone().length() < 7) { user.setCreateTime(null); err.reject("phoneErr", "电话号码位数要大于7"); }else if (user.getAge() <= 0) { user.setCreateTime(null); err.reject("ageErr", "年龄要大于0"); } } } |
下面是表单类:
public class User { private String account; private String phone; private int age; private String city; private Date createTime; public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } } |
public class City { private String cityName; private String cityNo; public String getCityName() { return cityName; } public void setCityName(String cityName) { this.cityName = cityName; } public String getCityNo() { return cityNo; } public void setCityNo(String cityNo) { this.cityNo = cityNo; } } |
public class UserController extends SimpleFormController { protected Map referenceData(HttpServletRequest req) throws Exception { Map map = new HashMap(); List cityList = new ArrayList(); City city1 = new City(); city1.setCityName("BeiJing"); city1.setCityNo("010"); cityList.add(city1); City city2 = new City(); city2.setCityName("ShangHai"); city2.setCityNo("020"); cityList.add(city2); map.put("cityList", cityList); return map; } protected void onBind(HttpServletRequest req, Object obj) throws Exception { User user = (User) obj; //format the infor user.setAccount(user.getAccount().trim()); user.setPhone(user.getPhone().trim()); } protected void onBindAndValidate(HttpServletRequest req, Object obj, BindException err) throws Exception { User user = (User) obj; user.setCreateTime(new Date()); } protected ModelAndView onSubmit(Object obj) throws Exception { User user = (User) obj; return new ModelAndView(this.getSuccessView(), "user", user); } } |
<FORM action="user.htm" method="post"> <TABLE> <TBODY> <TR> <TD> <spring:bind path="command.account"> 用户名:<INPUT name="${status.expression}" type="text" value="${status.value}"/> </spring:bind> </TD> </TR> <TR> <TD> <spring:bind path="command.age"> 年龄:<INPUT name="${status.expression}" type="text" value="${status.value}"/> </spring:bind> </TD> </TR> <TR> <TD> <spring:bind path="command.phone"> 电话号码:<INPUT name="${status.expression}" type="text" value="${status.value}"/> </spring:bind> </TD> </TR> <TR> <TD> <spring:bind path="command.city"> 城市: <SELECT name="${status.expression}"> <c:forEach items="${cityList}" var="city" varStatus="loopStep"> <OPTION value="${city.cityNo}" <c:if test="${city.cityNo == status.value}">selected</c:if>> <c:out value="${city.cityName}"/> </OPTION> </c:forEach> </SELECT> </spring:bind> </TD> </TR> <TR> <TD> <spring:bind path="command.*"> <c:out value="${status.errorMessage}"/> </spring:bind> </TD> </TR> <TR> <TD align="center"> <INPUT type="submit" value="提交" /> </TD> </TR> </TBODY> </TABLE> </FORM> |
<TABLE> <TBODY> <TR> <TD> User infor: </TD> </TR> <TR> <TD> <c:out value="${user.account}" /> </TD> </TR> <TR> <TD> <c:out value="${user.age}" /> </TD> </TR> <TR> <TD> <c:out value="${user.phone}" /> </TD> </TR> <TR> <TD> <c:out value="${user.city}" /> </TD> </TR> <TR> <TD> <c:out value="${user.createTime}" /> </TD> </TR> </TBODY> </TABLE> |
在地址栏中直接输入地址http://localhost:8080/SpringMVC/user.htm(SpringMVC是工程名),会显示如下页面(user.jsp):
在上图框体内填入信息:
修改电话号码:
处理原理:填入信息后点击提交,会以user.htm路径按post方法提交表单。处理流程和上述失败时差不多。只是在执行完onBindAndValidate方法后由于没有了错误,接着执行onSubmit方法。
以上是整个的处理流程。
相关文章推荐
- springMVC3学习--SimpleFormController
- Spring中试用SimpleFormController 完成表单验证
- Spring中的SimpleFormController
- SpringMVC—SimpleFormController的referenceData方法
- SpringMVC SimpleFormController学习备忘
- spring3.0 MVC 继承SimpleFormController不执行onSubmit方法解决办法。
- springMVC3学习(六)--SimpleFormController
- Spring SimpleFormController 工作流程
- springMVC3学习(六)--SimpleFormController
- Spring MVC SimpleFormController
- springMVC3学习(六)--SimpleFormController
- springMVC3学习(六)--SimpleFormController
- springMVC3学习(六)--SimpleFormController
- Spring中的SimpleFormController
- springMVC3学习(六)--SimpleFormController
- 方法对象Spring MVC SimpleFormController
- springMVC3学习(六)--SimpleFormController
- Spring中SimpleFormController & MultiActionController合并
- spring 继承SimpleFormController问题
- Spring学习笔记(十二)----SimpleFormController(上)