(22)Spring Boot 拦截器HandlerInterceptor【从零开始学Spring Boot】

 

上一篇对过滤器的定义做了说明,也比较简单。过滤器属于Servlet范畴的API,与Spring 没什么关系。 
    Web
开发中,我们除了使用 Filter 来过滤请web求外,还可以使用Spring提供的HandlerInterceptor(拦截器)。

HandlerInterceptor 的功能跟过滤器类似,但是提供更精细的的控制能力:在request被响应之前、request被响应之后、视图渲染之前以及request全部结束之后。我们不能通过拦截器修改request内容,但是可以通过抛出异常(或者返回false)来暂停request的执行。

实现 UserRoleAuthorizationInterceptor 的拦截器有: 
ConversionServiceExposingInterceptor 
CorsInterceptor 
LocaleChangeInterceptor 
PathExposingHandlerInterceptor 
ResourceUrlProviderExposingInterceptor 
ThemeChangeInterceptor 
UriTemplateVariablesHandlerInterceptor 
UserRoleAuthorizationInterceptor

其中 LocaleChangeInterceptor ThemeChangeInterceptor 比较常用。

配置拦截器也很简单,Spring 为什么提供了基础类WebMvcConfigurerAdapter ,我们只需要重写 addInterceptors 方法添加注册拦截器。

实现自定义拦截器只需要3步: 
1
、创建我们自己的拦截器类并实现 HandlerInterceptor 接口。 
2
、创建一个Java类继承WebMvcConfigurerAdapter,并重写 addInterceptors 方法。 
2
、实例化我们自定义的拦截器,然后将对像手动添加到拦截器链中(在addInterceptors方法中添加)。 
PS
:本文重点在如何在Spring-Boot中使用拦截器,关于拦截器的原理请大家查阅资料了解。

代码示例:

com.kfit.interceptor.MyInterceptor1.java

package com.kfit.interceptor;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

 

/**

 * 自定义拦截器1

 *

 * @author   Angel

 */

publicclass MyInterceptor1 implements HandlerInterceptor {

 

    @Override

    publicboolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

            throws Exception {

        System.out.println(">>>MyInterceptor1>>>>>>>在请求处理之前进行调用(Controller方法调用之前)");

 

        returntrue;// 只有返回true才会继续向下执行,返回false取消当前请求

    }

 

    @Override

    publicvoid postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

            ModelAndView modelAndView) throws Exception {

        System.out.println(">>>MyInterceptor1>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");

    }

 

    @Override

    publicvoid afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

            throws Exception {

        System.out.println(">>>MyInterceptor1>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");

    }

 

}

 

com.kfit.interceptor.MyInterceptor2.java

package com.kfit.interceptor;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.springframework.web.servlet.HandlerInterceptor;

import org.springframework.web.servlet.ModelAndView;

 

/**

 * 自定义拦截器2

 *

 * @author   Angel

 */

public class MyInterceptor2 implements HandlerInterceptor {

 

    @Override

    publicboolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

            throws Exception {

        System.out.println(">>>MyInterceptor2>>>>>>>在请求处理之前进行调用(Controller方法调用之前)");

 

        returntrue;// 只有返回true才会继续向下执行,返回false取消当前请求

    }

 

    @Override

    publicvoid postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

            ModelAndView modelAndView) throws Exception {

        System.out.println(">>>MyInterceptor2>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");

    }

 

    @Override

    publicvoid afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

            throws Exception {

        System.out.println(">>>MyInterceptor2>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");

    }

 

}

 

Com.kfit.config.MyWebAppConfigurer.java

package com.kfit.config;

 

import com.kfit.interceptor.MyInterceptor1;

import com.kfit.interceptor.MyInterceptor2;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

 

@Configuration

public class MyWebAppConfigurer

        extends WebMvcConfigurerAdapter {

 

    @Override

    publicvoid addInterceptors(InterceptorRegistry registry) {

        // 多个拦截器组成一个拦截器链

        // addPathPatterns 用于添加拦截规则

        // excludePathPatterns 用户排除拦截

        registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**");

        registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**");

        super.addInterceptors(registry);

    }

 

}

 

然后在浏览器输入地址: http://localhost:8080/index 后,控制台的输出为:

>>>MyInterceptor1>>>>>>>在请求处理之前进行调用(Controller方法调用之前)

>>>MyInterceptor2>>>>>>>在请求处理之前进行调用(Controller方法调用之前)

