您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

springboot三种拦截器

时间:2021-05-10 10:16:33  来源:今日头条  作者:风骚的程序员

SpringBoot 共有三种拦截http请求方式Filter,interceptor和aop。

1、FIlter

使用Filter的时候需要在Application启动类上加入@ServletComponentScan注解

import JAVAx.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
 * 在SpringBoot中通过注解注册的方式简单的使用Filter
 * @author rayfoo
 */
@WebFilter(urlPatterns = "/*", filterName = "MyFilter")
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("MyFilter  Filter初始化中");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("MyFilter  开始进行过滤处理");
        //调用该方法后,表示过滤器经过原来的url请求处理方法
        chain.doFilter(request, response);
        System.out.println("MyFilter  处理后的操作");
    }

    @Override
    public void destroy() {
        System.out.println("MyFilter  Filter销毁中");
    }
}

上述代码中,重写了Filter的三个方法,分别是:

init:在此Filter被创建时执行

doFilter:处理Filter的真正业务逻辑,可以在这个方法中对请求进行放行,在放行前后都可以执行代码,也可以在此方法中进行重定向和请求转发,但是一旦使用了请求转发、重定向,抛出异常,出现异常,被拦截的路径对应的业务方法就不会被执行。

destory:在此FIlter被销毁时执行

2、Interceptor

Interceptor依赖于web框架,我们经常在Spring MVC中用到该配置,在这个场景下Interceptor 就依赖于SpringMVC框架。

使用Interceptor之前要先创建类并实现HandlerInterceptor接口

import org.springframework.lang.Nullable;
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 {
    /**
     * 在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor  方法执行之前...");
        return true;
    }

    /**
     * 在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor  回调操作...");
    }

    /**
     * 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面)
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        System.out.println("MyInterceptor  方法执行之后...");
    }
}

创建完实现类还需要注册Interceptor

在SpringBoot2中,建议使用的注册拦截器的方法有如下两种:

1)实现WebMvcConfigurer接口

2)继承WebMvcConfigurerAdapter类(此类也是实现了WebMvcConfigurer)

下面介绍一下实现WebMvcConfigurer方法注册拦截器

import com.xa.filter.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;

@Configuration
public class MyConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //1.得到自定义的拦截器
        InterceptorRegistration interceptor = registry.addInterceptor(new MyInterceptor());
        //2.需要拦截的路径 /**所有资源都拦截
        interceptor.addPathPatterns("/**");
        //3.设置不拦截的路径 (登录页需要的和静态资源)
        interceptor.excludePathPatterns("/","/index.html","/login","/css/**","/img/**","/js/**");
    }
}

3、AOP

使用AOP首先要引入jar包

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
     <version>2.1.1.RELEASE</version>
 </dependency>

定义切面


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

@Aspect
@Component
@Order(1) //指定切面类执行顺序,数字越小越先执行
public class MyAspect {
    /**
     * 定义那个包下的执行 面向切换
     * 该示例 实现 所有controller 包下的方法执行的切面
  	 * 第一个*含义是:代表所有类型的返回值
		 * 第二个*是代表com.mall.web.controller包下的所有类
		 * 第三个是类下的所有方法,括号中两个点表示任意个形参
	*/
    @Pointcut("execution(public * com.*.controller.*.*(..))")
    public void webLog(){}

    /**
     * 请求之前 进入控制之前 执行,但是在拦截器之后执行
     * @param joinPoint
     * @throws Throwable
     */
    @Before("webLog()")
    public void deBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        System.out.println("MyAspect  URL : " + request.getRequestURL().toString());
        System.out.println("MyAspect  HTTP_METHOD : " + request.getMethod());
        System.out.println("MyAspect  IP : " + request.getRemoteAddr());
        System.out.println("MyAspect  CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        System.out.println("MyAspect  ARGS : " + Arrays.toString(joinPoint.getArgs()));


    }

    /**
     * 控制器执行之后执行,得到控制器方法的返回值
     * @param ret
     * @throws Throwable
     */
    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
        System.out.println("MyAspect  方法的返回值 : " + ret);
    }

    //后置异常通知
    @AfterThrowing("webLog()")
    public void throwss(JoinPoint jp){
        System.out.println("MyAspect  方法异常时执行.....");
    }

    //后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
    @After("webLog()")
    public void after(JoinPoint jp){
        System.out.println("MyAspect  方法最后执行.....");
    }

    //环绕通知,环绕增强,相当于 请求方法的拦截器
    @Around("webLog()")
    public Object arround(ProceedingJoinPoint pjp) {
        System.out.println("MyAspect  方法环绕start....."); // 最先执行
        try {
            Object o =  pjp.proceed();
            System.out.println("MyAspect  方法环绕proceed,结果是 :" + o); // 最后执行
            return o;
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }
}

