1、Spring aop 實現bash
AOP概念:框架
通知(Advice)的類型:ide
使用不一樣的通知,能夠幫咱們實現不一樣的日誌記錄,正常的操做日誌以及異常日誌等。。。模塊化
aop 的實現方式須要咱們自定義一個切面類,咱們須要記錄的就是經過controller的請求操做, 具體代碼以下:post
/**
* 經過aop 實現簡單的日誌功能
*/
@Aspect
@Component
public class LogAspect {
private final static Logger logger = LoggerFactory.getLogger(LogAspect.class);
private static final ThreadLocal<Long> startTimeThreadLocal =
new NamedThreadLocal<Long>("ThreadLocal StartTime");
// 聲明一個切入點
@Pointcut("execution(public * com.test.controller..*.*(..))")
public void aspect() {
}
@Before("aspect()")
public void LogRequestInfo(JoinPoint joinPoint) throws Exception {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
long beginTime = System.currentTimeMillis();//一、開始時間
startTimeThreadLocal.set(beginTime); //線程綁定變量(該數據只有當前請求的線程可見)
logger.debug("開始計時: {} URI: {} 請求方式: {} 參數: {}" , new SimpleDateFormat("hh:mm:ss.SSS")
.format(beginTime), request.getRequestURI(),request.getMethod(),JSONObject.toJSONString(joinPoint.getArgs()));
}
@AfterReturning("aspect()")
public void logResultVOInfo(JoinPoint joinPoint) throws Exception {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
long beginTime = startTimeThreadLocal.get();//獲得線程綁定的局部變量(開始時間)
long endTime = System.currentTimeMillis(); //二、結束時間
logger.debug("結束時間: {} 耗時: {} 最大內存: {}m 已分配內存: {}m 已分配內存中的剩餘空間: {}m 最大可用內存: {}m",
new SimpleDateFormat("hh:mm:ss.SSS").format(endTime), DateUtils.formatDateTime(endTime - beginTime),
Runtime.getRuntime().maxMemory()/1024/1024, Runtime.getRuntime().totalMemory()/1024/1024, Runtime.getRuntime().freeMemory()/1024/1024,
(Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory())/1024/1024);
}
}
複製代碼
訪問個路徑,看下控制檯打印結果ui
2、攔截器 實現spa
實現HandlerInterceptor接口線程
HandlerInterceptor 接口中定義了三個方法,咱們就是經過這三個方法來對用戶的請求進行攔截處理的。debug
preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顧名思義,該方法將在請求處理以前進行調用。SpringMVC 中的Interceptor 是鏈式的調用的,在一個應用中或者說是在一個請求中能夠同時存在多個Interceptor 。每一個Interceptor 的調用會依據它的聲明順序依次執行,並且最早執行的都是Interceptor 中的preHandle 方法,因此能夠在這個方法中進行一些前置初始化操做或者是對當前請求的一個預處理,也能夠在這個方法中進行一些判斷來決定請求是否要繼續進行下去。該方法的返回值是布爾值Boolean 類型的,當它返回爲false 時,表示請求結束,後續的Interceptor 和Controller 都不會再執行;當返回值爲true 時就會繼續調用下一個Interceptor 的preHandle 方法,若是已是最後一個Interceptor 的時候就會是調用當前請求的Controller 方法。3d
postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解釋咱們知道這個方法包括後面要說到的afterCompletion 方法都只能是在當前所屬的Interceptor 的preHandle 方法的返回值爲true 時才能被調用。postHandle 方法,顧名思義就是在當前請求進行處理以後,也就是Controller 方法調用以後執行,可是它會在DispatcherServlet 進行視圖返回渲染以前被調用,因此咱們能夠在這個方法中對Controller 處理以後的ModelAndView 對象進行操做。postHandle 方法被調用的方向跟preHandle 是相反的,也就是說先聲明的Interceptor 的postHandle 方法反而會後執行。
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,該方法也是須要當前對應的Interceptor 的preHandle 方法的返回值爲true 時纔會執行。顧名思義,該方法將在整個請求結束以後,也就是在DispatcherServlet 渲染了對應的視圖以後執行。這個方法的主要做用是用於進行資源清理工做的。
一、自定義攔截器
public class LogInterceptor implements HandlerInterceptor {
private final static Logger logger = LoggerFactory.getLogger(LogInterceptor.class);
private static final ThreadLocal<Long> startTimeThreadLocal =
new NamedThreadLocal<Long>("ThreadLocal StartTime");
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
long beginTime = System.currentTimeMillis();//一、開始時間
startTimeThreadLocal.set(beginTime); //線程綁定變量(該數據只有當前請求的線程可見)
logger.debug("開始計時: {} URI: {}", new SimpleDateFormat("hh:mm:ss.SSS")
.format(beginTime), request.getRequestURI());
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
if (modelAndView != null){
logger.info("ViewName: " + modelAndView.getViewName());
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
// 打印JVM信息。
long beginTime = startTimeThreadLocal.get();//獲得線程綁定的局部變量(開始時間)
long endTime = System.currentTimeMillis(); //二、結束時間
logger.debug("計時結束:{} 耗時:{} URI: {} 最大內存: {}m 已分配內存: {}m 已分配內存中的剩餘空間: {}m 最大可用內存: {}m",
new SimpleDateFormat("hh:mm:ss.SSS").format(endTime), DateUtils.formatDateTime(endTime - beginTime),
request.getRequestURI(), Runtime.getRuntime().maxMemory() / 1024 / 1024, Runtime.getRuntime().totalMemory() / 1024 / 1024, Runtime.getRuntime().freeMemory() / 1024 / 1024,
(Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory())/1024/1024);
}
}
複製代碼
二、配置攔截器
@Configuration
public class WebAppConfig extends WebMvcConfigurerAdapter {
/**
* addPathPatterns 配置須要攔截的請求路徑,excludePathPatterns配置不須要攔截的請求路徑。
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor()).addPathPatterns ("/**");
super.addInterceptors(registry);
}
}
複製代碼
查看打印結果
兩種方式均可以實現,具體仍是要看本身的需求而定