SpringMVC(七)拦截器

版权声明:From Lay https://blog.csdn.net/Sadlay/article/details/84109029

SpringMVC(七)拦截器

当请求来到DispatcherServlet时,它会根据HandlerMapping的机制找到处理器,这样就返回一个HandlerExecutionChain对象,这个对象包含处理器和拦截器。这里的拦截器会对处理器进行拦截,这样通过拦截器就可以增强处理器的功能。

拦截器的设计

所有拦截器都要实现HandlerInterceptor接口。

HandlerInterceptor源码

public interface HandlerInterceptor {

	//处理器执行前方法
	boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception;

	//处理器处理后方法
	void postHandle(
			HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
			throws Exception;
	
    //处理器完成后方法
	void afterCompletion(
			HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception;

}

拦截器流程

具体的流程如下
拦截器执行过程

  • 执行preHandler方法,该方法会返回一个布尔值。如果为false,就结束所有流程;如果为true,则执行下一步
  • 执行处理器的逻辑,它包含控制器的功能
  • 执行postHandler方法
  • 执行视图解析和视图模型
  • 执行afterCompetion方法

开发拦截器

通过实现HandlerInterceptor接口来写一个简单的拦截器

MyInterceptor

package com.lay.mvc.interceptor;

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Description: 简单的拦截器
 * @Author: lay
 * @Date: Created in 14:07 2018/11/15
 * @Modified By:IntelliJ IDEA
 */
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("处理器前方法");
        //返回true,不会拦截后续的处理
        return true;
    }

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

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("处理完成方法");
    }
}

这里重写了HandlerInterceptor的三个拦截器方法,在中间打印了一些信息。

有了这个拦截器,spring mvc并不会发现它,它还需要进行注册才能够拦截处理器,为此需要在配置文件中实现WebMmcConfigurer接口,并覆盖addInterceptors方法进行注册拦截器。

InterceptorCofig 拦截器注册

package com.lay.mvc.config;

import com.lay.mvc.interceptor.MyInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @Description:拦截器配置
 * @Author: lay
 * @Date: Created in 14:18 2018/11/15
 * @Modified By:IntelliJ IDEA
 */
@Configuration
public class InterceptorCofig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册拦截器到Spring MVC机制,然后它会返回一个拦截器注册
        InterceptorRegistration ir = registry.addInterceptor(new MyInterceptor());
        //指定拦截匹配模式,限制拦截器拦截请求
        ir.addPathPatterns("/interceptor/*");
    }
}

这里指定了拦截器的模式,所以它只会拦截与正则式"/interceptor/*"匹配的请求。

接着创建一个用于测试的控制器

扫描二维码关注公众号,回复: 4300606 查看本文章

InterceptorController

package com.lay.mvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Description: 拦截器控制器
 * @Author: lay
 * @Date: Created in 14:23 2018/11/15
 * @Modified By:IntelliJ IDEA
 */
@Controller
@RequestMapping("/interceptor")
public class InterceptorController {
    @GetMapping("/start")
    public String start(){
        System.out.println("执行处理器逻辑");
        return "/welcome";
    }
}

这里写了处理器逻辑,并且返回一个视图

welcome.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>
    <h1>welcome</h1>
</body>
</html>

控制台出如下

处理器前方法
执行处理器逻辑
处理后方法
处理完成方法

多个拦截器

注册顺序

registry.addInterceptor(new MyInterceptor1());
registry.addInterceptor(new MyInterceptor2());
registry.addInterceptor(new MyInterceptor3());

打印日志

【MyInterceptor1】处理器前方法
【MyInterceptor2】处理器前方法
【MyInterceptor3】处理器前方法
执行处理器逻辑
【MyInterceptor3】处理后方法
【MyInterceptor2】处理后方法
【MyInterceptor1】处理后方法
【MyInterceptor3】处理完成方法
【MyInterceptor2】处理完成方法
【MyInterceptor1】处理完成方法

可以看到多个拦截器同时作用的时候,遵循责任链式规则。对于处理器前方法采用先注册限制性,而处理器后方法和完成方法则是先注册后执行的规则。但这也只是测试了所有拦截器前方法都返回true的场景。如果我们将MyInterceptor2的前方法preHandler返回值改为false

【MyInterceptor1】处理器前方法
【MyInterceptor2】处理器前方法
【MyInterceptor1】处理完成方法

从日志可以看出,处理器前方法会执行,但是一旦返回false,则后续的拦截器、处理器和所有的拦截器的处理器后方法都不会执行。完成方法afterCompletion则不一样,它只会执行返回true的拦截器的完成方法,而且顺序是先注册后执行。

猜你喜欢

转载自blog.csdn.net/Sadlay/article/details/84109029