Spring 框架——spring MVC框架应用全解

一、入门内容

1、运行原理图

 对比:Struts2执行流程

 strutsPrepareAndExcuteFilter拦截请求(控制层),拦截请求,转发请求

 寻找Action执行

 ActionProxy:strutsActionProxy extends defaultActionProxy

 ActionMapping去寻找执行类Action

2、与struts2的对比

  • 实现机制:Springmvc基于servlet实现。Servlet比过滤器快。Struts2是基于过滤器实现的。
  • 运行速度:Struts2是多例,请求来了以后,struts2创建多少个对象;Springmvc是单例。
  • 参数封装来分析:Struts基于属性进行封装。Springmvc基于方法封装。

3、入门案例

1.需要的jar包

        因为springmvc是spring的一部分,故jar包和之前的相同,只是要加一个jar:spring-webmvc-3.2.0.RELEASE.jar

2.程序编写

        首先要在在web.xml中配置前端控制器:DispatcherServlet

<servlet>
     <servlet-name>springmvc</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
     <servlet-name>springmvc</servlet-name>
     <url-pattern>*.do</url-pattern>
</servlet-mapping>

然后编写一个controller(类似struts2中的action):

public class MyController implements Controller{
	public ModelAndView handleRequest(HttpServletRequest arg0,
			HttpServletResponse arg1) throws Exception {
		// 接受请求,接受参数,验证参数
		//封装参数,调用业务方法
		//返回视图
		ModelAndView mv = new ModelAndView();
		//设置页面回显数据,键值对
		mv.addObject("hello", "欢迎学习springmvc!");
		
		//指定跳转的视图
		//返回物理视图
		//mv.setViewName("/WEB-INF/jsps/index.jsp");
		//返回逻辑视图
		mv.setViewName("index");
		
		return mv;
	}
}

 之后在spring配置文件中(这里为springmvc.xml)首先要引入新的命名空间,如下:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"<!--这里-->
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/mvc<!--这里--> 
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd ><!--这里-->

然后就可以在spring配置文件中配置如下:

<!-- 配置处理器映射器,springmvc默认的处理器映射器
BeanNameUrlHandlerMapping:根据bean(自定义Controler)的name属性的url去寻找hanler(Action:Controller)
 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
	 	
<!-- 配置处理器适配器执行Controlelr ,springmvc默认的
SimpleControllerHandlerAdapter:执行Controller
-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 配置自定义Controler -->
<bean name="/hello.do" class="cn.itcast.controller.MyController"></bean>

说明:即通过url为.../hello.do来访问该controller,如果在上面的controller类中返回的是物理视图,就可直接跳到index页面中,如果返回的是逻辑视图,还需要配置如下部分:

<!-- 配置sprigmvc视图解析器:解析逻辑试图 	 后台返回逻辑试图:index
	视图解析器解析出真正物理视图:前缀+逻辑试图+后缀====/WEB-INF/jsps/index.jsp
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/WEB-INF/jsps/"></property>
	<property name="suffix" value=".jsp"></property>		
</bean>

配置完如上部分后,还需要在web.xml文件中将该配置文件加载进去:

<servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--加载-->
       <init-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>classpath:springmvc.xml</param-value>   
       </init-param>
  </servlet>

说明: 配置文件也可以默认加载,但必须满足如下规范:

  • 文件命名:servlet-name-servlet.xml,这里的(web.xml)名为springmvc,故配置文件名应为springmvc-servlet.xml
  • 路径规范:必须在WEB-INF目录下面

最后在index中便可通过${hello}来取值。

二、语法详情

1、处理器映射器

        就是将从浏览器发送过来的url地址进行处理,将url和controller对应起来,但是还未执行controller。

1.BeanNameUrlHandlerMapping

       根据url请求去匹配bean的name属性url,从而获取Controller,如下:

<!-- 配置处理器映射器,springmvc默认的处理器映射器
BeanNameUrlHandlerMapping:根据bean(自定义Controler)的name属性的url去寻找hanler(Action:Controller)
 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 配置自定义Controler -->
<bean name="/hello.do" class="cn.itcast.controller.MyController"></bean>

只需要访问http:..../hello.do即可。

