打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
SpringMVC学习笔记(二)

最近在学习SpringMVC,想写点东西记录以备查阅,感觉还少点什么,迟迟未动手;今天看到这位仁兄的Blog:http://86asm.iteye.com/blog/932564写的挺好,于是在他的基础上添加些自己的东西;

如果这位仁兄有异议,告知 必删之!

 

比较常用的Contoller

1、直接实现Controller 接口或继承AbstractController抽象类
2、用于直接跳转页面的
      ParameterizableViewController, UrlFilenameViewController
3、能封装表单参数的CommondController、 FormController
4、在同一控制器类中处理多个请求的MultiActionController.
     具体调用的方法通过MethodNameResolver决定
        (InternalPathMethodResolver, ParameterMethodNameResolver, PropertiesMethodResolver)
     方法签名:
        public (ModelAndView | Map | String | void) actionName(HttpServletRequest request,HttpServletResponse response, [,HttpSession] [,AnyObject]);

 

1. 概述SpringMVC 后端控制器

 

为了方便开发人员快捷地建立适合特定应用的后端控制器,springMVC 实现Controller 接口,自定义了许多特定控制器。这些控制器的层次关系如下:
---AbstractController
---AbstractUrlViewController
 ---UrlFilenameViewController
----BaseCommandController
   ---AbstractCommandController
   ---AbstractFormController
---AbstractWizardFormController
---SimpleFormController
   ---CancellableFormController
---MultiActionController
---ParameterizableViewController
 ---ServletForwardingController
---ServletWrappingController


AbstractController提供了一个最顶层的Controller模板,用来完成一些基本的任务。AbstractController可以注入以下属性。

 

(1)supportedMethods:设定允许的HTTP请求方式,默认为GET和POST。如果需要PUT、HEAD之类的请求,则需要覆盖默认的设定,不过,通常不需要设定其他HTTP请求方式。

 

(2)requireSession:设定是否需要Session支持,默认为false。如果设定为true,则要求当前请求必须和Session关联,这样可以保证子类在任何时候调用request.getSession()时不会得到null。

 

(3)cacheSeconds:设定HTTP响应头的缓存,默认值为-1,表示不添加任何缓存指令到HTTP响应头;如果设为0,表示完全不缓存;如果设为大于0,表示应当缓存的秒数。

 

(4)synchronizeOnSession:表示来自同一用户的请求是否能并行处理,默认值为false,表示允许同一用户同时向服务器发送多个请求。如果设定为true,则同一用户的请求只能被依次处理,这个设置可以有效控制同一用户对服务器的并发请求,例如,禁止使用多线程下载由Controller生成的文件。

 

由于AbstractController位于Controller继承体系的上端,其他子类也可以非常方便地设定上述属性。

 

 

下面重点分析两个特色控制器:


2.SimpleFormController 控制器

 

   在正式开发前,请先熟悉上前面的HelloWord 实例。在保证熟悉前一个实例后,我们将在此基础上进行改进。

SimpleFormController可以自动将用户从表单获取的参数存入一个JavaBean的实例中,这样就不用逐一调用request.getAttribute()方法去获取。


步骤一 :建立后端控制器RegController.java 代码如下:

Java代码  
  1. <span>package com.wy.controller;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4. import javax.servlet.http.HttpServletResponse;  
  5.   
  6. import org.springframework.validation.BindException;  
  7. import org.springframework.web.servlet.ModelAndView;  
  8. import org.springframework.web.servlet.mvc.SimpleFormController;  
  9.   
  10. import com.wy.pojo.User;  
  11.   
  12. public class RegController extends SimpleFormController {  
  13.     @SuppressWarnings("deprecation")  
  14.     /** 
  15.      * 也可以在springmvc-servlet.xml中绑定User 
  16.      * <property name="commandClass" value="com.wy.pojo.User"/> 
  17.      */  
  18.     public RegController() {  
  19.         setCommandClass(User.class);  
  20.     }  
  21.   
  22.     protected ModelAndView processFormSubmission(HttpServletRequest arg0,  
  23.             HttpServletResponse arg1, Object commandClass, BindException arg3)  
  24.             throws Exception {  
  25.         User user = (User) commandClass;  
  26.         ModelAndView mav = new ModelAndView("hello");  
  27.         mav.addObject("msg", "Hello World!");  
  28.         mav.addObject("user", user);  
  29.         return mav;  
  30.     }  
  31.   
  32. }  
  33. </span>  

 

  User.java ,代码如下:

