您的位置:首页 > 编程语言 > Java开发

springboot中filter、interceptor的区别和实例

2018-07-19 12:45 537 查看

前言:从概念上来讲,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方法,进行测试。

[code]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方法进行过滤

[code]
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("【安全过滤雷达已经关闭】");

}
}

启动时:

[code]2018-07-19 12:18:51.122  INFO 10428 --- [ost-startStop-1]
【安全过滤雷达已经开启】
2018-07-19 12:18:51.572  INFO 10428 --- [           main]

执行结果:

[code]【不明飞行物穿过大气层】
boom!!!!导弹击中我方指挥部!!
【不明飞行物已经解除警报】

服务器正常关闭:

[code]2018-07-19 12:21:49.042  INFO 6812 --- [      Thread-12]
【安全过滤雷达已经关闭】

 

interceptor产生的效果

 

interceptor对请求进行拦截

现在加上interceptor,首先定义interceptor:

[code]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进行注册:

[code]
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");
}
}

运行结果:

[code]【不明飞行物穿过大气层】
--------导弹拦截失败!!--------
boom!!!!导弹击中我方指挥部!!
--------司令部被摧毁-----!!!
---------重新开启司令部-------
【不明飞行物已经解除警报】

interceptor对方法进行拦截

被拦截的方法:

[code]import org.springframework.stereotype.Component;

@Component
public class AspectDemo {

public void attack(){
System.out.println("》》》攻击《《《");
}
}

拦截器定义:

[code]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("-----骑士光环消失----");
}*/
}

运行结果:

[code]----冰霜特效----
----火焰特效----
》》》攻击《《《
---攻击后僵直---

环绕通知开启后,运行结果:

[code]----骑士光环---
----冰霜特效----
----火焰特效----
》》》攻击《《《
-----骑士光环消失----
---攻击后僵直---

可见,@Around总是在@Before和@After之前运行。另外,还有其他如@AfterReturning和@AfterThrowing,读者请自行百度。

 

简单总结

过滤器和拦截器在对请求进行拦截时,一个是发生的时机不一样,filter是在servlet容器外,interceptor在servlet容器内,且可以对请求的3个关键步骤进行拦截处理。另外filter在过滤是只能对request和response进行操作,而interceptor可以对request、response、handler、modelAndView、exception进行操作。

如有异议,可至邮   zwh_mc@sina.com,欢迎指正。

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: