springboot中有三种拦截器可供选择:filter、interceptort和aop。本文主要讨论三种拦截器的使用场景与使用方式。
下文中的举例功能是计算每个请求的从开始到结束的时间,例子来源是慕课网。
一、filter
特点:可以获取原始的ServletRequest,但无法获取具体方法
实现:
1.继承javax.servlet.Filter类,
[email protected]注解将其注入到框架中
3.实现其中的dofilter方法,所有的请求都会经过该方法,可以在此计算出每个请求的耗时,代码如下:
1 package com.zzy.web.filter; 2 3 import java.io.IOException; 4 import java.util.Date; 5 6 import javax.servlet.Filter; 7 import javax.servlet.FilterChain; 8 import javax.servlet.FilterConfig; 9 import javax.servlet.ServletException; 10 import javax.servlet.ServletRequest; 11 import javax.servlet.ServletResponse; 12 13 import org.springframework.stereotype.Component; 14 15 @Component 16 public class TimeFilter implements Filter{ 17 18 @Override 19 public void init(FilterConfig filterConfig) throws ServletException { 20 // TODO Auto-generated method stub 21 System.out.println("filter init"); 22 23 } 24 25 @Override 26 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 27 throws IOException, ServletException { 28 // TODO Auto-generated method stub 29 Long startTime = new Date().getTime(); 30 System.out.println("filter 请求开始时间:"+ startTime); 31 chain.doFilter(request, response); 32 Long endTime = new Date().getTime(); 33 System.out.println("filter 请求结束时间:" + endTime +",请求耗时:" + (endTime - startTime)); 34 35 } 36 37 @Override 38 public void destroy() { 39 // TODO Auto-generated method stub 40 41 } 42 43 }
注:如果有的框架没有@Component 这个注解,可以自己写一个配置类,在该类中指定过滤器,而且还可以指定过滤的url,配置类如下:
1 package com.zzy.web.config; 2 3 import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown; 4 5 import java.util.ArrayList; 6 import java.util.List; 7 8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.boot.web.servlet.FilterRegistrationBean; 10 import org.springframework.context.annotation.Bean; 11 import org.springframework.context.annotation.Configuration; 12 import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 13 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 14 15 import com.zzy.web.filter.TimeFilter; 16 import com.zzy.web.interceptor.TimeInterceptor; 17 18 @Configuration 19 public class WebConfig extends WebMvcConfigurerAdapter { 20 21 @Autowired 22 private TimeInterceptor timeInterceptor; 23 24 // @Override 25 // public void addInterceptors(InterceptorRegistry registry) { 26 // // TODO Auto-generated method stub 27 // registry.addInterceptor(timeInterceptor); 28 // } 29 30 @Bean 31 public FilterRegistrationBean timeFilter() { 32 FilterRegistrationBean registrationBean = new FilterRegistrationBean(); 33 TimeFilter timeFilter = new TimeFilter(); 34 registrationBean.setFilter(timeFilter); 35 List<String> urls = new ArrayList<>(); 36 urls.add("/user/*"); 37 registrationBean.setUrlPatterns(urls); 38 return registrationBean; 39 } 40 41 }
二、interceptor
特点:可以获取到原始的request和请求的方法,但无法获取方法的具体参数的值。
实现:
1.继承HandlerInterceptor接口
2.请求前的逻辑写在prehandle(请求前调用)
3.请求后的逻辑写在posthandle(请求成功后调用,失败则不调用)
4.请求后,不管成功失败都会调用aftercompletion。
5.intceptor方式继承了之后还没起作用,还需要在配置类里面加一下,把刚声明的拦截器注册一下。
代码示例:
1 package com.zzy.web.interceptor; 2 3 import java.util.Arrays; 4 import java.util.Date; 5 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 9 import org.springframework.stereotype.Component; 10 import org.springframework.web.method.HandlerMethod; 11 import org.springframework.web.servlet.HandlerInterceptor; 12 import org.springframework.web.servlet.ModelAndView; 13 @Component 14 public class TimeInterceptor implements HandlerInterceptor { 15 16 @Override 17 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 18 throws Exception { 19 // TODO Auto-generated method stub 20 System.out.println("interceptor 执行preHandle"); 21 22 request.setAttribute("startTime", new Date().getTime()); 23 return true; 24 } 25 26 @Override 27 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 28 ModelAndView modelAndView) throws Exception { 29 // TODO Auto-generated method stub 30 Long startTime = Long.parseLong(request.getAttribute("startTime").toString()); 31 Long endTime = new Date().getTime(); 32 System.out.println("interceptor 执行postHandle"); 33 System.out.println("interceptor 请求类:"+((HandlerMethod)handler).getBean().getClass().getName()); 34 System.out.println("interceptor 请求方法:"+((HandlerMethod)handler).getMethod()); 35 // System.out.println("interceptor 请求参数:"); 36 // Arrays.asList(((HandlerMethod)handler).getMethodParameters()).stream().forEach(arg->System.out.println(arg)); 37 System.out.println("interceptor 请求耗时:" + (endTime - startTime)); 38 39 } 40 41 @Override 42 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 43 throws Exception { 44 // TODO Auto-generated method stub 45 Long startTime = Long.parseLong(request.getAttribute("startTime").toString()); 46 Long endTime = new Date().getTime(); 47 System.out.println("interceptor 执行afterCompletion"); 48 System.out.println("interceptor 请求类:"+((HandlerMethod)handler).getBean().getClass().getName()); 49 System.out.println("interceptor 请求方法:"+((HandlerMethod)handler).getMethod()); 50 System.out.println("interceptor 请求耗时:" + (endTime - startTime)); 51 System.out.println("interceptor 请求异常:" + ex); 52 53 } 54 55 }
配置类如下:
1 package com.zzy.web.config; 2 3 import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown; 4 5 import java.util.ArrayList; 6 import java.util.List; 7 8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.boot.web.servlet.FilterRegistrationBean; 10 import org.springframework.context.annotation.Bean; 11 import org.springframework.context.annotation.Configuration; 12 import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 13 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 14 15 import com.zzy.web.filter.TimeFilter; 16 import com.zzy.web.interceptor.TimeInterceptor; 17 18 @Configuration 19 public class WebConfig extends WebMvcConfigurerAdapter { 20 21 @Autowired 22 private TimeInterceptor timeInterceptor; 23 24 @Override 25 public void addInterceptors(InterceptorRegistry registry) { 26 // TODO Auto-generated method stub 27 registry.addInterceptor(timeInterceptor); 28 } 29 30 31 }
三、aop
特点:能拿到方法和具体参数的值,但是拿不到原始的servletrequest的信息。
实现:
1.使用@aspect注解
[email protected]声明切面,声明切面的语法可参考官网https://docs.spring.io/spring/docs/4.3.18.RELEASE/spring-framework-reference/htmlsingle/#aop-pointcuts
3.使用@Around(方法前和方法后),@Before(方法前)或@After(方法后)
以下为@Around举例,代码如下:
1 package com.zzy.web.aspect; 2 3 import java.util.Date; 4 5 import org.aspectj.lang.ProceedingJoinPoint; 6 import org.aspectj.lang.annotation.Around; 7 import org.aspectj.lang.annotation.Aspect; 8 import org.codehaus.jackson.map.ObjectMapper; 9 import org.springframework.stereotype.Component; 10 11 @Aspect 12 @Component 13 public class TimeAspect { 14 15 @Around("execution(* com.zzy.web.controller.UserController.*(..))") 16 public Object test(ProceedingJoinPoint pjp) throws Throwable { 17 Long startTime = new Date().getTime(); 18 Object[] args = pjp.getArgs(); 19 for (Object arg : args) { 20 System.out.println("aspect 参数:" + arg); 21 } 22 Object object = pjp.proceed(); 23 System.out.println("aspect 请求耗时:" + (new Date().getTime() - startTime)); 24 System.out.println("aspect 请求结果:" + new ObjectMapper().writeValueAsString(object)); 25 26 return object; 27 28 } 29 }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Menlo }
原文地址:https://www.cnblogs.com/zuxiaoyuan/p/9702363.html