美文网首页Java程序栈程序员IT技术篇
基于spring的三种拦截机制

基于spring的三种拦截机制

作者: 一直想上树的猪 | 来源:发表于2018-12-26 16:56 被阅读2次

首先说一下为什么引出这三种拦截机制

在某些应用场景下,对于一个用户而言,我们需要在他访问接口的时候去进行一系列的校验(身份、权限、系统关系等),同时也为了防止恶意攻击,出于系统内部的安全性考虑,有必要去进行加入拦截机制

三种拦截机制:包括最原始的filter、interceptor、aspect

一、Filter

创建filter类来实现Filter(servlet包下)类,实现init、doFilter和destory方法,在doFilter方法中去拦截请求,要想使Filter起作用:可以在过滤器类上添加注解@Component去拦截所有的请求,还可以通过配置去给特定的url去起作用,如下:

过滤器配置
但是使用Fiter并不能知道哪个请求是用哪个过滤器的什么方法去处理的,因为所有的请求都是基于spring的。

二、interceptor

是Spring框架本身提供的。拦截器会拦截所有控制器

@Component
public class TimeInterceptor implements HandlerInterceptor {
    /**
     * 在控制器的方法调用之前调用
     * @param request
     * @param response
     * @param handler   比filter多的一个参数,真正用来处理逻辑的一个参数
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle");
        //打印类名和方法名
        System.out.println(((HandlerMethod)handler).getBean().getClass().getName());
        System.out.println(((HandlerMethod)handler).getMethod().getName());
        request.setAttribute("startTime",new Date().getTime());

        return true;
    }

    /**
     * 在控制器的方法调用之后调用,但是抛出异常之后不会进入这个方法
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
        Long start = (Long) request.getAttribute("startTime");
//        request.setAttribute("endTime",new Date().getTime()-);
        System.out.println("postHandle请求耗时:"+ (new Date().getTime() - start));
    }

    /**
     * 不管是正常调用还是抛出异常都会被调用
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
        Long start = (Long) request.getAttribute("startTime");
//        request.setAttribute("endTime",new Date().getTime()-);
        System.out.println("afterCompletion请求耗时:"+ (new Date().getTime() - start));
        System.out.println("ex is " + ex);
    }
}

写完之后并不会生效,还需要去对其进行注册,注册的代码:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private TimeInterceptor timeInterceptor;

    //拦截器的注册器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(timeInterceptor);
    }
}

这样,拦截器就会拦截所有的请求。
注意:在拦截器中,handler是用来过滤的方法,但是这个方法只能获取到此次请求所用到的那个类和那个方法,并不能看到传递的参数以及传递的对象。追踪源码:在DispatcherServlet中的doService方法里面调用了doDispatcher()方法,在doDispatcher()方法中有一个appplyPreHandle方法,这个方法就是去调用我们写的那个拦截器的preHandle方法,只有在preHandle方法返回true的时候才往下执行,下面会调用handle方法,在这个方法中会对请求中传递的参数进行拼装,将传递的JSON字符串等数据组装成我们需要的一些自定义对象。所以,采用拦截器的方法虽然能知道此次请求调用的类和方法,但是并不能知道请求中传递的参数,如果需要知道传递的参数,则需要使用切片(Aspect)的方式。

三、Aspect

这种方式主要使用了Spring的AOP的思想


AOP思想

1.切入点

四个注解用来控制什么时候起作用:

  • @before 调用方法之前
  • @after 调用方法之后
  • @afterThrowing 调用方法之后,如果指定的方法抛出异常,则执行这个
  • @around 完全覆盖了之前的三种,都可以用这种方式

2.Aspect实现

AspectJ实现

其中,注解中的表达式可以参考面向切面编程表达式的写法
我们推荐使用这个去进行拦截,但是缺点是拿不到原始的http请求和响应的那两个对象

四、拦截顺序

三种拦截机制的拦截顺序

相关文章

网友评论

    本文标题:基于spring的三种拦截机制

    本文链接:https://www.haomeiwen.com/subject/mlzhlqtx.html