前言
在SpringBoot中使用REST服务时,往往需要对Controller层
的请求进行拦截或者获取请求数据和返回数据,就需要过滤器、拦截器或者切片。
执行请求的处理顺序:过滤器(Filter)> 拦截器(Interceptor)> 切片(Aspect)
过滤器(Filter)
过滤器(Filter):对HttpServletRequest
处理,也可以对HttpServletResponse
进行后处理,无法获取请求方法的信息。
方式一:注解方式
项目启动类,需要加上 @ServletComponentScan
注解
TestFilter 使用注解的方式过滤,在class上面加上 @Component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets;
@Component @WebFilter(urlPatterns = "/*") public class TestFilter implements Filter {
@Override public void destroy() { System.out.println("===== 销毁 TestFilter过滤器 ====="); }
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("===== TestFilter过滤器,开始 ====="); long start = new Date().getTime(); chain.doFilter(request, response); System.out.println("TestFilter过滤器,耗时:" + (new Date().getTime() - start)); System.out.println("===== TestFilter过滤器,结束 ====="); }
@Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("===== 初始化 TestFilter过滤器 ====="); } }
|
属性名 |
类型 |
释义 |
filterName |
String |
指定过滤器的 name 属性,等价于 |
value |
String[] |
该属性等价于 urlPatterns 属性。但是两者不应该同时使用。 |
urlPatterns |
String[] |
指定一组过滤器的 URL 匹配模式。等价于标签。 |
servletNames |
String[] |
指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中的取值。 |
dispatcherTypes |
DispatcherType |
指定过滤器的转发模式。具体取值包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。 |
initParams |
WebInitParam[] |
指定一组过滤器初始化参数,等价于标签。 |
asyncSupported |
boolean |
声明过滤器是否支持异步操作模式,等价于标签。 |
description |
String |
该过滤器的描述信息,等价于标签。 |
displayName |
String |
该过滤器的显示名,通常配合工具使用,等价于标签。 |
方式二:配置文件方式
TestFilter 使用配置文件的方式过滤,添加过滤文件WebConfig
使用这种方式,TestFilter不需要
加@Component
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets;
public class TestFilter implements Filter {
@Override public void destroy() { System.out.println("===== 销毁 TestFilter过滤器 ====="); }
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("===== TestFilter过滤器,开始 ====="); long start = new Date().getTime(); chain.doFilter(request, response); System.out.println("TestFilter过滤器,耗时:" + (new Date().getTime() - start)); System.out.println("===== TestFilter过滤器,结束 ====="); }
@Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("===== 初始化 TestFilter过滤器 ====="); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import java.util.ArrayList; import java.util.List;
@Configuration public class WebConfig extends WebMvcConfigurerAdapter {
@Bean public FilterRegistrationBean timeFilter() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); ResponseFilter filter = new ResponseFilter(); registrationBean.setFilter(filter); List<String> urls = new ArrayList<>(); urls.add("/test/list"); registrationBean.setUrlPatterns(urls); return registrationBean; } }
|
拦截器(Interceptor)
拦截器(Interceptor):可以获取HttpServletRequest
、HttpServletResponse
的数据,也可以获取请求方法的信息,但是无法获取请求的参数和返回参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Date;
@Component public class TestInterceptor implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("在业务处理器处理请求之前被调用的方法"); 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("===== 在业务处理器处理请求完成之后,生成视图之前执行的方法 ====="); Long start = (Long) request.getAttribute("startTime"); System.out.println("Test拦截器,耗时:" + (new Date().getTime() - start)); }
@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception { System.out.println("===== 请求完成之后执行的方法 ====="); Long start = (Long) request.getAttribute("startTime"); System.out.println("Test拦截器,耗时:" + (new Date().getTime() - start)); System.out.println("异常:"+ exception); } }
|
切片(Aspect)
切片(Aspect):AOP
的切片可以获取请求的参数和返回的值,但是无法获HttpServletRequest
、HttpServletResponse
的数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; import java.util.Date;
@Aspect @Component public class TestAspect { @Around("execution(* com.smart.controller.UserController.*(..))") public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable { System.out.println("===== Test切面,开始 ====="); Object[] args = pjp.getArgs(); for (Object arg : args) { System.out.println("请求参数:" + arg); } long start = new Date().getTime(); Object object = pjp.proceed(); System.out.println("Test切面,耗时:" + (new Date().getTime() - start)); System.out.println("===== Test切面,结束 ====="); return object; } }
|