Filter、Interceptor、Aspect拦截机制的区别

    在使用Spring MVC开发TEST API的时候,咱们进场会使用Java的拦截机制来处理请求,Filter是Java自己自带拦过滤器,Interceptor则是Spring自带的拦截器,而Aspect是Spring AOP主要的使用场景有:日志记录、事务控制和异常处理,该篇文章主要说说它们是如何实现以及他们之间的差异。java

Filter

    我对Filter过滤器作了如下总结:web

Filter的实现方式

@Component
public class TimeFilter implements Filter {
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("初始化TimeFilter...");
    }

 
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("-------TimeFilter Start--------");
        long start = new Date().getTime();
        filterChain.doFilter(request, response);
        System.out.println("TimeFilter执行耗时:" + (new Date().getTime() - start));
        System.out.println("-------TimeFilter End--------");
    }

    @Override
    public void destroy() {
        System.out.println("销毁TimeFilter...");
    }
}

    注意:关于filterChain.doFilter(request,response,filterChain),执行filterChain.doFilter的意思是将请求转发给过滤器脸上的下一个对象,若是没有filter那就是你请求的资源。 通常filter都是一个链,web.xml 里面配置了几个就有几个。一个一个的连在一块儿 这里指的是下一个Filter,request->filter1->filter2->filter3->...->response。app

    咱们定义完Filter以后,若是咱们不使用@Component注解注入,可使用另外一种方式将Filter注入到咱们的容器中,这里使用@Bean的形式定义,经过继承WebMvcConfigurerAdapter抽象类来实现配置,最后返回registrationBean,这个方法主要有两个好处就是第一咱们能够经过 registrationBean.setUrlPatterns(urls) 来指明filter在哪些路径下起做用,第二咱们可使用该方法区注入第三方的filter,缘由的不少地方放的filter并并非以@Component注入方式,这时候咱们就不能使用@Component第一种方式来注入了:ide

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Autowired
    TimeInterceptor timeInterceptor;

    @Bean
    public FilterRegistrationBean charsetFilter(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();

        TimeFilter timeFilter = new TimeFilter();
        CharsetFilter charsetFilter = new CharsetFilter();
        registrationBean.setFilter(charsetFilter);
        registrationBean.setFilter(timeFilter);

        //至关于@webFilter的@WebInitParam()注解的做用
        Map<String,String> paramMap = new HashMap<>();
        paramMap.put("charset","utf-8");
        registrationBean.setInitParameters(paramMap);

        //至关于@webFilter的 urlPatterns = "/*"的做用
        List<String> urls = new ArrayList<>();
        urls.add("/*");
        //urls.add("/user/*");
        registrationBean.setUrlPatterns(urls);

        return registrationBean;
    }

咱们在controller中定义一个getInfo()方法:post

//请求路径的{id}回传到方法里也就是传到(@PathVariable String id)的id里
    @RequestMapping(value = "/user/{id:\\d+}",method = RequestMethod.GET)
    @JsonView(User.UserDetailView.class)    //这里由于UserDetailView继承了UserSimpleView全部会返回username和password
    @ApiOperation("获取用户信息")
    public User getInfo(@PathVariable Integer id) {

//        throw new UserNotExistException(id);
        System.out.println("进入getInfo()服务");
        User user = new User();
        user.setId(1);
        user.setUsername("jacklin");
        user.setPassword("123");
        return user;
    }

当咱们调用controller中的getInfo()方法的时候,看看请求响应是否成以及控制台的输出:url

GET请求发送成功,返回200,控制台输出以下:spa

从上述结果,咱们能够分析得出,当客户端发送请求,到达Controller方法以前,先执行Filter初始化操做,接着进入Controller的方法体,最后执行完成,经过分析咱们明白了Filter的工做原理和方法的执行顺序!3d

Interceptor

    我对Interceptor过滤器作了如下总结(导图中加粗部分是重点):日志

Interceptor拦截器的实现方式

**
 * @Author 林必昭
 * @Date 2019/7/4 13:15
 */

@Component
public class TimeInterceptor implements HandlerInterceptor {

    /**
     * preHandle方法的返回值是boolean值,当返回的是false时候,不会进入controller里的方法
     */
    @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;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("------->postHandle");
        long start = new Date().getTime();
        System.out.println("TimeInterceptor执行耗时:"+" "+(new Date().getTime()-start));
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) throws Exception {
        System.out.println("------->afterCompletion");
        long start = new Date().getTime();
        System.out.println("TimeInterceptor执行耗时:"+" "+(new Date().getTime()-start));
        System.out.println("Exception is "+ e);
    }
}

一样,咱们经过发送请求,观察控制台的输出,来分析结果:code

从TimeInterceptor拦截器结果,咱们能够分析得出,当客户端发送请求,到达Controller方法以前,先执行Interceptor的preHandler方法,接着进入Controller的方法体,咱们能够获取到对应的Controller,接着执行postHandler方法,最后执行完成!

Aspect

    我对Aspect过滤器作了如下总结:

相关文章
相关标签/搜索