我们新增个Controller来测试下他们的运行顺序

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class DemoController {

    @GetMapping("/demo")
    public Map test() {
        Map map = new HashMap() ;
        map.put("a","123") ;
        return map ;
    }
}

我们访问http://localhost:{port}/demo可以看到后台打印如下日志

 

springboot三种拦截器

 

可以看出他们的拦截顺序:filter—>Interceptor—->@Aspect 。以下这个图可以比较直观看出他们之间的拦截顺序

springboot三种拦截器

 

总结: 过滤器和拦截器的区别,过滤器是依赖于servlet容器(struts),在实现上基于函数回调,可以对几乎所有的请求进行过滤。但缺点是一个过滤器实例只能在容器初始化时调用一次,来进行过滤操作,获得我们想要的数据。

三者之间主要还是粒度的差异,应用场景的不同。

过滤器(Filter) :采用filter过滤器,可以获取http、http请求和响应,但无法获取与spring框架相关的信息,如哪个control处理,哪个方法处理,有哪些参数,这些都是无法获取的。

拦截器(Interceptor):采用interceptor拦截器,除了获取http、http请求和响应对象,还可以获取请求的类名、方法名,但拦截器无法获取请求参数的值。

切片 (Aspect) : 切片 aspect 可以获取传入的参数值,但无法获取原始的http,http请求和响应对象。