2.SimpleUrlHandlerMaping

       根据浏览器url匹配简单url的key,key又通过Controller的id找到Controller,如下:

<!-- 简单处理器映射器:把Url进行集中配置-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
         <props>
		     <prop key="/abc.do">myController</prop>
		     <prop key="/ss.do">***</prop>
		     <prop key="/mine.do">***</prop>
		 </props>
    </property>
</bean>
<!-- 配置自定义Controler -->
<bean id="myController" class="cn.itcast.controller.MyController"></bean>

在上述配置中,如果访问.../abc.do将会访问自定义的controller

3.ControllerClassNameHandlerMapping

       根据类名(MyController)类名.do来访问,类名首字母小写,如下:

<!-- 定义通过: 类名.do 形式来访问controller -->
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"></bean>
<!-- 配置自定义Controler -->
<bean  class="cn.itcast.controller.MyController"></bean>

在上述配置中只要访问..../myController(就是自定义的controller的类名的首字母小写),即可访问自定义的MyController

注意:3个处理器映射器是可以共存的

2、处理器适配器

        用来执行相应的controller的。处理器适配器的类型与自定义controller时所实现的接口是对应的,每一种适配器处理一种实现特定接口的controller。

1.SimpleControllerHandlerAdapter

  controller需要实现的接口为Controller,返回modelAndView,如下:

controller中

public class MyController implements Controller{
	public ModelAndView handleRequest(HttpServletRequest arg0,
			HttpServletResponse arg1) throws Exception {
		ModelAndView mv = new ModelAndView();
		mv.addObject("hello", "欢迎学习springmvc!");
		//指定跳转的视图
		//返回物理视图
		//mv.setViewName("/WEB-INF/jsps/index.jsp");
		//返回逻辑视图
		mv.setViewName("index");
		return mv;
	}
}

配置中

<!-- 配置处理器适配器执行Controlelr ,springmvc默认的-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>

2.HttpRequestHandlerAdapter

      controller需要实现的接口为HttpRequestHandler,无返回值,如下:

controller中

public class HttpController implements HttpRequestHandler{
	public void handleRequest(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//给Request设置值,在页面进行回显
		request.setAttribute("hello", "这是HttpRequestHandler!");
		//跳转页面
		request.getRequestDispatcher("/WEB-INF/jsps/index.jsp").forward(request, response);
	}
}

注意:因为无返回值,故在跳转页面时只能是物理视图,不能是逻辑视图。

配置中

<!-- HttpRequestHandlerAdapter负责执行实现接口HttpRequestHandler的后端控制器。-->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean>

注意:2个处理器适配器可以共存

3、注解的使用

如果使用注解开发,那么再spring配置文件中要有如下配置:

<context:component-scan base-package="cn.itcast"></context:component-scan>
		
<!-- 配置注解处理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
		
<!-- 配置注解处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
		
<!-- 配置sprigmvc视图解析器:解析逻辑试图 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
   <property name="prefix" value="/WEB-INF/jsps/"></property>
   <property name="suffix" value=".jsp"></property>		
</bean>

注意:可以使用如下配置

<mvc:annotation-driven/>

来替代注解处理器和适配器,并且还自动支持json格式数据。但是注意此时(使用json格式数据)在javaBean中不能添加@XmlRootElement(提供对xml视图支持)。

然后自定义的Controller类可以使用注解来开发,举例如下:

@Controller//相对应<bean class="UserController"/>
public class UserController {
	@RequestMapping("hello.do")//相对于<bean name="/hello.do" class="..."></bean>
	public String hello(){
		return "index";//跳转到index.jsp
	}
}

注意:

1.requestMapping可以写为:

  • requestMapping(“hello”)
  • requestMapping(“/hello.do”)
  • requestMapping(value=”/hello.do”)
  • requestMapping(value=”/hello.do”,method=RequestMethod.GET)//指定只接受get请求
  • requestMapping(value=”/hello.do”,method={RequestMethod.POST, RequestMethod.GET})//get和post请求都可以

2.RequestMaping设置根路径:

@Controller//相对应<bean class="UserController"/>
@RequestMapping("/user")//这里
public class UserController {
	@RequestMapping("hello.do")
	public String hello(){
		return "index";
	}
}

