前言:
任何一個項目都會有一個用戶操作日志(也叫行為日志)的模塊,它主要用來記錄某個用戶做了某個操作,當出現操作失敗時,通過日志就可以快速的查找是哪個用戶在哪個模塊出現了錯誤,以便于開發人員快速定位問題所在。
實現這一功能一般有兩種方法:
- 第一種就是很傳統的做法,就是在每個模塊進行插入日志的操作(不推薦),這種做法雖然實現了記錄用戶的操作,但很繁瑣而且基本上是重復的工作。
- 第二種就是使用Spring的AOP來實現記錄用戶操作,也是推薦的現如今都使用的一種做法。它的優勢在于這種記錄用戶操作的代碼獨立于其他業務邏輯代碼,不僅實現了解耦,而且避免了冗余代碼。
具體實現步驟
在pom.xml中添加AOP依賴<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>`
設計操作日志記錄表新增日志實體類、dao層 接口自定義操作日志記錄的注解package com.example.springcloud.aop;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author lyz* @title: OperationLog* @projectName springcloud* @date 2020/9/23* @description: 自定義操作日志注解*/
@Target(ElementType.METHOD)//注解放置的目標位置即方法級別
@Retention(RetentionPolicy.RUNTIME)//注解在哪個階段執行
@Documented
public @interface OperationLogAnnotation {String operModul() default ""; // 操作模塊String operType() default ""; // 操作類型String operDesc() default ""; // 操作說明
}
自定義操作日志切面類,該類是將操作日志保存到數據庫package com.example.springcloud.aop;import com.example.springcloud.dao.OperationLogDao;
import com.example.springcloud.domain.OperationLog;
import com.example.springcloud.utils.IPUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;/*** @author lyz* @title: OperationAspect* @projectName springcloud* @date 2020/9/23* @description: 操作日志切面處理類*/
@Aspect
@Component
public class OperationLogAspect {@AutowiredOperationLogDao logDao;private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");/*** 設置操作日志切入點 在注解的位置切入代碼*/@Pointcut("@annotation(com.example.springcloud.aop.OperationLogAnnotation)")public void operLogPoinCut() {}@AfterReturning(returning /*** 記錄操作日志* @param joinPoint 方法的執行點* @param result 方法返回值* @throws Throwable*/ = "result", value = "operLogPoinCut()")public void saveOperLog(JoinPoint joinPoint, Object result) throws Throwable {// 獲取RequestAttributesRequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();// 從獲取RequestAttributes中獲取HttpServletRequest的信息HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);try {//將返回值轉換成map集合Map<String, String> map = (Map<String, String>) result;OperationLog operationLog = new OperationLog();// 從切面織入點處通過反射機制獲取織入點處的方法MethodSignature signature = (MethodSignature) joinPoint.getSignature();//獲取切入點所在的方法Method method = signature.getMethod();//獲取操作OperationLogAnnotation annotation = method.getAnnotation(OperationLogAnnotation.class);if (annotation != null) {operationLog.setModel(annotation.operModul());operationLog.setType(annotation.operType());operationLog.setDescription(annotation.operDesc());}//操作時間operationLog.setOperationTime(Timestamp.valueOf(sdf.format(new Date())));//操作用戶operationLog.setUserCode(request.getHeader("userCode"));//操作IPoperationLog.setIp(IPUtil.getIpAdrress(request));//返回值信息operationLog.setResult(map.get("message"));//保存日志logDao.save(operationLog);} catch (Exception e) {e.printStackTrace();}}}
在controller層的某一個方法加入@OperationLogAnnotation 注解package com.example.springcloud.controller;import com.example.springcloud.aop.OperationLogAnnotation;
import com.example.springcloud.domain.User;
import com.example.springcloud.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import java.util.Map;/*** @author lyz* @title: UserController* @projectName springcloud* @date 2020/9/12* @description:*/
@Api(tags = "用戶表")
@RestController
@RequestMapping("/user")
public class UserController {@AutowiredUserService userService;@OperationLogAnnotation(operModul = "用戶模塊-用戶列表",operType = "查詢",operDesc = "查詢所有用戶")@ApiOperation(value = "查詢所有用戶",notes = "這是用來查詢所有用戶列表")@GetMapping("/users")public Object findAll(@RequestParam(required = false)String userName,@RequestParam(required = false)Integer sex,@RequestParam(required = false, defaultValue = "10") int limit,@RequestParam(required = false, defaultValue = "0") int offset,@RequestParam(required = false, defaultValue = "createTime") String sortBy,@RequestParam(required = false, defaultValue = "DESC") String sortFlag, HttpServletRequest request){offset=offset/limit;request.setAttribute("userCode","admin");return userService.findAll(userName,sex,sortBy,sortFlag,offset,limit);}@OperationLogAnnotation(operModul = "用戶模塊-新增用戶",operType = "新增",operDesc = "新增用戶")@PostMapping("/addUser")@ApiOperation(value = "新增用戶",notes = "通過這個方法可以添加新用戶")public Object createUser(@RequestBody Map<String, String>map){return userService.save(map);}}
通過swagger或者postmain進行測試,最后在數據庫中查看操作日志記錄
總結:用戶操作日志是AOP最常見的一種業務場景,這里使用了后置通知,當然也可以也可以使用異常通知記錄異常信息,方法如上。
原文作者:哥的冷酷,你模仿不來
原文鏈接:https://segmentfault.com/a/1190000023961648
原文出處:CSDN
總結
以上是生活随笔為你收集整理的中操作日志文件记录的是什么_SpringBoot+AOP实现用户操作日志的记录的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。