Java代码  
  1. <span>package com.wy.pojo;  
  2.   
  3. public class User {  
  4.     private String username;  
  5.     private int age;  
  6.   
  7.     public String getUsername() {  
  8.         return username;  
  9.     }  
  10.   
  11.     public void setUsername(String username) {  
  12.         this.username = username;  
  13.     }  
  14.   
  15.     public int getAge() {  
  16.         return age;  
  17.     }  
  18.   
  19.     public void setAge(int age) {  
  20.         this.age = age;  
  21.     }  
  22.   
  23. }  
  24. </span>  

 

简要说明 :如果熟悉struts1.x 相信很容易理解Object formbean 参数,其实它就是和表单属性打交道的一个对象,也即是说表单参数会依据一定的规则填充给formbean 对象。在struts1.x 中,如果像把这种与formbean 转换成User 对象,必须要求User 继承自 ActionForm 类, 这样才能把一个表单参数转换成一个具体的formbean 对象(所谓具体实质是指参数formbean 对象已经能成功地赋值给User 对象)并与相应的Action 绑定 。


但 springmvc 并不要求这种User 一定要继承某个类,既然springmvc 对这种User 没有要求,那表单参数是怎样与User 进行完美匹配的,注意在RegControl ler构造方法中有如下一句代码: setCommandClass(User. class ); 这句代码就指明了此控制器绑定User 类来和表单进行匹配。如果想验证此句代码的作用,可以注释掉这句代码并查看异常。后面将会分析这种控制器的一个执行过程(包括表单填充及验证过程)


 

概述此步要点:

     (1 )继承 SimpleFormController

     (2 )构造器中调用 setCommandClass 方法绑定定命令对象(这里为User 类)

     (3 )转换formbean 为User 类进行业务逻辑操作


 

 

步骤二 :配置spmvc-servlet.xml 文件,代码如下:

Xml代码  
  1. <span><!-- URL Mapping -->  
  2.     <bean id="simpleUrlHandlerMapping"  
  3.         class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
  4.         <property name="mappings">  
  5.             <props>  
  6.                 <prop key="/helloWorld.do">helloController</prop>  
  7.                 <prop key="/reg.do">regController</prop>  
  8.             </props>  
  9.         </property>  
  10.     </bean>  
  11.     <bean id="helloController" class="com.wy.controller.HelloWorldController"></bean>  
  12.     <bean id="regController" class="com.wy.controller.RegController">  
  13.        <!--  
  14.         <property name="commandClass" value="com.wy.pojo.User"/> 
  15.          -->  
  16.     </bean></span>  

 

步骤三 :根据配置文件完善相应页面
在index.jsp 设定表单填写页面,主要代码如下:

 

   < form action = "<%= request.getContextPath() %> /reg.do " method = "post" >

 

    用户名: < input type = "text" name = "username" >< br />

 

    年龄: < input type = "text" name = "age" >< br />

 

    < input type = "submit" >

 

    </ form >
/page/hello.jsp ,主要代码如下:
< body >

 

    世界,你好! (WEB-INF/page)

 

    用户名: ${user.username }

 

    年龄: ${user.age }

 

</ body >

 

步骤四 :启动服务器,访问到首页,填写表单完成测试。


在RegController.java 中增加如下代码:

Java代码  
  1. <span>protected Object formBackingObject(HttpServletRequest request) throws Exception {  
  2.         System.out.println("formBackingObject方法执行-->01");  
  3.         setCommandClass(User.class); //也可在此处调用setCommandClass方法  
  4.         return super.formBackingObject(request);  
  5.     }  
  6.   
  7.     protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {  
  8.         System.out.println("initBinder方法执行-->02");  
  9.         super.initBinder(request, binder);  
  10.     }  
  11.       
  12.     protected void onBind(HttpServletRequest request, Object command) throws Exception {  
  13.         System.out.println("onBind方法执行-->03");  
  14.         super.onBind(request, command);  
  15.     }  
  16.       
  17.     protected void onBindAndValidate(HttpServletRequest request, Object command, BindException errors)  
  18.             throws Exception {  
  19.         System.out.println("onBindAndValidate方法执行-->04");  
  20.         super.onBindAndValidate(request, command, errors);  
  21.     }</span>  

 

