SpringBoot入门系列~使用AOP切面记录用户的访问日志
使用Aop切面记录用户访问日志
1、记录日志目的
网站一般都会记录某个用户的访问信息,分析某个用户经常访问那些业务,针对用户的访问量进行一下营销策略、还可以记录用户的日活量和月活量,针对一下活跃的用户进行进行一些优惠的活动
2、AOP的基本介绍
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,实现AOP记录日志主要有以下几个步骤
使用@Aspect注解将一个java类定义为切面类
使用@Pointcut定义一个切入点,可以是一个规则表达式,比如下例中某个package下的所有函数,也可以是一个注解等根据需要在切入点不同位置的切入内容
使用@Before在切入点开始处切入内容
使用@After在切入点结尾处切入内容
使用@AfterReturning在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
使用@Around在切入点前后切入内容,并自己控制何时执行切入点自身的内容
使用@AfterThrowing用来处理当切入内容部分抛出异常之后的处理逻辑
具体步骤如下
3、创建 日志实体
1 package com.sun.spring.boot.pojo; 2 3 import java.util.Date; 4 5 import javax.persistence.Column; 6 import javax.persistence.Entity; 7 import javax.persistence.GeneratedValue; 8 import javax.persistence.Id; 9 import javax.persistence.Table; 10 11 /** 12 * 系统日志实体Bean 13 * @ClassName: SysLogInfoBean 14 * @author sunt 15 * @date 2017年11月10日 16 * @version V1.0 17 */ 18 @Entity 19 @Table(name = "F_SYS_LOG") 20 public class SysLogInfoBean { 21 22 /** 23 * 主键 24 */ 25 @Id 26 @GeneratedValue 27 private Integer Id; 28 29 /** 30 * 用户名 31 */ 32 @Column(name = "F_USER_NAME",length = 20) 33 private String userName; 34 35 /** 36 * 访问的IP 37 */ 38 @Column(name = "F_IP",length = 20) 39 private String ip; 40 41 /** 42 * 访问接口名称 43 */ 44 @Column(name = "F_METHOD_NAME", length = 100) 45 private String methodNmae; 46 47 /** 48 * 访问的类名称 49 */ 50 @Column(name = "F_CLASS_NAME", length = 200) 51 private String className; 52 53 /** 54 * 访问时间 55 */ 56 @Column(name = "F_CREATE_DATE") 57 private Date createDate; 58 59 /** 60 * 主机名 61 */ 62 @Column(name = "F_REMOTE_HOST", length = 50) 63 private String remoteHost; 64 65 /** 66 * 访问的URL 67 */ 68 @Column(name = "F_URL", length = 50) 69 private String url; 70 71 public Integer getId() { 72 return Id; 73 } 74 75 public void setId(Integer id) { 76 Id = id; 77 } 78 79 public String getUserName() { 80 return userName; 81 } 82 83 public void setUserName(String userName) { 84 this.userName = userName; 85 } 86 87 public String getIp() { 88 return ip; 89 } 90 91 public void setIp(String ip) { 92 this.ip = ip; 93 } 94 95 public String getMethodNmae() { 96 return methodNmae; 97 } 98 99 public void setMethodNmae(String methodNmae) { 100 this.methodNmae = methodNmae; 101 } 102 103 public String getClassName() { 104 return className; 105 } 106 107 public void setClassName(String className) { 108 this.className = className; 109 } 110 111 public Date getCreateDate() { 112 return createDate; 113 } 114 115 public void setCreateDate(Date createDate) { 116 this.createDate = createDate; 117 } 118 119 public String getRemoteHost() { 120 return remoteHost; 121 } 122 123 public void setRemoteHost(String remoteHost) { 124 this.remoteHost = remoteHost; 125 } 126 127 public String getUrl() { 128 return url; 129 } 130 131 public void setUrl(String url) { 132 this.url = url; 133 } 134 135 }
4、创建日志dao接口
1 package com.sun.spring.boot.dao; 2 3 import org.springframework.data.jpa.repository.JpaRepository; 4 import org.springframework.stereotype.Repository; 5 6 import com.sun.spring.boot.pojo.SysLogInfoBean; 7 8 /** 9 * 系统日志Dao接口 10 * @ClassName: ISysLogInfoDao 11 * @author sunt 12 * @date 2017年11月10日 13 * @version V1.0 14 */ 15 @Repository 16 public interface ISysLogInfoDao extends JpaRepository<SysLogInfoBean, Integer> { 17 18 }
5、创建日志记录Service接口和实现
1 package com.sun.spring.boot.service; 2 3 import com.sun.spring.boot.pojo.SysLogInfoBean; 4 5 /** 6 * 日志service接口 7 * @ClassName: ISysLogInfoService 8 * @author sunt 9 * @date 2017年11月10日 10 * @version V1.0 11 */ 12 public interface ISysLogInfoService { 13 14 /** 15 * 保存日志信息 16 * @Title: insertSysLog 17 * @author sunt 18 * @date 2017年11月10日 19 * @param bean 日志实体 20 * @return void 21 */ 22 void insertSysLog(SysLogInfoBean bean); 23 }
1 package com.sun.spring.boot.service.impl; 2 3 import org.apache.log4j.Logger; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.stereotype.Service; 6 7 import com.sun.spring.boot.dao.ISysLogInfoDao; 8 import com.sun.spring.boot.pojo.SysLogInfoBean; 9 import com.sun.spring.boot.service.ISysLogInfoService; 10 11 /** 12 * 系统日志Service实现 13 * @ClassName: SysLogInfoServiceImpl 14 * @author sunt 15 * @date 2017年11月10日 16 * @version V1.0 17 */ 18 @Service 19 public class SysLogInfoServiceImpl implements ISysLogInfoService{ 20 21 private Logger logger = Logger.getLogger(SysLogInfoServiceImpl.class); 22 23 @Autowired 24 private ISysLogInfoDao sysLogInfoDao; 25 26 @Override 27 public void insertSysLog(SysLogInfoBean bean) { 28 logger.info("++++++++执行日志入库操作++++++++++"); 29 sysLogInfoDao.save(bean); 30 } 31 32 }
6、创建日志切面类
具体逻辑代码里面都有详细的注释
1 package com.sun.spring.boot.aspect; 2 3 import java.util.Date; 4 5 import javax.servlet.http.HttpServletRequest; 6 7 import org.apache.log4j.Logger; 8 import org.aspectj.lang.JoinPoint; 9 import org.aspectj.lang.annotation.After; 10 import org.aspectj.lang.annotation.AfterReturning; 11 import org.aspectj.lang.annotation.Aspect; 12 import org.aspectj.lang.annotation.Before; 13 import org.aspectj.lang.annotation.Pointcut; 14 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.stereotype.Component; 16 import org.springframework.web.context.request.RequestContextHolder; 17 import org.springframework.web.context.request.ServletRequestAttributes; 18 19 import com.sun.spring.boot.pojo.SysLogInfoBean; 20 import com.sun.spring.boot.service.ISysLogInfoService; 21 22 /** 23 * 发送请求的切面入口类,需要在Spring中注入 24 * @ClassName: RequestAsprct 25 * @author sunt 26 * @date 2017年11月10日 27 * @version V1.0 28 */ 29 @Component 30 @Aspect 31 public class RequestAsprct { 32 33 private Logger logger = Logger.getLogger(RequestAsprct.class); 34 35 @Autowired 36 private ISysLogInfoService sysLogInfoService; 37 38 /** 39 * 记录日志,定义切入点:指定那些业务(业务对应的方法) 40 * @Title: log 41 * @author sunt 42 * @date 2017年11月10日 43 * @return void 44 */ 45 @Pointcut("execution(public * com.sun.spring.boot.controller.*.*(..))") 46 //切入点说明:包下的任意类,任意方法,任意参数,任意返回值的方法都进行切入 47 public void sysLog() { 48 49 } 50 51 @Before("sysLog()") 52 public void doBefore(JoinPoint joinPoint) { 53 54 ServletRequestAttributes servletRequestAttributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); 55 HttpServletRequest request = servletRequestAttributes.getRequest(); 56 57 String requestUri = request.getRequestURI();// 得到请求的资源 58 String remoteAddr = request.getRemoteAddr();// 得到来访者的IP地址 59 String method = request.getMethod();// 得到请求URL地址时使用的方法 60 String remoteHost = request.getRemoteHost();//客户端主机名 61 String className = joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName(); 62 63 logger.info("+++++++从切入点开始处切入内容..."); 64 logger.info("requestUri=" + requestUri + ",remoteAddr=" + remoteAddr 65 + ",method=" + method + ",remoteHost=" + remoteHost + ",className=" + className); 66 SysLogInfoBean bean = new SysLogInfoBean(); 67 bean.setUserName("1号活跃用户"); 68 bean.setIp(remoteAddr); 69 bean.setCreateDate(new Date()); 70 bean.setMethodNmae(method); 71 bean.setRemoteHost(remoteHost); 72 bean.setClassName(className); 73 bean.setUrl(requestUri); 74 75 //TODO :测试直接入库操作,用户量比较大的网站一般缓存到消息队列执行批量入库,推荐Apache Kafka 76 sysLogInfoService.insertSysLog(bean); 77 } 78 79 @After("sysLog()") 80 public void doAfter(JoinPoint joinPoint) { 81 logger.info("------------->在切入点结尾处(方法执行后)切入内容..."); 82 } 83 84 85 @AfterReturning(returning = "result",pointcut = "sysLog()") 86 public void doAfterReturning(Object result) { 87 logger.info("在切入点return内容之后切入内容:" + result); 88 } 89 90 }
7、Request的常用方法
详细讲解HttpServletRequest参考这篇博客: http://www.cnblogs.com/love540376/p/5336881.html
getRequestURL方法返回客户端发出请求时的完整URL。 getRequestURI方法返回请求行中的资源名部分。 getQueryString 方法返回请求行中的参数部分。 getPathInfo方法返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以“/”开头。 getRemoteAddr方法返回发出请求的客户机的IP地址。 getRemoteHost方法返回发出请求的客户机的完整主机名。 getRemotePort方法返回客户机所使用的网络端口号。 getLocalAddr方法返回WEB服务器的IP地址。 getLocalName方法返回WEB服务器的主机名。
8、访问之前做的商品增删改查记录用户的操作信息
http://127.0.0.1:8088/goods/list
9、后台日志分析
10、查看数据库记录的信息
11、svn地址:svn://gitee.com/SunnySVN/SpringBoot
最新同步更新地址:https://www.sunnyblog.top/ 感谢您花时间阅读此篇文章,如果您觉得这篇文章你学到了东西也是为了犒劳下博主的码字不易不妨打赏一下吧,让博主能喝上一杯咖啡,在此谢过了! 如果您觉得阅读本文对您有帮助,请点一下左下角“推荐”按钮,您的“推荐”将是我最大的写作动力!另外您也可以选择【关注我】,可以很方便找到我! 本文版权归作者和博客园共有,来源网址:https://www.cnblogs.com/sunny1009 欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利!