之后再访问需要.../user/hello.do来访问hello方法

在接收参数时可以使用@RequestParam注解,如:

//接受int类型参数
@RequestMapping("recieveInt")
public String recieveInt(@RequestParam(defaultValue="2",value="ss",required=true) Integer id){		
	System.out.println(id);
	return "success";
}

那么在表单中:

<form action="${pageContext.request.contextPath }/user/recieveInt.do" method="post">
   ID:<input type="text" name="ss" id="id">
   <input type="submit" value="提交">
</form>

注意:name的值与controller中的value对应,如果没有传递的值默认值为2,required设置为true表示必须传递值,否则报错。

三、参数的接收与封装

1、参数的接收

        与Struts2的参数基于属性封装不同,Springmvc参数的封装是基于方法进行封装的。

1.接收int型参数

        首先在页面中:

<form action="${pageContext.request.contextPath }/user/recieveInt.do" method="post">
   ID:<input type="text" name="id" id="id">
   <input type="submit" value="提交">
</form>

那么在controller中:

//接受int类型参数
@RequestMapping("recieveInt")
public String recieveInt(Integer id){
	System.out.println(id);
	return "success";
}

注意:在方法中的参数名要与表单中提交过来的方法名一致。

2.接收String型参数

        首先在页面中:

<form action="${pageContext.request.contextPath }/user/recieveStr.do" method="post">
   姓名:<input type="text" name="username" id="username">
   <input type="submit" value="提交">
</form>

那么在controller中:

//接受字符类型参数
@RequestMapping("recieveStr")
public String recieveStr(String username)
{
	System.out.println(username);
	return "success";
}

3.接收数组型参数

        首先在页面中:

<form action="${pageContext.request.contextPath }/user/recieveArray.do" method="post">
   ID:<input type="checkbox" name="ids" value="1" id="ids">
   ID:<input type="checkbox" name="ids" value="2" id="ids">
   ID:<input type="checkbox" name="ids" value="3" id="ids">
   <input type="submit" value="提交">
</form>

那么在controller中:

//接受数组类型参数
@RequestMapping("recieveArray")
public String recieveArray(Integer[] ids){	
	System.out.println(ids);
	return "success";
}

4.接收bean型参数

        首先在页面中:

<form action="${pageContext.request.contextPath }/user/recieveUser.do" method="post">
   姓名:<input type="text" name="username" id="username">
   生日:<input type="text" name="birthday" id="birthday">
   性别:<input type="text" name="sex" id="sex">
   地址:<input type="text" name="address" id="address">
   <input type="submit" value="提交">
</form>

那么在controller中:

//接受参数封装User对象
@RequestMapping("recieveUser")
public String recieveUser(User user){		
	System.out.println(user);	
	return "success";
}

注意:这里的表单中提交过来的数据的name要与user bean中属性名相同

5.接收包装型参数

首先包装类如下:

public class UserCustom {
	private User user;
        //get set
}

然后在页面中:

<form action="${pageContext.request.contextPath }/user/recieveUserCustom.do" method="post">
    姓名:<input type="text" name="user.username" id="username">
   生日:<input type="text" name="user.birthday" id="birthday">
   性别:<input type="text" name="user.sex" id="sex">
   地址:<input type="text" name="user.address" id="address">
   <input type="submit" value="提交">
</form>

那么在controller中:

//接受包装类型参数
@RequestMapping("recieveUserCustom")
public String recieveUserCustom(UserCustom usercustom){
	System.out.println(userCustom);
	return "success";
}

注意:表单数据的名称

6.接收集合型参数

        因为在方法中参数不能是集合,故想要接收集合类型参数需要通过包装类来完成。

1.接收List类型参数

首先其包装类如下:

public class UserCustom {
	private List<User> userList;
	//set get
}

然后在页面中:

<form action="${pageContext.request.contextPath }/user/recieveList.do" method="post">
姓名:<input type="text" name="userList[0].username" id="username">
地址:<input type="text" name="userList[0].address" id="address">
姓名:<input type="text" name="userList[1].username" id="username">
地址:<input type="text" name="userList[1].address" id="address">
<input type="submit" value="提交">
</form>

那么在controller中:

