如題, 方式有三種。
(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方法的方法的參數列表。。。。。