下面简要分析执行过程:
(1 ). 当前端控制器把请求转交给此此控制器后,会首先调用 formBackingObject 方法,此方法的作用就是根据绑定的Command Class 来创建一个Command 对象,因此除了可以在构造方法中调用setCommandClass 方法,也可以在此处调用setCommandClass 方法。其实创建这个Command 对象很简单,spring 通过如下代码完成:

 

BeanUtils.instantiateClass ( this . commandClass );

 

由于在此处必须根据 commandClass 来完成Command 对象的创建,因此在此方法调用前应保证commandClass 设置完成,所以我们可以在 formBackingObject 方法 和构造方法中完成commandClass 的设置。

 

(2 ). 调用 initBinder 方法,初始化Command 对象,即把表单参数与Command 字段按名称进行匹配赋值。

 

(3 ). 调用 onBind 方法,把Command 对象和后端控制器绑定。

 

(4 ). 调用 onBindAndValidate 方法,验证用户输入的数据是否合法。如果验证失败,我们可以通过修改errors 参数,即新的errors 对象将会绑定到ModelAndView 上并重新回到表单填写页面。

 

(5). 执行 processFormSubmission 方法,主要操作就是把绑定的Command 对象转换成一个User 这样的表单对象,并调用业务逻辑方法操作User 对象,根据不同的逻辑返回不同的ModelAndView 对象。


3.MultiActionController 控制器

  

此控制器 来将多个请求处理方法合并在一个控制器里,这样可以把相关功能组合在一起(它和struts1.x 中的 DispatchAction 极为相似 )。下面通过实例演示此控制器的使用。

 

步骤一 : 建立后端控制器 UserManagerController.java , 代码如下:

 

Java代码  
  1. <span>package com.wy.controller;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4. import javax.servlet.http.HttpServletResponse;  
  5.   
  6. import org.springframework.web.servlet.ModelAndView;  
  7. import org.springframework.web.servlet.mvc.multiaction.MultiActionController;  
  8.   
  9. public class UserManagerController extends MultiActionController {  
  10.     public ModelAndView list(HttpServletRequest request,  
  11.             HttpServletResponse response) {  
  12.         ModelAndView mav = new ModelAndView("list");  
  13.         return mav;  
  14.     }  
  15.   
  16.     public ModelAndView add(HttpServletRequest request,  
  17.             HttpServletResponse response) {  
  18.         ModelAndView mav = new ModelAndView("add");  
  19.         return mav;  
  20.     }  
  21.   
  22.     public ModelAndView edit(HttpServletRequest request,  
  23.             HttpServletResponse response) {  
  24.         ModelAndView mav = new ModelAndView("edit");  
  25.         return mav;  
  26.     }  
  27.   
  28. }  
  29. </span>  

 

步骤二 :配置web.xml (参前面实例),并在spmvc-servlet.xml 中增加如下配置:

Xml代码  
  1. <span><bean id="springMethodNameResolver"        class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">  
  2.         <property name="mappings">  
  3.             <props>  
  4.                 <prop key="/list.do">list</prop>  
  5.                 <prop key="/add.do">add</prop>  
  6.                 <prop key="/edit.do">edit</prop>  
  7.             </props>  
  8.         </property>  
  9.     </bean>  
  10.   
  11.     <bean id="userManagerController" class="com.asm.UserManagerController">  
  12.         <property name="methodNameResolver"  
  13.             ref="springMethodNameResolver">  
  14.         </property>  
  15.     </bean></span>  

 

说明 methodNameResolver 负责从请求中解析出需要调用的方法名称。 Spring 本身已经提供了一系列 MethodNameResolver 的实现,当然也可以编写自己的实现。在这里我们使用了 Pro p方式来解析,具体表现如下:

 

< prop key = "/list.do" > list </ prop > 请求 list.do 时调用 list 方法

 