//接受集合类型参数
@RequestMapping("recieveList")
public String recieveList(UserCustom userCustom){	
	System.out.println(userCustom);
	return "success";
}

2.接收Map类型参数

首先其包装类如下:

public class UserCustom {
	private Map<String,Object> maps = new HashMap<String, Object>();
        //get set
}

然后在页面中:

<form action="${pageContext.request.contextPath }/user/recieveMap.do" method="post">
姓名:<input type="text" name="maps['username']" id="username">
地址:<input type="text" name="maps['address']" id="address">
<input type="submit" value="提交">
</form>

那么在controller中:

//接受集合类型参数
@RequestMapping("recieveMap")
public String recieveMap(UserCustom userCustom){		
	System.out.println(userCustom);
	return "success";
}

2、参数的封装

       Springmvc通过命令设计模式接受页面参数。现在实现将from表单中的数据封装到bean中,首先先有一个user bean:

public class User {
	private Integer id;
	private String username;
	private Date birthday;
	private String sex;
	private String address;
        //get and set
}

然后创建一个controller,通过它来跳转到form表单页面:

public class ToAddController implements Controller{
	public ModelAndView handleRequest(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		ModelAndView mv = new ModelAndView();
		//调转到add添加页面视图
		mv.setViewName("add");
		return mv;
	}
}

它在配置文件中的主要配置如下:

<bean name="/toAdd.do" class="cn.itcast.controller.ToAddController"></bean>

那么这时访问.../toAdd.do将会执行该controller,然后通过它跳到下面的jsp中:

<form action="${pageContext.request.contextPath }/command.do" method="post">
       姓名:<input type="text" name="username" id="username">
       生日:<input type="text" name="birthday" id="birthday">
       性别:<input type="text" name="sex" id="sex">
       地址:<input type="text" name="address" id="address">
       <input type="submit" value="提交">
</form>

提交的url(...command.do)在spring配置中:

<bean name="/command.do" class="cn.itcast.controller.CommandController"></bean>

即,将由CommandController来处理:

public class CommandController extends AbstractCommandController{
	//指定参数绑定到那个javaBean
	public CommandController(){
		this.setCommandClass(User.class);
	}
	@Override
	protected ModelAndView handle(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException errors)
			throws Exception {
		//把命令对象强转成User对象
		User user = (User) command;
		ModelAndView mv = new ModelAndView();
		mv.addObject("user", user);	
		mv.setViewName("index");		
		return mv;
	}
}

这时将跳转到index 页面,来显示user的信息:

<body>
${user.username } <br>
${user.birthday } <br>
${user.sex } <br>
${user.address } <br>
</body>

注意:可能出现的问题

问题1:中文乱码

  • Get请求乱码

  • post请求乱码

通过配置Spring编码过滤器来解决,在web.xml中配置:

<filter>
   <filter-name>characterEncoding</filter-name>
   <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
   <init-param>
       <param-name>encoding</param-name>
       <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
   <filter-name>characterEncoding</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

问题2:日期格式的转换

       如上例子中如果在日期栏中添加的是:2016/10/4 这样的格式的话date是可以提交上去的(默认,与系统格式一致),但是如果是:2016-10-4等,提交上去的将会为null,在CommandController中再添加方法initBinder(自动执行),可以转换日期格式:

public class CommandController extends AbstractCommandController{
	public CommandController(){		
	}
	//。。。。。。
	@Override
	protected void initBinder(HttpServletRequest request,
			ServletRequestDataBinder binder) throws Exception {
		String str = request.getParameter("birthday");
		if(str.contains("/")){
			binder.registerCustomEditor(Date.class, 
					new CustomDateEditor(new SimpleDateFormat("yyyy/MM/dd"), true));
		}else{
			binder.registerCustomEditor(Date.class, 
					new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));	
		}
	}
}

四、页面的回显

        在spring mvc中通过model来实现页面中数据的回显,相当于application域对象。下面以显示集合对象中的数据为例说明:

首先在controller中添加要显示在页面中的数据:

@RequestMapping("list")
public String list(Model model){
	List<User> userList = new ArrayList<User>();
		
	User user1 = new User();
	user1.setId(1);
	user1.setSex("男");
	user1.setUsername("张山峰");
	user1.setAddress("武当山");
	user1.setBirthday(new Date());
		
	User user2 = new User();
    User user3 = new User();
        //。。。			
	userList.add(user1);
	userList.add(user2);
	userList.add(user3);
	
	model.addAttribute("userList", userList);//将该对象放到model中
	return "list";
}

之后在页面中取出:

<table border="1" style="color: blue">
   <tr>
       <td>姓名</td>
       <td>生日</td>
       <td>性别</td>
       <td>地址</td>
       <td>操作</td>
   </tr>
   <c:forEach items="${userList}" var="user">
   <tr>
      <td>${user.username }</td>
      <td>${user.birthday }</td>
      <td>${user.sex }</td>
      <td>${user.address }</td>
      <td>
          <a href="${pageContext.request.contextPath }/rest/user/updateByID.do?id=${user.id }">修改</a>
       </td>
   </tr>
   </c:forEach>
</table>

附加:如果点击修改后的实现:

//修改
@RequestMapping("updateByID")
public String updateByID(Integer id,Model model){
	User user1 = new User();
	user1.setId(id);
    //。。。。	
	model.addAttribute("user", user1);
	return "edit";
}

五、其它

1、URL模版映射

        在spring mvc 中url 格式为...controller.do?参数,这不符合restfull软件架构(无扩展名,无参数)。为了实现Restfull风格设计可以进行如下修改:

首先假如有如下url请求:

<a href="${pageContext.request.contextPath }/rest/user/updateByID.do?id=${user.id }">

而处理的controller为:

@RequestMapping("updateByID")
public String updateByID(Integer id){
      //。。。。
}

想去掉后面根加的请求参数可以将其写为:

<a href="${pageContext.request.contextPath }/user/updateByID/${user.id }.do">

并且在controller中修改为:

@RequestMapping("updateByID/{id}")
public String updateByID(@PathVariable Integer id){
      //。。。。		
}

而想去掉.do扩展名,则可以在web.xml中配置的url拦截改为:

  <servlet-mapping>
  <servlet-name>springmvc</servlet-name>
  <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  
  <servlet-mapping>
  <servlet-name>springmvc</servlet-name>
  <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>

注意:第二个映射的rest是默认的。

此时url访问将变为:

<a href="${pageContext.request.contextPath }/rest/user/updateByID/${user.id }"

2、转发和重定向

1.转发(forward)

在本类(同一个controller中方法与方法之间进行转发)进行转发:

@RequestMapping("forward")
public String forward(){	
	return "forward:list.do";
}

在不同类中进行转发:

@RequestMapping("forward")
public String forward(){		
	return "forward:/items/list.do";
}

2.重定向(redirect)

@RequestMapping("redirect")
public String redirect(){		
	return "redirect:/items/list.do";
}

3、整合JSON数据

 首先需要在处理器适配器中进行如下配置:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"</bean>
    </property>
</bean>

 或者如前面注解中的

1.接收json数据,输出json数据

    接收后转为pojo,然后将pojo输出为json格式,首先在页面中:

function requestJson(){
    //模拟json格式数据
    var jsonObj=JSON.stringify({"username":"小明","sex":"男","address":“”河南});
    $.ajax({
            type:'POST',
            url:'${pageContext.request.contextPath}/user/requestJson.do',
            contentType:'application/json;charset=utf-8',
            data:jsonObj,
            success:function(data){//这里的data表示的是返回的数据
                    alert(data.username)
            }
    })
}

在后台代码中:

@RequestMapping("requestJson")
public @ResponseBody User requestJson(@RequestBody User user){
    Sysotem.out.println(user);
    return user;//这里不再是页面了
}

2.接收pojo数据,输出json数据

首先在页面中:

function requestPo(){
    $.ajax({
            type:'POST',
            url:'${pageContext.request.contextPath}/user/requestPo.do',
            data:'username=小明&sex=男&address=河南',
            success:function(data){//这里的data表示的是返回的数据
                    alert(data.username)
            }
    })
}

在后台代码中:

@RequestMapping("requestPo")
public @ResponseBody User requestJson(User user){
    Sysotem.out.println(user);
    return user;//这里不再是页面了
}

