1.数据库与表结构
(1)日志表信息描述sysLog
(2)Sql语句
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 ) )
(3)实体类
package lucky.domain; import java.util.Date; /** * 系统日志实体类 */ 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() { 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; } }
2.AOP日志思路分析图
3.代码部分
(1)aop配置
在springmvc.xml文件中添加如下内容:
<!-- 支持AOP的注解支持,AOP底层使用代理技术 JDK动态代理,要求必须有接口 cglib代理,生成子类对象,proxy-target-class="true" 默认使用cglib的方式 --> <aop:aspectj-autoproxy proxy-target-class="true"/>
(2)AopLog.java(最重要)
package lucky.controller; import lucky.domain.SysLog; import lucky.service.ISysLogService; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.User; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.util.Date; /** * AOP日志 * 注意:获取url时,classAnnotation.path()还是classAnnotation.value()一定要和controller上的注解相一致,否则会报错 * 可以打上断点看看 */ @Component @Aspect public class LogAop { @Autowired private HttpServletRequest request; @Autowired private ISysLogService sysLogService; private Date visitTime; //访问时间 private Class clazz; //访问的类 private Method method;//访问的方法 /** * 前置通知,主要是获取开始时间,执行的类是哪一个,执行的是哪一个方法 */ @Before("execution(* lucky.controller.*.*(..))") public void doBefore(JoinPoint jp) throws Exception { 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(); } clazz.getMethod(methodName, classArgs); } } /** * 后置通知 */ @After("execution(* lucky.controller.*.*(..))") public void doAfter(JoinPoint jp) throws Exception{ long time = new Date().getTime() - visitTime.getTime(); //获取访问的时长 String url = ""; //获取url if (clazz != null && method != null && clazz != LogAop.class) { //1.获取类上的@RequestMapping("/orders") RequestMapping classAnnotation = (RequestMapping) clazz.getAnnotation(RequestMapping.class); //String[] classValue = classAnnotation.value(); if (classAnnotation != null) { String[] classValue = classAnnotation.path(); //2.获取方法上的@RequestMapping(xxx) RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class); if (methodAnnotation != null) { String[] methodValue = methodAnnotation.path(); url = classValue[0] + methodValue[0]; //获取访问的ip String ip = request.getRemoteAddr(); //利用springSecurity获取当前操作的用户 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.setUrl(url); sysLog.setUsername(username); sysLog.setVisitTime(visitTime); //调用Service完成操作 sysLogService.save(sysLog); } } } } }
(3)service层代码
接口
package lucky.service; import lucky.domain.SysLog; import java.util.List; public interface ISysLogService{ void save(SysLog sysLog); List<SysLog> queryAll(); }
实现类
package lucky.service.impl; import lucky.dao.ISysLogDao; import lucky.domain.SysLog; import lucky.service.ISysLogService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class SysLogServiceImpl implements ISysLogService { @Autowired private ISysLogDao iSysLogDao; @Override public void save(SysLog sysLog) { iSysLogDao.save(sysLog); } @Override public List<SysLog> queryAll() { return iSysLogDao.queryAll(); } }
(5)持久层
package lucky.dao; import lucky.domain.SysLog; import org.apache.ibatis.annotations.Select; import java.util.List; public interface ISysLogDao { @Select("insert into LUCKY.SYSLOG(visitTime,username,ip,url,executionTime,method) values(#{visitTime},#{username},#{ip},#{url},#{executionTime},#{method})") public void save(SysLog sysLog); @Select("select * from LUCKY.SYSLOG") List<SysLog> queryAll(); }
4.效果图