对于日志的管理,我们要实现收集、存储和展示三个过程。(展示 ,我们就不过多介绍了,无非就是从数据库中调取日志并展示在页面上)
因为日志是要存储在数据库中的,所以我们先要弄清日志应该包含哪些内容,再创建一张数据表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之类的代码就不过多阐述了,比较简单。。。