Tags:springboot   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
我是一名程序员关注我们吧,我们会多多分享技术和资源。进来的朋友,可以多了解下青锋的产品,已开源多个产品的架构版本。Thymeleaf版(开源)1、采用技术: springboot、layui、Thymel...【详细内容】
2021-12-14  Tags: springboot  点击:(20)  评论:(0)  加入收藏
前言项目中的配置文件会有密码的存在,例如数据库的密码、邮箱的密码、FTP的密码等。配置的密码以明文的方式暴露,并不是一种安全的方式,特别是大型项目的生产环境中,因为配置文...【详细内容】
2021-11-17  Tags: springboot  点击:(25)  评论:(0)  加入收藏
SpringBoot开发的物联网通信平台系统项目功能模块 功能 说明 MQTT 1.SSL支持 2.集群化部署时暂不支持retain&will类型消 UDP ...【详细内容】
2021-11-05  Tags: springboot  点击:(55)  评论:(0)  加入收藏
1. 介绍1.1 介绍今天开始我们来学习Java操作MySQL数据库的技巧,Java操作MySQL是借助JdbcTemplate这个对象来实现的。JdbcTemplate是一个多数据库集中解决方案,而我们今天只讲...【详细内容】
2021-11-05  Tags: springboot  点击:(30)  评论:(0)  加入收藏
SpringBoot中的Controller注册本篇将会以Servlet为切入点,通过源码来看web容器中的Controller是如何注册到HandlerMapping中。请求来了之后,web容器是如何根据请求路径找到对...【详细内容】
2021-11-04  Tags: springboot  点击:(52)  评论:(0)  加入收藏
环境:Springboot2.4.11环境配置接下来的演示都是基于如下接口进行。@RestController@RequestMapping("/exceptions")public class ExceptionsController { @GetMapping(...【详细内容】
2021-10-11  Tags: springboot  点击:(41)  评论:(0)  加入收藏
SpringBoot项目默认使用logback, 已经内置了 logback 的相关jar包,会从resource包下查找logback.xml, logback 文件格式范本 可直接复制使用,有控制台 info.log error.log三个...【详细内容】
2021-10-09  Tags: springboot  点击:(50)  评论:(0)  加入收藏
环境:Springboot2.4.10当应用程序启动时,Spring Boot将自动从以下位置查找并加载application.properties和application.yaml文件: 从Classpath类路径classpath的根类路径classp...【详细内容】
2021-09-26  Tags: springboot  点击:(76)  评论:(0)  加入收藏
搭建基础1. Intellij IDEA 2. jdk1.8 3. maven3.6.3搭建方式(1)在线创建项目Spring Boot 官方提供的一种创建方式,在浏览器中访问如下网址: https://start.spring.io/在打开的页...【详细内容】
2021-09-14  Tags: springboot  点击:(78)  评论:(0)  加入收藏
最近开发项目的时候需要用到对象的属性拷贝,以前也有用过一些复制框架,比如spring的 BeanUtils.copyProperties等方式,但总是不尽如人意,最近发现使用orika进行对象拷贝挺好用的...【详细内容】
2021-08-27  Tags: springboot  点击:(231)  评论:(0)  加入收藏
▌简易百科推荐
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了...【详细内容】
2021-12-23  Python阿杰    Tags:FastAPI   点击:(6)  评论:(0)  加入收藏
文章目录1、Quartz1.1 引入依赖<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version></dependency>...【详细内容】
2021-12-22  java老人头    Tags:框架   点击:(11)  评论:(0)  加入收藏
今天来梳理下 Spring 的整体脉络啦,为后面的文章做个铺垫~后面几篇文章应该会讲讲这些内容啦 Spring AOP 插件 (了好久都忘了 ) 分享下 4ye 在项目中利用 AOP + MybatisPlus 对...【详细内容】
2021-12-07  Java4ye    Tags:Spring   点击:(14)  评论:(0)  加入收藏
&emsp;前面通过入门案例介绍,我们发现在SpringSecurity中如果我们没有使用自定义的登录界面,那么SpringSecurity会给我们提供一个系统登录界面。但真实项目中我们一般都会使用...【详细内容】
2021-12-06  波哥带你学Java    Tags:SpringSecurity   点击:(18)  评论:(0)  加入收藏
React 简介 React 基本使用<div id="test"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js...【详细内容】
2021-11-30  清闲的帆船先生    Tags:框架   点击:(19)  评论:(0)  加入收藏
流水线(Pipeline)是把一个重复的过程分解为若干个子过程,使每个子过程与其他子过程并行进行的技术。本文主要介绍了诞生于云原生时代的流水线框架 Argo。 什么是流水线?在计算机...【详细内容】
2021-11-30  叼着猫的鱼    Tags:框架   点击:(21)  评论:(0)  加入收藏
TKinterThinter 是标准的python包,你可以在linx,macos,windows上使用它,你不需要安装它,因为它是python自带的扩展包。 它采用TCL的控制接口,你可以非常方便地写出图形界面,如...【详细内容】
2021-11-30    梦回故里归来  Tags:框架   点击:(26)  评论:(0)  加入收藏
前言项目中的配置文件会有密码的存在,例如数据库的密码、邮箱的密码、FTP的密码等。配置的密码以明文的方式暴露,并不是一种安全的方式,特别是大型项目的生产环境中,因为配置文...【详细内容】
2021-11-17  充满元气的java爱好者  博客园  Tags:SpringBoot   点击:(25)  评论:(0)  加入收藏
一、搭建环境1、创建数据库表和表结构create table account(id INT identity(1,1) primary key,name varchar(20),[money] DECIMAL2、创建maven的工程SSM,在pom.xml文件引入...【详细内容】
2021-11-11  AT小白在线中  搜狐号  Tags:开发框架   点击:(29)  评论:(0)  加入收藏
SpringBoot开发的物联网通信平台系统项目功能模块 功能 说明 MQTT 1.SSL支持 2.集群化部署时暂不支持retain&will类型消 UDP ...【详细内容】
2021-11-05  小程序建站    Tags:SpringBoot   点击:(55)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条