springboot中filter、interceptor的区别和实例
前言:从概念上来讲,filter是servlet规范定义的,而interceptor是spring定义的。 作用在什么位置? 一次会话,请求在进入servlet容器执行service()方法之前就会经过filter过滤(上图步骤1),在离开servlet容器相应客户端的时候也会经过过滤器(上图步骤7)。而interceptor,分两种情况,一种是对会话的拦截,需要定义类实现sp...
前言:从概念上来讲,filter是servlet规范定义的,而interceptor是spring定义的。
作用在什么位置?
一次会话,请求在进入servlet容器执行service()方法之前就会经过filter过滤(上图步骤1),在离开servlet容器相应客户端的时候也会经过过滤器(上图步骤7)。而interceptor,分两种情况,一种是对会话的拦截,需要定义类实现spring的org.springframework.web.servlet.HandlerInterceptor接口并注册到mvc的拦截队列中,其中preHandle()方法在调用Handler之前进行拦截(上图步骤3),postHandle()方法在视图渲染之前调用(上图步骤5.5),afterCompletion()方法在返回相应之前执行(上图步骤6.5);另一种是对方法的拦截,需要使用@Aspect注解,在每次调用指定方法的前、后进行拦截。
下面通过代码详述他们之间的区别:
先写一个controller方法,进行测试。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/intercepter")
public class InterceptorController {
@GetMapping("/pre")
public String preHandleTest(){
System.out.println("boom!!!!导弹击中我方指挥部!!");
return "wow";
}
}
filter产生的效果
该filter拦截器对上述controller方法进行过滤
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@Component//注入ioc容器
@WebFilter(filterName = "urlFilter",urlPatterns = "/intercepter/pre")//配置拦截路径
public class UrlFilter implements Filter {
//filter初始化的时候调用,即web容器启动时调用
//web容器启动时根据web.xml文件,依次加载ServletContext----》listener---》filter----》servlet
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("【安全过滤雷达已经开启】");
}
//filter执行功能,根据参数来看,可以对request,response和chain(是否放行)进行操作
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("【不明飞行物穿过大气层】");//请求进入servlet之前调用
chain.doFilter(request,response);//请求放行,允许进入servlet,可手动禁止放行
System.out.println("【不明飞行物已经解除警报】");//请求从servlet出来返回客户端之前调用
System.exit(0);
}
//filter在服务器正常关闭(比如System.exit(0))等情况下会调用。
@Override
public void destroy() {
System.out.println("【安全过滤雷达已经关闭】");
}
}
启动时:
2018-07-19 12:18:51.122 INFO 10428 --- [ost-startStop-1]
【安全过滤雷达已经开启】
2018-07-19 12:18:51.572 INFO 10428 --- [ main]
执行结果:
【不明飞行物穿过大气层】
boom!!!!导弹击中我方指挥部!!
【不明飞行物已经解除警报】
服务器正常关闭:
2018-07-19 12:21:49.042 INFO 6812 --- [ Thread-12]
【安全过滤雷达已经关闭】
interceptor产生的效果
interceptor对请求进行拦截
现在加上interceptor,首先定义interceptor:
package com.peilian.practice.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class PreIntercepterDemo implements HandlerInterceptor {
//在HandlerMapping获取handler之后,调用handler之前调用该方法,可以对request,response和handler进行操作
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("--------导弹拦截失败!!--------");
return true;
}
//在调用handler之后,视图渲染之前调用,可以对中request,response,handler,modelAndView进行操作
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("--------司令部被摧毁-----!!!");
}
//在视图渲染之后,返回客户端之前调用,可以对request,response,handler以及handler产生的异常信息ex进行操作
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("---------重新开启司令部-------");
}
}
然后对interceptor进行注册:
import com.peilian.practice.interceptor.PreIntercepterDemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@SpringBootConfiguration
public class MyWebMvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private PreIntercepterDemo preIntercepterDemo;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册拦截器并配置拦截的路径
registry.addInterceptor(preIntercepterDemo).addPathPatterns("/intercepter/pre");
}
}
运行结果:
【不明飞行物穿过大气层】
--------导弹拦截失败!!--------
boom!!!!导弹击中我方指挥部!!
--------司令部被摧毁-----!!!
---------重新开启司令部-------
【不明飞行物已经解除警报】
interceptor对方法进行拦截
被拦截的方法:
import org.springframework.stereotype.Component;
@Component
public class AspectDemo {
public void attack(){
System.out.println("》》》攻击《《《");
}
}
拦截器定义:
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class EnhanceMonitor {
//定义切点
@Pointcut("execution(* com.peilian.*..attack(..))")
public void pointCutMethod(){}
//前置
@Before("pointCutMethod()")
public void magicEnhance1(){
System.out.println("----冰霜特效----");
}
//前置
@Before("pointCutMethod()")
public void magicEnhance2(){
System.out.println("----火焰特效----");
}
//后置
@After("pointCutMethod()")
public void afterAttack(){
System.out.println("---攻击后僵直---");
}
/*环绕
@Around("pointCutMethod()")
public void buffAttack(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("----骑士光环---");
pjp.proceed();
System.out.println("-----骑士光环消失----");
}*/
}
运行结果:
----冰霜特效----
----火焰特效----
》》》攻击《《《
---攻击后僵直---
环绕通知开启后,运行结果:
----骑士光环---
----冰霜特效----
----火焰特效----
》》》攻击《《《
-----骑士光环消失----
---攻击后僵直---
可见,@Around总是在@Before和@After之前运行。另外,还有其他如@AfterReturning和@AfterThrowing,读者请自行百度。
简单总结
过滤器和拦截器在对请求进行拦截时,一个是发生的时机不一样,filter是在servlet容器外,interceptor在servlet容器内,且可以对请求的3个关键步骤进行拦截处理。另外filter在过滤是只能对request和response进行操作,而interceptor可以对request、response、handler、modelAndView、exception进行操作。
如有异议,可至邮 zwh_mc@sina.com,欢迎指正。
更多推荐
所有评论(0)