SpringMVC学习笔记11-拦截器

十一 拦截器

1 拦截器简介
1.1什么是拦截器 Spring MVC 的拦截器(Interceptor)与 Servlet 的过滤器(Filter)类似,它主要用于拦 截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否 登录等功能上。
1.2拦截器执行流程
SpringMVC学习笔记11-拦截器_第1张图片

1.3拦截器和过滤器的区别 
拦截器 SpringMVC 组件,而过滤器是 Servlet 组件。 
拦截器不依赖容器,过滤器依赖容器。 
拦截器只能对控制器请求起作用,而过滤器则可以对所有的请求起作用。 
拦截器可以获取 IOC 容器中的各个 bean,而过滤器就不太方便。
2 定义拦截器
在 Spring MVC 中定义一个拦截器需要对拦截器进行创建和配置。
创建拦截器时需要实 现 HandlerInterceptor 接口。
2.1拦截器方法介绍 在 HandlerInterceptor 接口中包含了三个抽象方法,分别表示拦截的时间点。
2.1.1 preHandle 方法 该方法在控制器的处理请求方法前执行,其返回值表示是否中断后续操作,返回 true 表示继续向下执行,返回 false 表示中断后续操作。
2.1.2 postHandle 方法 该方法在控制器的处理请求方法执行之后、视图解析之前执行,可以通过此方法对请求 域中的模型和视图做进一步的修改。

2.1.3 afterCompletion 方法 该方法在控制器的处理请求方法执行完成后执行,即视图渲染结束后执行,可以通过此 方法实现一些资源清理、记录日志信息等工作。

2.2创建拦截器

2.2.1 创建项目
SpringMVC学习笔记11-拦截器_第2张图片

2.2.2 创建拦截器
代码:

package com.bjsxt.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 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 :为客户端产生响应之前");

    }
}

2.3配置拦截器

需要在 SpringMVC 的配置文件中,通过mvc:interceptors标签配置拦截器。


<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">
    
    <context:component-scan base-package="com.bjsxt.web.controller"/>
    
    <mvc:annotation-driven/>
    
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    bean>
    
    <mvc:interceptors>
         <mvc:interceptor>
            
            <mvc:mapping path="/**"/>
            
            
            <bean class="com.bjsxt.interceptor.MyInterceptor"/>
        mvc:interceptor>
        mvc:interceptors>
beans>

运行结果:
控制台中输出:
SpringMVC学习笔记11-拦截器_第3张图片修改拦截的路径:配置不拦截的地址
运行结果:不拦截这个getUsers请求!

SpringMVC学习笔记11-拦截器_第4张图片

3 定义全局拦截器

全局拦截器是指可以拦截所有被控制器所处理 URL。作用等同于/**

3.1创建全局拦截器

package com.bjsxt.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 GlobalInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Global PreHandle");
        return true;
    }

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

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Global afterCompletion");
    }
}

3.2配置全局拦截器
感觉全局拦截器很牛逼,直接在标签里面写bean就可以了,连路径都不需要写。


<mvc:interceptors>
    
    <bean class="com.bjsxt.interceptor.GlobalInterceptor"/>
    <mvc:interceptor>
        
        <mvc:mapping path="/**"/>
        
        
        <bean class="com.bjsxt.interceptor.MyInterceptor"/>
    mvc:interceptor>
    mvc:interceptors>

运行结果:控制台输出。拦截流程中的语句!

SpringMVC学习笔记11-拦截器_第5张图片

4 多拦截器执行顺序
如果一个 URL 能够被多个拦截器所拦截,全局拦截器最先执行,其他拦截器根据配置 文件中配置的上下顺序来决定执行顺序的。先配置谁, 谁就先执行。


<mvc:interceptors>
    
    <bean class="com.bjsxt.interceptor.GlobalInterceptor"/>
    <mvc:interceptor>
        
        <mvc:mapping path="/**"/>
        
        
        <bean class="com.bjsxt.interceptor.MyInterceptor"/>
    mvc:interceptor>
    
    <mvc:interceptor>
        
        <mvc:mapping path="/**"/>
        
        
        <bean class="com.bjsxt.interceptor.MyInterceptor2"/>
    mvc:interceptor>
   mvc:interceptors>
package com.bjsxt.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 MyInterceptor2 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle2 :在处理请求的目标方法之前");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle2 :目标方法执行之后,视图解析器之前");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion2 :为客户端产生响应之前");

    }
}

运行结果:执行顺序就是springmvc中的书写顺序。
先执行全局拦截器pre
在执行第一个拦截器pre
在执行第二个拦截器pre
在执行第二个拦截器post
在执行第一个拦截器post
在执行全局拦截器post
在执行第二个拦截器after…

运行结果:
SpringMVC学习笔记11-拦截器_第6张图片

5 拦截器应用案例

5.1需求
在响应的结果中将 Oldlu 字符串更换为*****。
5.2创建拦截器

package com.bjsxt.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

public class ContentReplaceInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        Map<String, Object> model = modelAndView.getModel();
        String str = (String)model.get("msg");
        if(str.contains("Oldlu")) {
            String newStr = str.replaceAll("Oldlu","*****");
            model.put("msg",newStr);
        }

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

5.3配置拦截器


<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">
    
    <context:component-scan base-package="com.bjsxt.web.controller"/>
    
    <mvc:annotation-driven/>
    
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    bean>
    
    <mvc:interceptors>
        
        <bean class="com.bjsxt.interceptor.GlobalInterceptor"/>
        <mvc:interceptor>
            
            <mvc:mapping path="/**"/>
            
            
            <bean class="com.bjsxt.interceptor.MyInterceptor"/>
        mvc:interceptor>
        
        <mvc:interceptor>
            
            <mvc:mapping path="/**"/>
            
            
            <bean class="com.bjsxt.interceptor.MyInterceptor2"/>
        mvc:interceptor>
        
        <mvc:interceptor>
            
            <mvc:mapping path="/user/getUsers"/>
            <bean class="com.bjsxt.interceptor.ContentReplaceInterceptor"/>
        mvc:interceptor>
    mvc:interceptors>
beans>

其他部分代码:

<%--
  Created by IntelliJ IDEA.
  User: HP
  Date: 2020/12/22
  Time: 20:45
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Titletitle>
head>
<body>
user...${msg}
body>
html>
package com.bjsxt.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/user")
public class UsersController {
    @RequestMapping("/getUsers")
    public String getUsers(Model model) {
        model.addAttribute("msg","Hello Oldlu");
        return "showuser";
    }
}

运行结果:
在post请求处理完毕之后拦截,将字符替换。
注意重点是Model放一下msg,不能是HttpServletRequest,ModelAndView。试的时候,发现拦截器中的post…方法取不到msg,报空指针了。
SpringMVC学习笔记11-拦截器_第7张图片
总结:
拦截器就是一个实现Springmvc的HandlerInterceptor接口的三个方法的类。这个类需要在springmvc的配置文件中配置拦截器标签。跟注解扫描没有关系。执行顺序见图。全局拦截所有请求,其他的可以配置拦的请求uri,可以配置不拦截的请求的uri,可以在请求执行前做些操作,在请求的目标方法执行完毕,视图解析器执行前做些操作,还可以在响应前做些操作。

你可能感兴趣的:(SpringMVC学习笔记)