1.SpringMVC拦截器
1.1 拦截器(interceptor)的作用
Spring MVC的拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(intercrptor Chain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。
1.2 拦截器快速入门
创建拦截器步骤:
① 创建拦截器实现HandlerInterceptor
② 配置拦截器
③ 测试拦截器的拦截效果
开发步骤:
首先要有个目标资源用来访问,在对目标资源进行访问时对该请求使用拦截器进行拦截操作,具体开发步骤如下:
(1)第一步搭建maven项目(使用maven模板):
对pom.xml文件写入以下依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
(2)第二步 在java目录下创建controller包 并在包内添加目标访问资源targetController.java:
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class TargetController {
@RequestMapping(value = "/target") //配置目标访问路径
public ModelAndView target(){
System.out.println("目标资源访问target.....");
ModelAndView modelAndView = new ModelAndView();
//设置模型数据
modelAndView.addObject("name", "Harry patter!");
//设置视图
modelAndView.setViewName("success");
return modelAndView;
}
}
(3)第三步 在webapp下创建success.jsp文件 用于访问资源成功后要进行跳转的视图:
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<H2>${name} Success!!!!</H2>
</body>
</html>
(4) 第四步 在resources目录下创建spring-mvc.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 1. controller组件扫描 -->
<context:component-scan base-package="controller"/>
<!-- 2.配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 3.注解驱动-->
<!-- <mvc:annotation-driven/>-->
<!-- 4. 静态资源开放 -->
<!-- <mvc:default-servlet-handler/>-->
<!-- <mvc:resources mapping="/js/**" location="/js/" />-->
</beans>
(5)第五步 配置web.xml文件:
<web-app>
<!--配置前端控制器 -->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name> <!--固定名称contextConfigLocation -->
<param-value>classpath:spring-mvc.xml</param-value> <!-- spring-mvc.xml文件 -->
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
最后的项目结构如下:
测试http://localhost:8080/spring_interceptor_/target是否能跳转至success.jsp页面,效果:
(6)第六步创建拦截器 在java目录下创建interceptor包 包内创建MyInterceptor.java类并实现HandlerInterceptor接口:
package interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
//在目标方法执行之前 执行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return false; //返回true代表放行,false代表不放行
}
@Override
//在目标方法执行之后 视图对象返回之前执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
//在流程都执行完毕后执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterComletion");
}
}
(7)在spring-mvc.xml文件中配置拦截器:
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/> <!-- 表示对哪些资源执行拦截操作 /**表示所有资源 -->
<bean class="interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
测试:http://localhost:8080/spring_interceptor_/target是否能跳转至success.jsp页面,页面效果:
页面啥也没有,看控制台发现在MyInterceptor类中preHandle方法的输出语句打印了,而访问的目标资源内的输出语句以及其他没有被打印出来,说明拦截器起作用了 控制台效果:
现在将preHandle方法的返回值设置为true再进行测试
public class MyInterceptor implements HandlerInterceptor {
@Override
//在目标方法执行之前 执行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true; //返回true代表放行,false代表不放行
}
}
重启服务器测试:http://localhost:8080/spring_interceptor_/target是否能跳转至success.jsp页面,页面效果:
显然,当preHandler方法中的返回值为true值,页面能够进行正常的跳转了,再来看看控制台, 控制台效果:
打印的顺序为:preHandle —> 目标资源 —>postHandle —>afterComletion
从而得出了它们之间的执行顺序。
1.3 拦截器小实验:
实验1:
实验说明:在拦截器的preHandle方法中对客户端请求过来参数进行判断 如果为yes则返回true并跳转至success.jsp;否则为false,跳转至error.jsp
(1)在上一小节的基础上,在webapp下添加error.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>Error!!!</h2>
</body>
</html>
项目结构:
(2)在preHandle方法编写具体代码:
@Override
//在目标方法执行之前 执行 返回true代表放行,false代表不放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
String param = request.getParameter("param"); //获取前端请求参数
if("yes".equals(param)){
return true; //跳转至success.jsp页面
}else{
request.getRequestDispatcher("/error.jsp").forward(request, response);
return false;
}
}
启动服务器测试 http://localhost:8080/spring_interceptor_/target 页面效果:
添加param参数:http://localhost:8080/spring_interceptor_/target?param=no 页面效果:
将param参数修改为yes:http://localhost:8080/spring_interceptor_/target?param=yes 页面效果:
通过上面实验 使用拦截器对页面跳转进行了控制,仅当请求参数param为yes时才跳转至success.jsp页面,否则跳转至error.jsp页面。
实验2:
接下来 通过postHandle()方法对目标资源返回的ModelAndView对象进行修改:
@Override
//在目标方法执行之后 视图对象返回之前执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
modelAndView.addObject("name", "藤原拓海"); //覆盖目标资源返回的数据
}
启动服务器测试 http://localhost:8080/spring_interceptor_/target?param=yes 页面效果:
通过在postHandle()方法中将目标返回的model数据进行覆盖,并能够成功显示,表明,可以在postHandle()方法中对返回的ModelAndView对象进行修改。
实验3:
配置多个拦截器(拦截器链)
第一步:在interceptor包下 创建第二个拦截器MyInterceptor.java:
package interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor1 implements HandlerInterceptor {
@Override
//在目标方法执行之前 执行 返回true代表放行,false代表不放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle222222");
return true;
}
@Override
//在目标方法执行之后 视图对象返回之前执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle2222222");
}
@Override
//在流程都执行完毕后执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterComletion22222222");
}
}
第二步:在spring-mvc.xml文件配置拦截器:
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/> <!-- 表示对哪些资源执行拦截操作 /**表示所有资源 -->
<bean class="interceptor.MyInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/> <!-- 表示对哪些资源执行拦截操作 /**表示所有资源 -->
<bean class="interceptor.MyInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
启动服务器测试:http://localhost:8080/spring_interceptor_/target?param=yes 控制台效果:
执行的顺序与在spring-mvc.xml文件配置的顺序有关。
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/> <!-- 表示对哪些资源执行拦截操作 /**表示所有资源 -->
<bean class="interceptor.MyInterceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/> <!-- 表示对哪些资源执行拦截操作 /**表示所有资源 -->
<bean class="interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
颠倒spring-mvc.xml配置后的 控制台效果:
所以可根据需求更改spring-mvc.xml中配置的顺序,实现不同的拦截顺序。