對於日志的管理,我們要實現收集、存儲和展示三個過程。(展示 ,我們就不過多介紹了,無非就是從數據庫中調取日志並展示在頁面上)
因為日志是要存儲在數據庫中的,所以我們先要弄清日志應該包含哪些內容,再創建一張數據表sysLog:
CREATE TABLE sysLog(
id VARCHAR2(32) default SYS_GUID() PRIMARY KEY,
visitTime timestamp,
username VARCHAR2(50),
ip VARCHAR2(30),
url VARCHAR2(50),
executionTime int,
method VARCHAR2(200)
)
定義一個實體類:

public class SysLog { private String id; private Date visitTime; private String visitTimeStr; private String username; private String ip; private String url; private Long executionTime; private String method; public String getId() { return id; } public void setId(String id) { this.id = id; } public Date getVisitTime() { return visitTime; } public void setVisitTime(Date visitTime) { this.visitTime = visitTime; } public String getVisitTimeStr() { if(visitTime!=null){ visitTimeStr = DateUtils.date2String(visitTime,"yyyy-MM-dd HH:mm"); } return visitTimeStr; } public void setVisitTimeStr(String visitTimeStr) { this.visitTimeStr = visitTimeStr; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Long getExecutionTime() { return executionTime; } public void setExecutionTime(Long executionTime) { this.executionTime = executionTime; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } }
基於AOP日志處理
創建切面類處理日志

@Component @Aspect public class LogAop { @Autowired private HttpServletRequest request; @Autowired private ISysLogService sysLogService; private Date visitTime;//訪問時間 private Class clazz;//訪問的類 private Method method;//訪問的方法 //主要獲取訪問的時間、訪問的類、訪問的方法 @Before("execution(* com.itheima.ssm.controller.*.*(..))") public void doBefore(JoinPoint jp) throws NoSuchMethodException,SecurityException{ visitTime = new Date();//訪問時間 clazz = jp.getTarget().getClass();//具體要訪問的類 String methodName = jp.getSignature().getName();//獲取訪問的方法名稱 Object[] args = jp.getArgs();//獲取訪問的方法參數 //獲取具體執行的方法的Method對象 if(args==null&&args.length==0){ method = clazz.getMethod(methodName);//只能獲取無參數的方法 }else{ Class[] classArgs = new Class[args.length]; for(int i=0;i<args.length;i++){ classArgs[i] = args[i].getClass(); //如果傳遞的方法參數類型為基本數據類型,一定要用它的包裝類,如int 應改為Integer } method = clazz.getMethod(methodName,classArgs); } } //后置通知 @After("execution(* com.itheima.ssm.controller.*.*(..))") public void doAfter(JoinPoint jp) throws Exception{ long time = new Date().getTime() - visitTime.getTime();//獲取訪問的時長 String url = ""; if (clazz!=null&&method!=null&&clazz!=LogAop.class&&clazz!=SysLogController.class){ //獲取url //獲取類上的@RequestMapping(value="/**") RequestMapping classAnnotation = (RequestMapping) clazz.getAnnotation(RequestMapping.class); if (classAnnotation!=null){ String[] classValue = classAnnotation.value(); //獲取方法上的@RequestMapping(value="/**") RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class); if (methodAnnotation!=null){ String[] methodValue = methodAnnotation.value(); url = classValue[0]+methodValue[0]; } } //獲取訪問的ip地址 String ip= request.getRemoteAddr(); //獲取當前操作的用戶 SecurityContext context = SecurityContextHolder.getContext();//從上下文中獲取當前登錄的用戶 User user = (User) context.getAuthentication().getPrincipal(); String username = user.getUsername(); //將日志相關信息封裝到SysLog對象 SysLog sysLog = new SysLog(); sysLog.setExecutionTime(time);//執行時長 sysLog.setIp(ip); sysLog.setMethod("[類名]"+clazz.getName()+"[方法名]"+method.getName()); sysLog.setUsername(username); sysLog.setVisitTime(visitTime); sysLog.setUrl(url); //調用Service完成操作 sysLogService.save(sysLog); } } }
注意:在web.xml中,我們要定義一個request監聽器:
<!-- 配置監聽器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
<!--定義一個request監聽器--> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener>
在整合spring容器時使用ContextLoaderListener,它實現了ServletContextListener監聽器接口,ServletContextListener
只負責監聽web容器啟動和關閉的事件.而RequestContextListener實現ServletRequestListener監聽器接口,該監聽器監聽
HTTP請求事件,web服務器接收的每一次請求都會通知該監聽器.
spring容器啟動和關閉操作由web容器的啟動和關閉事件觸發,但如果spring容器中的Bean需要request,session,globalsession
作用域的支持,spring容器本身就必須獲得web容器的HTTP請求事件,以HTTP請求的事件"驅動"Bean作用域的控制邏輯.
定義SysLogController
@Controller @RequestMapping("/sysLog") public class SysLogController { @Autowired private ISysLogService sysLogService; @RequestMapping("/findAll.do") public ModelAndView findAll() throws Exception{ ModelAndView mv = new ModelAndView(); List<SysLog> sysLogs = sysLogService.findAll(); mv.addObject("sysLogs",sysLogs); mv.setViewName("syslog-list"); return mv; } }
其他相關的service、dao之類的代碼就不過多闡述了,比較簡單。。。