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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM