使用SpringMVC开发Restful API(2)-使用Filter、Interceptor对请求进行拦截和处理拦截顺序

一 使用Filter拦截请求:

1.使用Filter拦截只需要我们定义一个类并实现javax.servlet.Filter接口,然后将其注册为bean即可。

示例:

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.springframework.stereotype.Component;

@Component
public class MyFilter implements Filter{

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        
        System.out.println("MyFilter.init()");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        System.out.println("MyFilter.doFilter()");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        System.out.println("MyFilter.destroy()");
        
    }

}

其中:

  init():方法会在Filter初始化的时候被调用。

  destroy():方法会在Filter销毁的时候被调用。

  doFilter():这是Filter中最重要的一个方法,这个方法会在每次过滤指定URL的时候被调用,其中,chain.doFilter(request, response)表示这个Filter过滤的URL是否需要发送给下一个Filter,如果不写,表示请求将在该Filter被拦截,不会往下执行,当然也不会进入ServletController

2.只是将一个Filter注册成一个Bean固然可用,但是他会拦截所有的URL,无法拦截指定的URL,当我们需要拦截指定URL时,我们还可以在配置类中注册FilterBean

示例:

@Configuration
public class MyConfiguration {

    @Bean
    public FilterRegistrationBean myFilter() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new MyFilter());
        List<String> filterUrls = new ArrayList<>();
        filterUrls.add("/user/*");
        filterRegistrationBean.setUrlPatterns(filterUrls);
        return filterRegistrationBean;
    }
}

这样我们就可以用Filter拦截指定的URL

我们会发现,Filter虽然拦截了URL,但无法发现拦截的具体是哪个URL地址,也不知道调用了哪个Controller。想要知道拦截的具体是哪个URL地址,调用了哪个Controller,我们就得用到Interceptor

二  使用Interceptor拦截请求:

1.使用Interceptor我们只需要定义一个类并实现org.springframework.web.servlet.HandlerInterceptor接口。HandlerInterceptor有三个方法,具体作用如下:

  boolean preHandle()  这个方法会在进入具体Controller之前被调用,他的Object handler参数会记录这次请求会发送给哪个Controller,如果返回为true才会进入具体的Controller,否则会被拦截。

  postHandle()  这个方法会在具体的Controller方法处理完之后被调用,注意:如果Controller没有处理完就报了异常,那么这个方法就不会被调用。

  afterCompletion()  这个方法无论Controller有没有抛出异常都会被调用,如果抛出了异常,那么他的Exception ex参数会接收到异常信息。

示例:

@Component
public class MyInterceptor implements HandlerInterceptor{
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println(((HandlerMethod)handler).getMethod().getName());
        System.out.println("MyInterceptor.preHandle()");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor.postHandle()");    
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("MyInterceptor.afterCompletion()");
    }

}

仅仅是将Interceptor注册成Bean还不行,我们还得将该Bean添加到InterceptRegistry中,添加方法如下:

@Configuration
public class MyConfiguration extends WebMvcConfigurerAdapter{

    @Autowired
    private MyInterceptor myInterceptor;
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor);
    }
    
}

这样一个Interceptor就完成了。

注意:标注了@ControllerAdvice的异常处理的Bean会在afterCompletion()方法之前捕获异常,如果@ControllerAdvice的类中的方法处理了该异常,那么异常就不会被传到afterCompletion()方法中,只有@ControllerAdvice的类中的方法没处理到该异常,那么该异常才会进入afterCompletion()方法的Exception ex参数中。

我们会发现Interceptor虽然可以知道具体会调用哪个Controller,但并不知道调用该Controller中的方法的具体入参是多少,想要知道入参是多少,得用到Aspect,具体请参见Spring核心功能之一之AOP。

三  SpringMVC处理拦截的的顺序为:Filter -> Interceptor -> ControllerAdvice -> Aspect -> Controller异常返回的顺序则相反

猜你喜欢

转载自www.cnblogs.com/programmlover/p/10575631.html