>>>MyInterceptor2>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)

>>>MyInterceptor1>>>>>>>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)

>>>MyInterceptor2>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)

>>>MyInterceptor1>>>>>>>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)

 

根据输出可以了解拦截器链的执行顺序(具体原理介绍,大家找度娘一问便知)

最后强调一点:只有经过DispatcherServlet 的请求,才会走拦截器链,我们自定义的Servlet 请求是不会被拦截的,比如我们自定义的Servlet地址http://localhost:8080/myServlet1 是不会被拦截器拦截的。并且不管是属于哪个Servlet 只要复合过滤器的过滤规则,过滤器都会拦截。

最后说明下,我们上面用到的 WebMvcConfigurerAdapter 并非只是注册添加拦截器使用,其顾名思义是做Web配置用的,它还可以有很多其他作用,通过下面截图便可以大概了解,具体每个方法都是干什么用的,留给大家自己研究(其实都大同小异也很简单)。 

【Spring Boot 系列博客】

76. Spring Boot完美解决(406)Could not find acceptable representation原因及解决方法 

 

75. Spring Boot 定制URL匹配规则【从零开始学Spring Boot】 

 

71.mybatis 如何获取插入的id【从零开始学Spring Boot】 

 

67. @Transactional的类注入失败【从零开始学Spring Boot】 

 

63.JPA/Hibernate/Spring Data概念【从零开始学Spring Boot】 

 

61. mybatic insert异常:BindingException: Parameter 'name' not found【从零开始学Spring B】 

 

 

60. Spring Boot写后感【从零开始学Spring Boot】 

 

 

59. Spring Boot Validator校验【从零开始学Spring Boot】 

 

58. Spring Boot国际化(i18n)【从零开始学Spring Boot】 

 

57. Spring 自定义properties升级篇【从零开始学Spring Boot】 

 

56. spring boot中使用@Async实现异步调用【从零开始学Spring Boot】 

 

55. spring boot 服务配置和部署【从零开始学Spring Boot】 

 

54. spring boot日志升级篇—logback【从零开始学Spring Boot】

 

52. spring boot日志升级篇—log4j多环境不同日志级别的控制【从零开始学Spring Boot】 

 

51. spring boot属性文件之多环境配置【从零开始学Spring Boot】

 

50. Spring Boot日志升级篇—log4j【从零开始学Spring Boot】

 

49. spring boot日志升级篇—理论【从零开始学Spring Boot】

 

48. spring boot单元测试restfull API【从零开始学Spring Boot】

 

47. Spring Boot发送邮件【从零开始学Spring Boot】

 

46. Spring Boot中使用AOP统一处理Web请求日志

 

45. Spring Boot MyBatis连接Mysql数据库【从零开始学Spring Boot】

 

44. Spring Boot日志记录SLF4J【从零开始学Spring Boot】

 

43. Spring Boot动态数据源(多数据源自动切换)【从零开始学Spring Boot】

 

42. Spring Boot多数据源【从零开始学Spring Boot】

 

41. Spring Boot 使用Java代码创建Bean并注册到Spring中【从零开始学Spring Boot】

 

40. springboot + devtools(热部署)【从零开始学Spring Boot】 

 

39.4 Spring Boot Shiro权限管理【从零开始学Spring Boot】

 

39.3 Spring Boot Shiro权限管理【从零开始学Spring Boot】

 

39.2. Spring Boot Shiro权限管理【从零开始学Spring Boot】

 

39.1 Spring Boot Shiro权限管理【从零开始学Spring Boot】

 

38 Spring Boot分布式Session状态保存Redis【从零开始学Spring Boot】 

 

37 Spring Boot集成EHCache实现缓存机制【从零开始学Spring Boot】 

 

36 Spring Boot Cache理论篇【从零开始学Spring Boot】

 

35 Spring Boot集成Redis实现缓存机制【从零开始学Spring Boot】 

 

34Spring Boot的启动器Starter详解【从零开始学Spring Boot】

 

33 Spring Boot 监控和管理生产环境【从零开始学Spring Boot】

 

32 Spring Boot使用@SpringBootApplication注解【从零开始学Spring Boot】 

 

31 Spring Boot导入XML配置【从零开始学Spring Boot】

 

 

更多查看博客: http://412887952-qq-com.iteye.com/

原文地址:https://www.cnblogs.com/hehehaha/p/6147122.html