1、什么是拦截器?
SpringMVC的拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。
过滤器与拦截器的区别:拦截器是AOP思想的具体应用。
- 过滤器
- servlet规范中的一部分,任何java web工程都可以使用
- 在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截
- 拦截器
- 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
- 拦截器只会拦截访问的控制器方法, 访问的是jsp/html/css/image/js是不会进行拦截的
2、创建并配置拦截器
1,创建类实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
}
2,实现方法
//在handler方法执行之前被调用
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
//返回值代表是否放行
return true;
}
//目标方法执行之后
@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("afterCompletion");
}
- preHandle方法会在Handler方法执行之前执行,可以在其中进行一些前置的判断或者处理。
- postHandle方法会在Handler方法执行之后执行,可对域中的数据修改,以及要跳转的页面
- afterCompletion方法会在最后执行,此时已经没有办法对域中的数据进行修改,也没有办法修改要跳转的页面,我们在这方法中一般进行一些·资源的释放。
3,配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/> <!--配置拦截器需要连接的路径-->
<!--配置拦截器不需要连接的路径-->
<!-- <mvc:exclude-mapping path="/"/> -->
<bean class="interceptor.MyInterceptor"/> <!--配置拦截器对象注入bean-->
</mvc:interceptor>
</mvc:interceptors>
拦截路径:
/test/* 这种会拦截下面这种路径 /test/add /test/delete
但是拦截不了多级路径的情况,例如: /test/add/abc /test/add/sdd
/test/** 这种可以拦截多级,以及单级路径。
总而言之:/只能拦截单级路径,不能拦截子路径,而/*单级和多级路径都能拦截。
3、案例-登陆状态拦截器
1,需求
我们的接口需要做用户登录状态的校验。
如果用户没有登录,则跳转到登录页面;只有在登录的情况下才可以正常访问我们的接口。
2,分析
- 怎么判断是否登录?
- 很多接口都要去写判断的代码,难道要在每一个Handler中写判断逻辑?
- 登陆接口是否应该进行拦截?
- 静态资源是否要进行拦截?
3,代码实现
项目结构
表单
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
<input type="text" name="name"><br>
<input type="password" name="password"><br>
<input type="submit">
</form>
</body>
</html>
成功页面
<%--
Created by IntelliJ IDEA.
User: 27837
Date: 2021/8/3
Time: 10:33
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
登录成功
Session为${sessionScope.get("session")}
</body>
</html>
配置文件
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--自动扫描包:让指定包下的注解生效,由IOC容器统一管理-->
<context:component-scan base-package="controller"/>
<!--让SpringMVC不处理静态资源-->
<mvc:default-servlet-handler/>
<!--配置支持注解驱动-->
<mvc:annotation-driven >
<!--解决响应乱码-->
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="utf-8"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/> <!--配置拦截器需要连接的路径-->
<!--配置拦截器不需要连接的路径-->
<mvc:exclude-mapping path="/WEB-INF/jsp/**"/>
<mvc:exclude-mapping path="/static/**"/>
<mvc:exclude-mapping path="/login"/>
<bean class="interceptor.MyInterceptor"/> <!--配置拦截器对象注入bean-->
</mvc:interceptor>
</mvc:interceptors>
</beans>
控制器
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import javax.servlet.http.HttpServletRequest;
@Controller
@SessionAttributes("session")
public class TestController {
@RequestMapping("/login")
public String login(String name,String password, Model model){
System.out.println(name);
System.out.println(password);
if (name.equals("张三")&&password.equals("123")){
System.out.println("成功");
model.addAttribute("session","OK");
return "success";
}
else
System.out.println("失败");
return "forward:/static/form.html";
}
@RequestMapping("/success")
public String success(){
return "success";
}
}
拦截器
package interceptor;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取Session
HttpSession httpSession=request.getSession();
String session = (String) httpSession.getAttribute("session");//强制转换
//判断是否为空
if (StringUtils.isEmpty(session)){
//为空,未登录,重定向跳转到登录页面
response.sendRedirect("/static/form.html");
}
else {
//不为空,已登录
return true;
}
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
4、多个拦截器执行流程
拦截器的顺序与拦截器的名字无关,主要决定于配置文件中的顺序