spring mvc記錄各個controller訪問開始結束時間,以及耗時時間 執行緒安全
阿新 • • 發佈:2018-11-05
package cn.test.web.interceptor; public class StopWatchHandlerInterceptor extends HandlerInterceptorAdapter { private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("StopWatch-StartTime"); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { long beginTime = System.currentTimeMillis();//1、開始時間 startTimeThreadLocal.set(beginTime);//執行緒繫結變數(該資料只有當前請求的執行緒可見) return true;//繼續流程 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { long endTime = System.currentTimeMillis();//2、結束時間 long beginTime = startTimeThreadLocal.get();//得到執行緒繫結的區域性變數(開始時間) long consumeTime = endTime - beginTime;//3、消耗的時間 if(consumeTime > 500) {//此處認為處理時間超過500毫秒的請求為慢請求 //TODO 記錄到日誌檔案 System.out.println( String.format("%s consume %d millis", request.getRequestURI(), consumeTime)); } } }
import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.aspectj.lang.ProceedingJoinPoint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.NamedThreadLocal; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.common.interceptor /** *攔截所有使用者的操作,記錄操作日誌 * * @author * @version 1.00.00 * */ public class UserActionLogInterceptor extends HandlerInterceptorAdapter{ private static final Logger logger = LoggerFactory.getLogger(UserActionLogInterceptor.class.getName()); private NamedThreadLocal<Long> startTimeThreadLocal=new NamedThreadLocal<Long>("StartTime-EndTime"); @Autowired private JdbcTemplate jdbcTemplate; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String url=request.getRequestURI(); String reqId=UUID.randomUUID().toString(); //前段如果已經傳入請求標識,則繼續沿用 if(request.getParameter("reqId")==null){ request.setAttribute("reqId", reqId); }else{ reqId=request.getParameter("reqId"); //encode一次,防止前段sql注入 reqId=URLEncoder.encode(reqId, reqId); request.setAttribute("reqId", reqId); } logger.debug("進了Web端的logger interceptor,請求Url:"+url+" 請求標識為:" + reqId+" 開始處理請求Start"); Long startTime=System.currentTimeMillis(); startTimeThreadLocal.set(startTime); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { String url=request.getRequestURI(); Long startTime=startTimeThreadLocal.get(); Long endTime =System.currentTimeMillis(); String reqId=(String)request.getAttribute("reqId"); User user = SecurityUtils.getSessionUser(); if(user!=null){ String loginid=user.getLoginId(); String ip =request.getRemoteAddr(); String loginType=user.getLoginType(); logger.debug("UserActionLogInterceptor:使用者名稱:"+loginid+", IP:"+ip); if(handler instanceof HandlerMethod){ HandlerMethod method=(HandlerMethod)handler; String className=method.getBean().getClass().getSimpleName(); String methodName=method.getMethod().getName(); //記錄日誌-//xxhCommonController 不做日誌記錄 if(!"xxhCommonController".equals(className)&&!"MenuHintsController".equals(className)){ String msg=ex==null?"操作成功":"操作失敗:"+ex.getMessage(); if(msg.length()>512){//資料庫長度為1536,全部為漢字時是512個字元 msg=msg.substring(0, 512); } if(reqId.length()>96){ msg=msg.substring(0, 95); } UserActionLogger logBean=new UserActionLogger(); logBean.setUserId(loginid); logBean.setPostClassId(className); logBean.setPostAction(methodName); logBean.setLogType(loginType); logBean.setClientIP(ip); logBean.setProcessTime(endTime-startTime); logBean.setObjId(reqId); logBean.setBookId(user.getCurrentSetsOfBooksId()); logBean.setDetail(msg); log2DB(logBean); }else{ logger.debug("UserActionLogInterceptor:請求來自xxhCommonController,MenuHintsController,無需記錄日誌"); } }else{ logger.debug("UserActionLogInterceptor:非業務處理類的controller,無需記錄日誌"); } }else{ logger.debug("UserActionLogInterceptor:未登入使用者,無法獲取使用者資訊"); } if(ex!=null){ logger.debug("UserActionLogInterceptor攔截到來自controller的異常資訊", ex); } logger.debug("進了Web端的logger interceptor,請求Url:"+url+", 請求標識為:" + reqId+" 結束End"); } private void log2DB(UserActionLogger logInfo){ String insertSql=" insert into xxh_opt_log "+ " (syslogid, "+ " logtime, "+ " logtype, "+ " postclassid, "+ " postaction, "+ " objid, "+ " userid, "+ " clientip, "+ " bookid, "+ " detail, "+ " processtime) "+ " values "+ " (" + " SQ_xxh_OPT_LOG.Nextval, "+ " sysdate, "+ " '"+logInfo.getLogType()+"', "+ " '"+logInfo.getPostClassId()+"', "+ " '"+logInfo.getPostAction()+"', "+ " '"+logInfo.getObjId()+"', "+ " '"+logInfo.getUserId()+"', "+ " '"+logInfo.getClientIP()+"', "+ " "+logInfo.getBookId()+", "+ " '"+logInfo.getDetail()+"', "+ " "+logInfo.getProcessTime()+"" +")"; try {jdbcTemplate.execute(insertSql);} catch (Exception e) {logger.error("UserActionLogInterceptor_logInDB_error",e);} } }
XML 配置: <mvc:interceptors> <mvc:interceptor> <!-- 匹配的是url路徑, 如果不配置或/**,將攔截所有的Controller --> <mvc:mapping path="/**" /> <bean class="com.common.interceptor.UserActionLogInterceptor"></bean> <!-- 自定義攔截器路徑 --> </mvc:interceptor> <!-- 當設定多個攔截器時,先按順序呼叫preHandle方法,然後逆序呼叫每個攔截器的postHandle和afterCompletion方法 --> </mvc:interceptors>