4、Springmvc对多视图的支持

        对多视图支持,表示的是springmvc可以根据条件生成多种格式的数据(如通过提交的url的扩展名相应的返回xml格式数据【.xml】或者json格式数据【.json】)。首先导入相应的jar包(json如上,只导xml),然后在配置文件中配置多视图的支持:

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
       <!-- 配置支持媒体类型 -->
       <property name="contentNegotiationManager">
         <bean class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
            <property name="mediaTypes">
               <map>
                  <entry key="json" value="application/json"></entry>
		  <entry key="xml" value="application/xml"></entry>
               </map>
	   </property>
         </bean>
      </property>
      <!-- 指定默认视图 -->
       <property name="defaultViews">
	   <!-- 支持多个视图 -->
	   <list>
		<!-- 对josn格式视图支持 -->
		<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"></bean>
		
		<!-- xml格式视图支持 -->
		<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
		   <constructor-arg>
		      <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
		                     <property name="classesToBeBound">
		                              <list>
		                                    <value>com.shen.domain.User</value>
		                              </list>
		                        </property>
		                  </bean>
		     </constructor-arg>
		      </bean>
		</list>	
	</property>
</bean>

此外为了支持xml格式的输出,还要在输出的相应的实体类中加上如下注解:

@XmlRootElement
public class User {
}

在java代码中如下:

@RequestMapping("multView")
public String multView(){
	User user1 = new User();
	user1.setId(1);
	user1.setSex("男");
	user1.setUsername("张山峰");
	user1.setAddress("武当山");
	user1.setBirthday(new Date());
	return user1;
}

5、spring MVC的拦截器

       需要引入的命名空间为:

  xmlns:mvc="http://www.springframework.org/schema/mvc"<!--这里-->
    xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/mvc <!--这里-->
         http://www.springframework.org/schema/mvc/spring-mvc.xsd "><!--这里-->

1.局部拦截器

       针对单个处理器映射器,就叫局部拦截器。

2.全局拦截器

        在配置文件中:

<!--拦截器 -->
<mvc:interceptors>
	<!--多个拦截器,顺序执行 -->
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="com.shen.interceptor.Interceptor1"></bean>
	</mvc:interceptor>
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="com.shen.interceptor.Interceptor2"></bean>
	</mvc:interceptor>
</mvc:interceptors>

然后拦截器代码:

public class Interceptor1 implements HandlerInterceptor{
	//preHandle在处理器映射器之前进行执行
	//return false:拦截 return true:放行
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2) throws Exception {
		System.out.println("这是第一个拦截器Interceptor1。。。preHandle");
		return true;
	}
	//还没有调用Controller,还没返回modelAndView执行
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2, ModelAndView arg3) throws Exception {
		System.out.println("这是第一个拦截器Interceptor1。。。postHandle");
	}
	//返回modelAndView之后执行
	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object arg2, Exception arg3)
					throws Exception {
		System.out.println("这是第一个拦截器Interceptor1。。。afterCompletion");
	}
}
public class Interceptor2 implements HandlerInterceptor{
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2) throws Exception {
		System.out.println("这是第二个拦截器Interceptor2。。。preHandle");
		return true;
	}
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2, ModelAndView arg3) throws Exception {
		System.out.println("这是第二个拦截器Interceptor2。。。postHandle");	
	}
	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object arg2, Exception arg3)
					throws Exception {
		System.out.println("这是第二个拦截器Interceptor2。。。afterCompletion");	
	}
}

然后测试:

1.第一个拦截器放行,第二个拦截器也放行:

这是第一个拦截器Interceptor1。。。preHandle

这是第二个拦截器Interceptor2。。。preHandle

这是第二个拦截器Interceptor2。。。postHandle

这是第一个拦截器Interceptor1。。。postHandle

这是第二个拦截器Interceptor2。。。afterCompletion

这是第一个拦截器Interceptor1。。。afterCompletion

2.第一个拦截器放行,第二个不放行:

这是第一个拦截器Interceptor1。。。preHandle

这是第二个拦截器Interceptor2。。。preHandle

这是第一个拦截器Interceptor1。。。afterCompletion

说明:Springmvc规定:凡是preHandle返回true,afterCompletion必须执行。

猜你喜欢

转载自blog.csdn.net/qq_22172133/article/details/81318921