Spring中SimpleFormController & MultiActionController合并

来源:互联网 发布:java安装未完成 编辑:程序博客网 时间:2024/05/16 16:47

Spring中SimpleFormController & MultiActionController合并

关键字: Java Spring
SimpleFormController & MultiActionController
 
 
表面看来SimpleFormController用来处理与Form相关的提交,并且无法进行多个提交处理,必须自己判断提交类型。而MultiActionController可以用来处理如同过方法名字区别的不同提交,便于多个相似业务处理集中,但是却无法处理与Form相关的操作,比较遗憾。如果能将二者结合就好了。
下面有两种解决方案:
 
1>     自己定义MultiDispachController extends SimpleFormController;
这样MultiDispachController已经具备处理Form功能,然后自己定义MethodNameResolver,并且在onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException error)
函数中通过MethodNameResolver解析函数名字,并通过反射调用对应函数。
 
优点:可以灵活配置Form
缺点:使用反射,性能有所损失
2>     直接使用MultiActionController实现
通过对MultiActionController源代码观察,发现以下玄机:
在函数派发的时候MultiActionController会调用如下函数:invokeNamedMethod
而此函数中
 
// 如果调用参数大于=3,并且第三个参数为HttpSession
if (method.getParameterTypes().length >= 3 &&method.getParameterTypes()[2].equals(HttpSession.class) )
{
                 HttpSession session = request.getSession(false);
                if (session == null) {
throw new HttpSessionRequiredException("Pre-existing session required for handler method '" + methodName + "'");
              }
                params.add(session);
}
 
// 如果调用参数大于=3,并且第三个参数不是HttpSession,Spring框架默认为一个//Command,并尝试进行Form绑定操作,如下
// If last parameter isn't of HttpSession type, it's a command.
if (method.getParameterTypes().length >= 3 && !method.getParameterTypes()[method.getParameterTypes().length - 1].equals(HttpSession.class))
{
Object command =newCommandObject(method.getParameterTypes()[method.getParameterTypes().length - 1]);
                                                                params.add(command);
                                                                bind(request, command);
}
 
所以基于此隐秘的操作我们可以如下实现,下面是一个简单例子
package com.app.domain;
 
/**
 * @author xh94799
·         一个业务实体包含用户名,密码
 */
public class UserInfo {
 
                private String userName;
                private String password;
               
                public UserInfo()                {}
 
                public String getPassword() {
                                return password;
                }
 
                public void setPassword(String password) {
                                this.password = password;
                }
 
                public String getUserName() {
                                return userName;
                }
 
                public void setUserName(String userName) {
                                this.userName = userName;
                }
}
 
/**
·         一个更详细的业务实体
·         包含用户名,地址,ID 但实际上页面只有用户名密码,此类是用来测试绑定的
 */
package com.app.domain;
 
public class UserDetailInfo {
 
                private String userName;
                private String address;
                private String custID;
               
                public UserDetailInfo() {              super();                // TODO Auto-generated constructor stub }
 
                public String toString() {
                                // TODO Auto-generated method stub
                               
                                StringBuffer sb = new StringBuffer();
                                sb.append("UserName: " + this.userName).append("Add: " + this.address)                               .append("CustID: " + this.custID);
                               
                                return sb.toString();                       
                }
               
                public String getAddress() {
                                return address;
                }
 
                public void setAddress(String address) {
                                this.address = address;
                }
 
 
                public String getCustID() {
                                return custID;
                }
 
                public void setCustID(String custID) {
                                this.custID = custID;
                }
 
                public String getUserName() {
                                return userName;
                }
 
 
                public void setUserName(String userName) {
                                this.userName = userName;
                }
 
}
 
 
下面是我们的Controller
 
package com.app.web.controller;
 
// 处理登陆相关多个业务,从MultiActionController派生
public class LoginController extends MultiActionController {
 
                private static Logger _logger = LogManager.getLogger(LoginController.class);
               
                public LoginController() throws ApplicationContextException {
                                _logger.info("log4j constructor ActionController");
                }
 
                 /**
     *  Init Login Form jsp
     *  处理页面第一次加载显示,根据函数名识别
     */
    public ModelAndView loadLoginView(HttpServletRequest request,
            HttpServletResponse response) throws ServletException {
               
                    _logger.info("log4j loadLoginView init");
               
                return new ModelAndView(ViewConstant.LOGIN_VIEW);
    }
   
 
 
 
 
    /**
·         do Login on user submit 处理登陆校验业务
·         注意第三个参数,为一个Form对象
 
     */
    public ModelAndView doLogin(HttpServletRequest req, HttpServletResponse res,
                                UserInfo cmd ) throws Exception {
                                // TODO Auto-generated method stub
                               
                    _logger.info("LoginController doLogin()");
               
                UserInfo info = cmd;
                if ( cmd != null )
                {
                                    _logger.info("UserName: " + info.getUserName());
                                    _logger.info("Password: " + info.getPassword());
                }
                               
                                return new ModelAndView(ViewConstant.LOGIN_VIEW);
                }
   
   
   
    /**
·         do Login on user submit  处理登陆细节业务,
·         注意第三个参数,为一个Form对象
·         此处真正的FormUserInfo,这里用作测试
     */
    public ModelAndView doDetailProcess(HttpServletRequest req, HttpServletResponse res,
                                UserDetailInfo cmd ) throws Exception {
               
                    _logger.info("LoginController doDetailProcess()");
                    UserDetailInfo info = cmd;
               
                    if( info != null )
                {
                                _logger.info(info.toString());
                }
               
                return new ModelAndView(ViewConstant.LOGIN_VIEW);
    }
   
   
    //可以自定义注册绑定
    protected void initBinder(ServletRequest arg0, ServletRequestDataBinder arg1) throws Exception {
                // TODO Auto-generated method stub
                    super.initBinder(arg0, arg1);
 
                SimpleDateFormat dateFormat = new SimpleDateFormat(Constant.DATE_FORMAT);
                dateFormat.setLenient(false);
                  binder.registerCustomEditor(Date.class, null, new CustomDateEditor(dateFormat, false));
}
}
 
 
Action配置
 
<beanid="urlMapping"class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
     <property name="mappings">
     <props>
       <prop key="/login.htm" >LoginController</prop>
       <prop key="/doLogin.htm">LoginController</prop>
       <prop key="/doDetailProcess.htm">LoginController</prop>
     </props>
     </property>
</bean>
      
 
<bean id="LoginController" class="com.app.web.controller.LoginController" abstract="false" singleton="true">
     <property name="methodNameResolver">
     <bean class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
     <property name="mappings">
     <props>
       <prop key="/login.htm">loadLoginView</prop>
       <prop key="/doLogin.htm">doLogin</prop>                                         
       <prop key="/doDetailProcess.htm">doDetailProcess</prop>
    </props>
    </property>
    </bean>
 </property>
</bean>
 
JSP页面
<form name="loginFrm" action=<c:urlvalue="/servlet/doLogin.htm"/>method="post">
<p align="center">Login</p>
<br>
 UserName:<input type="text" name="userName">
<br>
              Password:<input type="password" name="password">
              <br>
              <p>
              <input type="submit" value="Submit" name="btnLogin">
              <input type="reset" value="Reset" name="btnReset">
              <input type="submit" value="DetailSubmit" name="btnDetail" onclick="doSubmit'<c:urlvalue='/servlet/doDetailProcess.htm'/>')">
              </p>
       </form