springboot使用过滤器、拦截器、切片

一、springboot中过滤器、拦截器和切片(Aspect)的描述及区别

1、描述:

(1)过滤器(Filter):是servlet容器实现的功能,使用时需要引入 Servlet 依赖。其可以对所有请求进行过滤,其在容器启动时进行一次初始化调用init方法,容器关闭时调用销毁方法。主要用于对 请求和响应做一些信息过滤,或者设置及销毁一些参数信息。如修改字符编码、在request加入参数、对请求进行拦截、通过request的session判断用户登录状态等。

(2)拦截器(Interceptor):是spring框架实现的功能,在实现上是基于Java的反射机制,一个拦截器实例在一个controller生命周期之内可以多次调用。只能对controller定义的方法进行拦截,但是对静态资源的请求则没办法进行拦截处理。

(3)切片(Aspect):即spring的AOP功能,面向切面编程,使用时需要引入 aop 依赖。定义切入点(在哪些方法起作用、什么时候起作用)以及在切入点执行的方法。

2、区别:

  1. 执行顺序:Filter 、Interceptor、Aspect的执行顺序为:Filter  -> Interceptor -> Aspect
  2. 获取的信息:Filter 在controller(方法)前调用,只能获取到请求和响应,不知道在那个控制器、方法处理,所以不能获取到调用的方法名,方法参数等信息(因为其为servlet定义,不知道spring定义的东西);Interceptor 能获取到方法名但无法获取到方法参数,可以看源码是因为controller方法的方法参数是在调用 Interceptor 后才设置进去的;Aspect 可以获取到方法名称、方法参数等信息。
  3. 使用:自定义Filter 需要实现 Filter 接口并加上@Component注解就会被容器注入bean进行使用;自定义Interceptor 需要实现HandlerInterceptor 接口并加上@Component注解,同时还要写一个实现 WebMvcConfigurer 接口的bean,在该bean中重写addInterceptors方法,方法中需要讲自定义的 Interceptor  加入InterceptorRegistry;自定义Aspect 需要在类上加 @Component、@Aspect两个注解,同时编写切面方法,在方法上添加对应注解表达在哪里执行,执行的节点等信息。
  4. 异常获取:如果项目中加了 @ControllerAdvice的统一异常处理器,则顺序变为 Filter  -> Interceptor -> ControllerAdvice ->Aspect -> controller。即controller抛出异常后只有Aspect 能够获取到异常信息,之后异常信息就被 ControllerAdvice 获取并进行统一的处理,而 Filter 、 Interceptor 无法直接获取到 controller抛出的异常信息

二、使用

1、过滤器

//过滤器名称为loginFilter,拦截/desktop,/hello的请求
//使用@Order是没办法控制多个过滤器顺序的,只能使用 FilterRegistrationBean
@WebFilter(filterName="loginFilter",urlPatterns={"/desktop","/hello/*"})
//@Component
public class LoginFilter implements Filter
{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("filter初始化");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("=====进去filter");
		//设置request请求编码等  
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		chain.doFilter(request, response);  //传给下一个过滤器
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
	}
}

当有多个过滤器,且需要控制其执行顺序时,过滤器注释掉 @WebFilter,改为@Component

然后在启动类(获取其他@Configuration注解的bean)写如下代码

	@Autowired
	private LoginFilter loginFilter;
	
	@Bean
	public FilterRegistrationBean filterRegistrationBean(){
		FilterRegistrationBean registrationBean = new FilterRegistrationBean();
		registrationBean.setFilter(loginFilter);
		registrationBean.setName("loginFilter");
		registrationBean.addUrlPatterns("/face/*");
		registrationBean.setOrder(3); //order越小越先执行
		return registrationBean;
	}

2、拦截器

定义拦截器实现类,实现 HandlerInterceptor

@Component
public class LoginInterceptor implements HandlerInterceptor
{
	@Override
	public boolean preHandle(HttpServletRequest request ,
			HttpServletResponse response, Object handler)throws Exception{
		System.out.println("========拦截");
                //获取类名
                ((HandlerMethod)handler).getBean().getClass().getName();
                //获取方法名
                ((HandlerMethod)handler).getMethod().getName();
		System.out.println(request.getContentType());
		return true;  //返回false则controller的方法不会执行
	}
	
	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler, ModelAndView model)throws Exception{
		//处理请求完成后视图渲染之前的处理操作,controller异常则不执行
	}
	
	@Override
	public void afterCompletion(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception e)throws Exception{
		//视图渲染之后的处理操作,controller异常仍执行
	}
}

需要在实现WebMvcConfigurer类中加入该拦截器,拦截器才能生效

@Configuration
public class Webconfigurer implements WebMvcConfigurer
{
	@Autowired
	private LoginInterceptor loginInterceptor;

        //拦截除	/login /register 外的所有请求
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login","/register");
		
	}
}

3、Aspect

定义切片实现类,添加@Aspect注解

@Aspect
@Component
public class MyAspect {
    @Around("execution(* com.example.security.controller.HelloController.*(..))")
    public Object handleAspect(ProceedingJoinPoint pjp) throws Throwable {
        Object[] args = pjp.getArgs();
        //打印方法中的所有参数
        Arrays.stream(args).forEach(System.out::println);
        //调用对应切入点的方法
        Object o = pjp.proceed();
        return null;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值