SpringBoot使用AOP記錄接口操作日志詳解
SpringBoot 使用 AOP 記錄接口操作日志,供大傢參考,具體內容如下
一、AOP簡介
1.什麼是AOP
AOP:Aspect Oriented Programming 面向切面編程
AOP關註不是某一個類或某些方法;控制大量資源,關註的是大量的類和方法。
2.AOP應用場景以及常用術語
- 權限控制、緩存控制、事務控制、分佈式追蹤、異常處理等
- Target:目標類,即需要被代理的類。例如:UserService
- Joinpoint(連接點):所謂連接點是指那些可能被攔截到的方法。例如:所有的方法
- PointCut 切入點:已經被增強的連接點。例如:addUser()
- Advice 通知/增強,增強代碼。例如:after、before
- Weaving(織入):是指把增強advice應用到目標對象target來創建新的代理對象proxy的過程.
- Aspect(切面): 是切入點pointcut和通知advice的結合
3.AOP的特點
1)降低模塊與模塊之間的耦合度,提高業務代碼的聚合度。(高內聚低耦合)
2)提高瞭代碼的復用性
3)提高系統的擴展性。(高版本兼容低版本)
4)可以在不影響原有的功能基礎上添加新的功能
二、springBoot 使用 AOP 實現流程
1.引入依賴
<!-- Spring AOP --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2.封裝記錄日志實體類
@Getter @Setter @ApiModel(value = "Systemlog對象", description = "") public class Systemlog implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty("ID") @TableId(value = "id", type = IdType.AUTO) private Integer id; @ApiModelProperty("用戶名") private String userName; @ApiModelProperty("用戶ID") private Integer userId; @ApiModelProperty("操作描述") private String operate; @ApiModelProperty("模塊") private String module; @ApiModelProperty("創建日志時間") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; @ApiModelProperty("操作結果") private String result; }
3.編寫註解類(自定義日志註解類)
/** * controller層切面日志註解 * @author hsq */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface SystemControllerLog { // 操作描述 String operate(); // 模塊 String module(); }
4.編寫操作日志的切面類
** * @author hsq */ @Aspect @Component public class SystemLogAspect { private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class); @Autowired private ISystemlogService iSystemlogService; @Autowired private UserService userService; /** * Controller層切點 */ @Pointcut("@annotation(com.hsq.demo.config.SystemControllerLog)") public void SystemControllerLog(){ } /** * 前置通知 用於攔截Controller層記錄用戶的操作的開始時間 * @param joinPoint 切點 * @throws InterruptedException */ @Before("SystemControllerLog()") public void doBefore(JoinPoint joinPoint) throws InterruptedException{ logger.info("進入日志切面前置通知!"); } @After("SystemControllerLog()") public void doAfter(JoinPoint joinPoint) { logger.info("進入日志切面後置通知!"); } /**value切入點位置 * returning 自定義的變量,標識目標方法的返回值,自定義變量名必須和通知方法的形參一樣 * 特點:在目標方法之後執行的,能夠獲取到目標方法的返回值,可以根據這個返回值做不同的處理 */ @AfterReturning(value = "SystemControllerLog()", returning = "ret") public void doAfterReturning(Object ret) throws Throwable { } /*** * 異常通知 記錄操作報錯日志 * * @param joinPoint * * @param e * */ @AfterThrowing(pointcut = "SystemControllerLog()", throwing = "e") public void doAfterThrowing(JoinPoint joinPoint, Throwable e) { logger.info("進入日志切面異常通知!!"); logger.info("異常信息:" + e.getMessage()); } //使用這個方法先註釋前面三個方法,留before方法就行 /** * 通知包裹瞭目標方法,在目標方法調用之前和之後執行自定義的行為 * ProceedingJoinPoint切入點可以獲取切入點方法上的名字、參數、註解和對象 * @param joinPoint */ @Around("SystemControllerLog() && @annotation(systemControllerLog)") public Result doAfterReturning(ProceedingJoinPoint joinPoint, SystemControllerLog systemControllerLog) throws Throwable { logger.info("設置日志信息存儲到表中!"); //joinPoint.proceed() 結果集 //參數數組 Object[] args = joinPoint.getArgs(); //請求參數數據 String requestJson = JSONUtil.toJsonStr(args); //方法名 String methodName = joinPoint.getSignature().getName(); //得到request HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); //得到token String token = request.getHeader("token"); String userId = JWT.decode(token).getAudience().get(0); User user = userService.getById(userId); logger.info("得到用戶信息:"+user.toString()); //寫入數據庫操作日志 Systemlog systemlog = new Systemlog(); systemlog.setUserId(user.getUid()); systemlog.setUserName(user.getUname()); systemlog.setOperate(systemControllerLog.operate()); systemlog.setModule(systemControllerLog.module()); systemlog.setCreateTime(new Date()); //存入返回的結果集 joinPoint.proceed() Result proceed = (Result) joinPoint.proceed(); systemlog.setResult(JSONUtil.toJsonStr(joinPoint.proceed())); //保存 saveSystemLog(systemlog); return proceed; } }
5.controller使用
@GetMapping("/userListPage") @SystemControllerLog(operate = "用戶查詢",module = "用戶管理") public Result findUserList( @RequestParam Integer pageNum, @RequestParam Integer pageSize, @RequestParam String username, @RequestParam String loveValue, @RequestParam String address) {} @PostMapping("/addOrUpdate") @SystemControllerLog(operate = "用戶修改或者添加",module = "用戶管理") public Result addOrUpdateUser(@RequestBody User user){}
6.數據庫記錄
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。
推薦閱讀:
- 關於aop切面 註解、參數如何獲取
- SpringBoot@Aspect 打印訪問請求和返回數據方式
- Spring AOP實現記錄操作日志
- springboot通過spel結合aop實現動態傳參的案例
- 基於SpringAop中JoinPoint對象的使用說明