今天有人问我怎么实现访问项目的时候,把一些请求存下来,我一听,我就说 拦截器啊,然后自己回家也试了试,发现注入service的时候会报null,因为 filter不能直接注入 spring容器里面的对象,然后我就自己从spring 容器里面去取了。代码如下

1.Filter 配置

@Configuration
public class UrlFilter implements Filter {

    @Autowired
    private UserInfoService userInfoService;

    @Bean
    public FilterRegistrationBean setBean(){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter( new UrlFilter() );
        bean.addUrlPatterns("/*");
        System.out.println("注入了 filter");
        return bean;
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        String url = request.getRequestURI() ;

        // 获取 servlet上下文
        ServletContext sc = request.getSession().getServletContext();
        // 获取 spring 容器
        AbstractApplicationContext cxt = (AbstractApplicationContext) WebApplicationContextUtils.getWebApplicationContext(sc);
        if(cxt != null && cxt.getBean("userInfoService") != null && userInfoService == null){
            // 取出 userInfoService
            userInfoService = (UserInfoService) cxt.getBean("userInfoService");
        }

        UserInfo userInfo = new UserInfo();
        userInfo.setTitle( url );
        userInfo.setPassword("filter");
        userInfo.setUsername("filter");
        userInfoService.insert(userInfo);

        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

因为这里直接获取不到 spring容器的service,所以我这里直接从spring容器里面去取

2.HandlerInterceptor拦截器实现

我把过滤器的写好了,发给她后,她说他现在用拦截器写的,说不想改了,我想也罢,就用拦截器写把

首先说一下,拦截器和过滤器的一个区别,过滤器不支持  @Autowired 注入,但是 拦截器支持  @Autowired注入的

所以,我们的代码就可以这样写了

拦截器代码:

@Configuration
public class URLHandlerInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private UserInfoService userInfoService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String url = request.getRequestURI() ;

        UserInfo userInfo = new UserInfo();
        userInfo.setTitle( url );
        userInfo.setPassword("handle");
        userInfo.setUsername("handle");
        userInfoService.insert(userInfo);

        // false 前端会显示 200
        // true 前端显示 404
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {
        // 放行
        super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 放行
        super.afterCompletion(request, response, handler, ex);
    }

}

拦截器配置:(此处重要,这里配置对了,@Autowired才注入的进去)

@Configuration
public class URLHandlerConfig implements WebMvcConfigurer  {

    @Bean
    public URLHandlerInterceptor setBean2(){
        System.out.println("注入了handler");
        return new URLHandlerInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        // 多个拦截器组成一个拦截器链
        // addPathPatterns 用于添加拦截规则
        // excludePathPatterns 用户排除拦截
        //由于spring boot 2.x依赖的spring 5.x版本,使用spring 5.x时,静态资源也会执行自定义的拦截器
        //所有导致静态资源不可访问的问题
        String [] exculudes = new String[]{"/*.html","/html/**","/js/**","/css/**","/images/**"};
        registry.addInterceptor(setBean2()).addPathPatterns("/**").excludePathPatterns(exculudes);

    }

}

此处的  addInterceptors 里面的  registry.addInterceptor() 参数直接写 上面 serBean2() 这样才注入的进去,才是从 spring 容器里面取得

由于spring boot 2.x依赖的spring 5.x版本,使用spring 5.x时,静态资源也会执行自定义的拦截器,所以这里得配置一下排除

3.访问效果:

可以看到,过滤器也执行了,拦截器也执行了,存入了两条数据金数据库了,就是我的访问地址,因为我的getAll方法获取的就是这张表的数据,所以全都出来了。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