10-Interceptor

1. Concept

image-20240101223657330
  • Servlet为Spring自带的,位于javax.servlet包中
  • Java_web时,Filter作用是保护服务器资源,如果请求地址符合拦截范围,会先在Servlet之前执行过滤器
  • 但在使用了SpringMVC后,Servlet只有一个(DispatcherServlet)。使用Filter,会拦截所有请求

  • SpringMVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),用于拦截用户请求
    • 进行权限验证
    • 记录请求信息的日志
    • 判断用户是否登录
  • 拦截器定义
    1. 通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类(eg:HandlerInterceptorAdapter)
    2. 通过实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口的实现类
  • 拦截器、过滤器区别
    1. 拦截器属于SpringMVC,过滤器属于Servlet
    2. 拦截器不依赖Servlet容器,由Spring容器初始化;过滤器依赖Servlet容器,由Servlet容器初始化
    3. 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
    4. 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问
    5. 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
    6. 拦截器可以获取IOC容器中的各个bean,而过滤器就不太方便。在拦截器里注入一个Service,可以调用业务逻辑

2. MyInterceptor

package com.listao.mvc.interceptor;

public class MyInterceptor implements HandlerInterceptor {

    /**
     * 请求到达自定义handler之前工作
     *
     * @param request  请求对象
     * @param response 响应对象
     * @param handler  要调用的目标Handler
     * @return true放行,false拦截
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor.preHandle()");
        // 1. 设置请求、响应的编码
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        // 2. 判断是否登录
        User user = (User) request.getSession().getAttribute("user");

        // 3. 用户权限控制

        return true;
    }


    /**
     * handler处理单元返回ModelAndView时,进行拦截
     *
     * @param modelAndView controller响应的结果:视图、数据
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor.postHandle()");

        // 1. 控制响应数据
        Map<String, Object> map = modelAndView.getModel();
        String msg = (String) map.get("msg");
        if (msg != null) {
            String newMsg = msg.replaceAll("脏话", "**");
            map.put("msg", newMsg);
        }

        // 2. 控制视图
        modelAndView.setViewName("/index.jsp");
    }


    /**
     * 页面渲染完毕,给浏览器响应数据前。Controller是否异常,都会执行的方法 == finally{}
     * 1. 异常处理工作
     * 2. 资源释放工作
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor.afterCompletion()");
        // System.out.println(ex);

    }
}


 










 

 


 


 











 


 







 










 





  • spring_mvc.xml中注册拦截器
<!-- 注册拦截器 -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/login"/>
        <bean id="myInterceptor" class="com.listao.mvc.interceptor.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>



 
 


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>success.jsp</title>
</head>
<body>
登录成功
<%
    System.out.println("success.jsp ==>> 定位MyInterceptor.afterCompletion()");
%>
${requestScope.msg}
</body>
</html>

3. 多拦截器执行顺序

  • 由配置顺序决定。先配置谁,谁就先执行
  • 可以理解为拦截器栈,先进后出
<!-- 注册拦截器 -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/login"/>
        <bean id="myInterceptor" class="com.listao.ssm.interceptor.MyInterceptor"/>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/login"/>
        <bean id="myInterceptor2" class="com.listao.ssm.interceptor.MyInterceptor2"/>
    </mvc:interceptor>
</mvc:interceptors>




 



 


public class MyInterceptor2 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor2.preHandle()");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor2.postHandle()");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor2.afterCompletion()");
    }
}
MyInterceptor.preHandle()
MyInterceptor2.preHandle()
login() ===>>>										// controller
MyInterceptor2.postHandle()
MyInterceptor.postHandle()
success.jsp ==>> 定位MyInterceptor.afterCompletion() // 页面渲染在`afterCompletion()`之前
MyInterceptor2.afterCompletion()
MyInterceptor.afterCompletion()