🌟本篇博文参考资料:黑马程序员 SSM框架 视频教学 >> 传送门 <<
1. 什么是拦截器?(Interceptor)
SpringMVC的拦截器类似于 Servlet 开发中的过滤器 Filter ,用于对处理器进行预处理和后处理
将拦截器按一定的顺序连接成一条链,这条链称为 拦截器链(Interceptor Chain) 。
在访问被拦截的方法或字段时,拦截器链中的拦截器就会按之前定义的顺序被调用。
拦截器是AOP思想的具体实现。
2. 拦截器和过滤器的区别
区别 | 过滤器 | 拦截器 |
---|
使用范围 | servlet规范的一部分,任何JavaWeb工程都可以使用 | 属于SpringMVC框架,只有该框架的工程能使用 | 拦截范围 | 在 url-parttern 中配置 /* 后,可对所有访问的资源拦截 | 只会拦截访问的控制器方法,如果访问的是jsp, html, css, image 或者 js 是不会进行拦截的 |
3. 实现拦截器的三部曲
- 创建拦截器类并实现 HandlerInterceptor接口
- 在spring-mvc.xml 里配置拦截器
- 测试拦截器的拦截效果
4. 拦截器的三大方法
方法名 | 说明 |
---|
perHandle() | 该方法将在请求处理之前被调用,返回值是布尔值Boolean类型,当返回false,则表示请求结束,后序的Interceptor 和Controller 都不再执行 ;放返回true,继续调用下一个Interceptor 的preHandle 方法 | postHandle() | 该方法在当前请求处理后被调用,前提是 preHandle() 返回 true才能成功调用,且会在 DispatcherServlet 进行视图返回渲染之前执行,所以可在这个方法里对 Controller 处理后的 ModelAndView 对象进行操作 | afterCompletion() | 该方法将在整个请求结束后,即在 DispathcerServlet 渲染了对应的视图之后执行,前提是 preHandle() 方法返回值为 true |
5. 测试拦截器效果的Demo
实现: 限制用户访问,测试url:http://localhost:8080/target
判断 访问如: http://localhost:8080/target?&id=xxx 的值是否符合要求
若符合要求则跳到 welcome.jsp 页面, 否则跳转到 error.jsp 页面
5.1 测试环境
IDEA Ultimate 2021.1 Tomcat 9.0.50 jdk1.8 IDEA 自带 Maven
5.2 项目文件结构
5.3 配置 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SpringMVC_Demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>SpringMVC_Demo Maven Webapp</name>
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>
</project>
修改好 pom.xml 配置文件后,需要手动刷新一下maven
5.4 配置 spring-mvc.xml 和 web.xml文件
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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven/>
<bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value = "/"/>
<property name="suffix" value = ".jsp"/>
</bean>
<mvc:default-servlet-handler/>
<context:component-scan base-package="com.uni.controller"/>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class = "com.uni.interceptor.MyInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</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>
5.5 编写控制层和拦截器的测试类
SpringMVC中的控制(Controller) 层 一般用于接收客户端的请求,然后调用Service层业务逻辑,获取到数据,传递数据给视图层(客户端)用于视觉呈现。
TargetController.java
package com.uni.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class TargetController {
@RequestMapping("/target")
public ModelAndView show(){
System.out.println("目标资源执行...");
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("age", 21);
modelAndView.setViewName("welcome");
return modelAndView;
}
}
MyInterceptor1.java
package com.uni.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
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle Done.");
String id = request.getParameter("id");
if("uni1024".equals(id)){
return true;
} else{
request.getRequestDispatcher("/error.jsp").forward(request, response);
return false;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle Done.");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterComepletion Done.");
}
}
5.6 编写测试的前端jsp文件
index.jsp
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>id不匹配!</h1>
</body>
</html>
welcome.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>欢迎访问 ${age} 岁的 uni!</h1>
</body>
</html>
5.7 测试效果
-
初次进入页面时显示index.jsp 正常,IDEA终端无输出 -
未传入id参数时,直接拦截,前端显示error.jsp ,终端只显示preHandle方法执行结束,同时表示拦截器的实现方法没有执行。 -
传入参数错误时,仍然显示错误页面error.jsp ,终端同样只输出preHandle Done. ,表示拦截器的实现方法没有执行。 -
传入参数正确,前端显示welcome.jsp 页面,其中21岁 ,是在拦截器方法调用ModelAndView 对象的方法addObject 添加了age:21 的 key-value键值对,这使得在 welcome.jsp 页面可以通过 ${age} 直接输出。 在终端则输出了三个拦截器方法以及实现方法show 的执行结果。
|