一 使用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被拦截,不会往下执行,当然也不会进入Servlet或Controller。
2.只是将一个Filter注册成一个Bean固然可用,但是他会拦截所有的URL,无法拦截指定的URL,当我们需要拦截指定URL时,我们还可以在配置类中注册Filter的Bean
示例:
@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,异常返回的顺序则相反。
原文地址:https://www.cnblogs.com/programmlover/p/10575631.html