如题, 方式有三种。
(1). 过滤器filter
javaEE规范
(2). 拦截器interceptor
springmvc提供
(3). 切片 aspect
一. Filter使用示例
import org.springframework.stereotype.Component; import javax.servlet.*; import java.io.IOException; /** * 使用@Component注解,该Filter就生效了。 * 还可以使用配置方式使用过滤生效 {@link FilterRegistrationBean} */ @Component public class LoggerFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("LoggerFilter doFilter begin"); long startTime = System.currentTimeMillis(); filterChain.doFilter(servletRequest,servletResponse); long endTime = System.currentTimeMillis(); System.out.println("used time :" + (endTime - startTime)); System.out.println("LoggerFilter doFilter end"); } @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("LoggerFilter init..."); } @Override public void destroy() { System.out.println("LoggerFilter destroy..."); } }
二. Interceptor使用示例
2.1 自定义一个拦截器
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; /** * 定义一个拦截器, 它会拦截所有的控制器,包括spring自带的控制器,诸如BasicErrorController.class * 注意: interceptor与filter不同,仅仅使用一个@Component注解,该interceptor并不会生效 */ @Component public class LoggerInterceptor implements HandlerInterceptor { /** * 在进入controller方法之前调用 * * @param handler : 就是启用的controller方法 * @return true: 执行下一个拦截器 * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("LoggerInterceptor preHandle..."); request.setAttribute("startTime", System.currentTimeMillis()); HandlerMethod handlerMethod = (HandlerMethod) handler; System.out.println("Controller类名:"+ handlerMethod.getBean().getClass().getName()); System.out.println("Controller方法名:"+ handlerMethod.getMethod().getName()); return true; } /** * 在执行完controller方法之后调用,如果controller方法抛出异常,则不会调用 * * @param request * @param response * @param handler * @param modelAndView * @throws Exception */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("LoggerInterceptor postHandle begin"); long startTime = (long) request.getAttribute("startTime"); System.out.println("used time :" + ( System.currentTimeMillis()-startTime)); System.out.println("LoggerInterceptor postHandle end"); } /** * 在视图渲染之后调用,controller有无异常抛出,都会被调用 * @param ex 如果controller方法无异常抛出,ex 为null , 否则就是controller中抛出来的异常 * @throws Exception */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("LoggerInterceptor afterCompletion begin"); long startTime = (long) request.getAttribute("startTime"); System.out.println("used time :" + ( System.currentTimeMillis()-startTime)); System.out.println("LoggerInterceptor afterCompletion ex = " + ex); System.out.println("LoggerInterceptor afterCompletion end"); } }
2.2 注册拦截器
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import qinfeng.zheng.mockmvcdemo.interceptor.LoggerInterceptor; /** * SpringBoot 1.X 使用WebMvcConfigurerAdapter.java即可, * SpringBoot 2.x WebMvcConfigurerAdapter.java已过时了 */ @Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private LoggerInterceptor loggerInterceptor; /** * 注册拦截器 * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { // registry.addInterceptor(new LoggerInterceptor()); registry.addInterceptor(loggerInterceptor); } }
三. 切片
/** * 定义一个切片 */ @Aspect @Component public class LoggerAspect { /** * 第一个 * : 方法的任意返回值 * 第二个 * : qinfeng.zheng.mockmvcdemo.controller.TestController类中的任意方法 * .. : 方法的任意参数 * @param pjp * @return * * 参考: https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/core.html#aop 5.4.3 */ @Around("execution(* qinfeng.zheng.mockmvcdemo.controller.TestController.*(..))") public Object handle(ProceedingJoinPoint pjp) throws Throwable { System.out.println("LoggerAspect handle start..."); // 方法参数列表 Object[] args = pjp.getArgs(); Arrays.stream(args).forEach(x-> System.out.println(x)); long startTime = System.currentTimeMillis(); Object result = pjp.proceed(); System.out.println("used time :" + (System.currentTimeMillis() - startTime)); System.out.println("LoggerAspect handle end..."); return result; } }
四. 总结
Filter最弱,只能获取request对象
Interceptor,比Filter好,它不但能获取request对象 ,而且还能拿到HandlerMethoh对象,从而知道调用那个Controller ,以及具体的方法
Aspect,功能最强大,它可以获取Controller方法的方法的参数列表。。。。。
日拱一卒无有尽,功不唐捐终入海