< prop key = "/add.do" > add </ prop >   请求为 add.do 时调用 add 方法

 

< prop key = "/edit.do" > edit </ prop 请求为 edit.do 时调用 edit 方法
然后通过把 springMethodNameResolver 解析器注入给 UserManagerController methodNameResolver ,这样配置后才完成了一个真正的具有请求转发能力的 MultiActionController 控制器对象—— UserManagerController


强调 :此步骤实质完成了一个工作:就是为 UserManagerController 控制器配置一个方法解析器。


 

步骤三 :配置请求转发的访问路径,在spmvc-servlet.xml 中添加如下代码

Xml代码  
  1. <span><bean id="simpleUrlHandlerMapping"     class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
  2.         <property name="mappings">  
  3.             <props>                 
  4.                 <prop key="/list.do">userManagerController</prop>  
  5.                 <prop key="/add.do">userManagerController</prop>  
  6.                 <prop key="/edit.do">userManagerController</prop>  
  7.             </props>  
  8.         </property>  
  9.     </bean></span>  

 

步骤四 :根据配置文件,完善jsp 页面编写。

 

page/list.jsp ,代码如下:

 

< body >

 

    用户列表页面

 

</ body >

 

page/add.jsp ,代码如下:

 

< body >

 

    用户添加页面

 

</ body >

 

page/edi.jsp ,代码如下:

 

< body >

 

    用户修改页面

 

</ body >

 

步骤五 :启动服务器,访问 …/list.do 将调用到 list 方法并转向到 list.jsp 页面。


补充:细说MethodNameResolver解析器


InternalPathMethodNameResolver:默认MethodNameResolver解析器从请求路径中获取文件名作为方法名 比如,…/list.do的请求会调用list(HttpServletRequest,HttpServletResponse)方法。


 

ParameterMethodNameResolver:解析请求参数,并将它作为方法名。 比如,对应…/userManager.do?method=add的请求,会调用 add(HttpServletRequest, HttpServletResponse)方法。使用paramName属性定义要使用的请求参数名称。

 

PropertiesMethodNameResolver :使用用户自定义的属性(Properties)对象,将请求的URL映射 到方法名,具体可以参见实例。

 

使用ParameterMethodNameResolver作为MethodNameResolver的解析器时,主要配置代码如下:

Xml代码  
  1. <span><bean id="simpleUrlHandlerMapping"     class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">  
  2.         <property name="mappings">  
  3.             <props>  
  4.                 <prop key="/user.do">userManagerController</prop>  
  5.             </props>  
  6.         </property>  
  7.     </bean>  
  8.   
  9.     <bean id="ParameterMethodNameResolver"       class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">  
  10.         <property name="paramName" value="crud"></property>  
  11.     </bean>  
  12.   
  13.     <bean id="userManagerController"  
  14.         class="com.asm.UserManagerController">  
  15.         <property name="methodNameResolver"  
  16.             ref="ParameterMethodNameResolver">  
  17.         </property>  
  18.     </bean></span>  

 


  

访问路径 为…/user.do?crud=list(add|edit)


 

小结:

         prefix和suffix将和逻辑视图名称一起组合成为实际视图的路径。例如,对于上例,若返回一个new ModelAndView("test", model),则实际的视图路径由prefix+逻辑视图名+suffix这3部分构成。

      

 

        /WEB-INF/page/test.jsp


 

    定义前缀(prefix)使得视图文件无论放在何处都可以通过修改前缀来实现位置无关性(当然,必须在web目录内),许多应用程序将其放在/WEB- INF 目录下,使得用户无法通过URL直接访问视图文件以保证视图文件的安全;

    定义后缀(suffix)可以在将来用另一种视图技术(例如,Velocity)取代现在的JSP视图,只需将后缀从“.jsp”更改为“.vm”即可,而不必更改源代码中的逻辑视图名。

    总之,一切目标都是为了实现最大限度的解耦。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
spring系列教程之web框架(转) - Hibernate - LUPA开源社区
【框架】126:springMVC框架初体验
springMVC对异常处理的支持
学习SpringMVC系列教程(一)Spring MVC入门
用struts framework开发应用程序
第四章 Controller接口控制器详解(2)——跟着开涛学SpringMVC
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服