拦截请求并记录相应信息-springboot
方式:
1、FIlter过滤器
2、interceptor拦截器
3、Aspect切片
一、Filter过滤器形式
只能处理request中的数据 不能确定请求要走的是哪个controller信息
1、过滤器实现第一种方式
package com.nxz.filter; import org.springframework.stereotype.Component; import javax.servlet.*; import java.io.IOException; import java.util.Date; // Filter 是javax.servlet下的 @Component //让自定义filter起作用,只需要让springcontext管理起来即可 public class TimeFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("time filter init"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("time filter start"); long time = new Date().getTime(); filterChain.doFilter(servletRequest, servletResponse); System.out.println("消耗时间:" + (new Date().getTime() - time)); System.out.println("time filter start"); } @Override public void destroy() { System.out.println("time filter destroy"); } }
当项目启动的时候会在控制台输出:time filter init
当访问localhost:8080/user/1时:进入拦截器
结束结束后:
time filter start 进入getinfo服务 消耗时间:367 time filter end
2、filter过滤器第二种方式
package com.nxz.filter; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class WebConfig { @Bean public FilterRegistrationBean timeFilter(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); TimeFilter timeFilter = new TimeFilter(); filterRegistrationBean.setFilter(timeFilter); //指定什么样的请求回走timefilter过滤器 filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } }
二、inteceptor拦截器
只能处理到类中的方法,但是不能记录方法的参数是什么
package com.nxz.inteceptor; 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 TimeInteceptor implements HandlerInterceptor { //在controller调用之前调用 @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { System.out.println("preHandler"); System.out.println(((HandlerMethod) o).getBean().getClass().getName());//输出类名 System.out.println(((HandlerMethod) o).getMethod().getName());//输出方法名 //为了在prehandler方法和posthandler方法之间传递信息,可以将数据放到request中 httpServletRequest.setAttribute("startTime", new Date().getTime()); return false; } //在controller调用之后调用,如果controller中抛出异常,这个方法不会调用 @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); Long start = (Long) httpServletRequest.getAttribute("startTime"); System.out.println("time interceptor 耗时:" + (new Date().getTime() - start)); } //无论controller是否抛出异常,都会调用 @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { System.out.println("afterCompletion"); Long start = (Long) httpServletRequest.getAttribute("startTime"); System.out.println("time interceptor 耗时:" + (new Date().getTime() - start)); System.out.println("ex is :" + e); } }
interceptor实现拦截功能还需要配置webconfig
package com.nxz.config; import com.nxz.filter.TimeFilter; import com.nxz.inteceptor.TimeInteceptor; import org.springframework.beans.factory.annotation.Autowired; 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.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Autowired private TimeInteceptor timeInteceptor; //自定义的interceptor 要起作用的话 需要继承webmvcConfigurerAdater ,重写addInterceptors @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(timeInteceptor); } }
访问localhost:8080/user/1后,输入日志:
preHandler com.nxz.controller.UserController getInfo 进入getinfo服务 postHandle time interceptor 耗时:48 afterCompletion time interceptor 耗时:48 ex is :null
三、切片Aspect(AOP) -- 切入点(注解)、增强(方法)
需要导入aop依赖
package com.nxz.aspect; 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 TimeAspect { //@Before @After @AfterThrowing @Around 基本的aop注解 @Around("execution(* com.nxz.controller.UserController.*(..))") public Object handlerControllerMehtod(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("time aspect start"); Object[] args = joinPoint.getArgs(); for (Object arg : args) { System.out.println(arg); } Long time = new Date().getTime(); Object obj = joinPoint.proceed(); System.out.println("time aspect end,耗时:" + (new Date().getTime() - time)); return obj; } }
访问地址后:
time aspect start 1 --》请求参数 进入getinfo服务 time aspect end,耗时:4
几种方式起作用的顺序:
====
Usercontroller:
@GetMapping("/{id:\\d+}") @JsonView(User.UserDetailView.class) public User getInfo(@PathVariable String id) { System.out.println("进入getinfo服务"); User user = new User(); user.setUsername("tom"); return user; }