拦截器、过滤器、Aspect区别?看这一篇就够了!

通俗易懂的解释:

过滤器:像滤网一样,肯定是用来过滤东西的,比如,三个请求只放行两个。

拦截器:拦而不截,都可以过,但是要过去的东西做点操作,比如,三个请求都放行。

具体区别:

 过滤器拦截器Aspect
关注的点所有web请求部分web请求偏向于业务层面的拦截
实现原理函数回调JAVA反射机制(动态代理)动态代理
是否依赖servlet容器依赖不依赖不依赖
servlet提供的支持Filter接口
spring提供的支持HandlerInterceptorAdapter类、HandlerInterceptor接口@Aspect
作用级别系统级非系统级皆可
可能需要实现的方法doFilterpreHandle、postHandle、afterCompletionBefore、After、Around

本质区别:

 从灵活性上说拦截器功能更强大些,Filter能做的事情,他都能做,而且可以在请求前,请求后执行,比较灵活。Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验(比较泛的,比如登录不登录之类),太细的话,还是建议用interceptor。不过还是根据不同情况选择合适的。但是Aspect能够做到方法级更细的操作。

具体应用场景:

拦截器:

preHandle在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制等处理,也可以配合postHandle可以测某个方法的运行时间,不过arthas工具可以测方法的运行效率,详细可以看下代码排查利器Arthas介绍

postHandle在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView; 

afterCompletion在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面),可以根据ex是否为null判断是否发生了异常,进行日志记录

过滤器:

统一字符编码设置,实现跨域请求,登录日志记录,登录校验,解决需要多次读取Request中携带的数据流,但是默认的只能读取一次的问题(https://www.cnblogs.com/JAYIT/p/10943155.html

Aspect:

主要用于方法运行前后日志的插入。

代码展示:

拦截器:

//在这个例子中,我们假设UserController中的注册操作只在9:00-12:00开放,那么就可以使用拦截器实现这个功能。 
public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter {  
    private int openingTime;  
    private int closingTime;  
    private String mappingURL;//利用正则映射到需要拦截的路径  
    public void setOpeningTime(int openingTime) {  
        this.openingTime = openingTime;  
    }  
    public void setClosingTime(int closingTime) {  
        this.closingTime = closingTime;  
    }  
    public void setMappingURL(String mappingURL) {  
        this.mappingURL = mappingURL;  
    }  
    @Override  
    public boolean preHandle(HttpServletRequest request,  
            HttpServletResponse response, Object handler) throws Exception {  
        String url=request.getRequestURL().toString();  
        if(mappingURL==null || url.matches(mappingURL)){  
            Calendar c=Calendar.getInstance();  
            c.setTime(new Date());  
            int now=c.get(Calendar.HOUR_OF_DAY);  
            if(now<openingTime || now>closingTime){  
                request.setAttribute("msg", "注册开放时间:9:00-12:00");  
                request.getRequestDispatcher("/msg.jsp").forward(request, response);  
                return false;  
            }  
            return true;  
        }  
        return true;  
    }  
}

过滤器:

//过滤器控制编码
public class EnCodingFilter implements Filter {

    public void destroy() {

    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filter)
            throws IOException, ServletException {
        HttpServletRequest request1 = (HttpServletRequest)request;
        HttpServletResponse response1 = (HttpServletResponse)response;

        //预处理
        request1.setCharacterEncoding("UTF-8");
        response1.setCharacterEncoding("UTF-8");

        //
        filter.doFilter(request, response);
    }

    public void init(FilterConfig arg0) throws ServletException {

    }

}

Aspect:

@Component("annotationTest")
@Aspect
public class AnnotationTest {
    //定义切点
    @Pointcut("execution(* *.saying(..))")
    public void sayings(){}
    @Before("sayings()")
    public void sayHello(){
        System.out.println("注解类型前置通知");
    }
    //后置通知
    @After("sayings()")
    public void sayGoodbey(){
        System.out.println("注解类型后置通知");
    }
    //环绕通知。注意要有ProceedingJoinPoint参数传入。
    @Around("sayings()")
    public void sayAround(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("注解类型环绕通知..环绕前");
        pjp.proceed();//执行方法
        System.out.println("注解类型环绕通知..环绕后");
    }
}

总结:

三者功能类似,但各有优势,从过滤器--》拦截器--》切面,拦截规则越来越细致,执行顺序依次是过滤器、拦截器、切面。一般情况下数据被过滤的时机越早对服务的性能影响越小,因此我们在编写相对比较公用的代码时,优先考虑过滤器,然后是拦截器,最后是aop。比如权限校验,一般情况下,所有的请求都需要做登陆校验,此时就应该使用过滤器在最顶层做校验;日志记录,一般日志只会针对部分逻辑做日志记录,而且牵扯到业务逻辑完成前后的日志记录,因此使用过滤器不能细致地划分模块,此时应该考虑拦截器,然而拦截器也是依据URL做规则匹配,因此相对来说不够细致,因此我们会考虑到使用AOP实现,AOP可以针对代码的方法级别做拦截,很适合日志功能。参考博文:

https://blog.csdn.net/dingfei136913/article/details/78840672

https://blog.csdn.net/Jintao_Ma/article/details/52972482

https://www.cnblogs.com/EasonJim/p/7704740.html

https://www.cnblogs.com/caijh/p/7154691.html

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值