1. 程式人生 > >springboot-aop面向切面編程

springboot-aop面向切面編程

length mapping === public namespace sqlserver 配置文件 hot ppi

需求:

項目中需要記錄用戶操作信息,例如用戶登陸系統後做了那些操作,需要有具體的日誌記錄。

解決辦法:

1、編寫操作記錄日誌業務類,在使用的方法中調用(一般記錄方式)。

2、使用面向切面方式記錄日誌,例如針對某些業務處理方法進行日誌記錄。

3、通過註解方式,在調用的業務方法上增加日誌類註解。

推薦使用第二、第三中方式,使用靈活,如果不需要日誌記錄,將切面取消即可,第一種不夠靈活。一些介紹使用註解方式編寫日誌記錄。

項目結構如下:

在pom.xml導入依賴包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example.springboot</groupId>
<artifactId>springboot-aop</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>springboot-aop</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.7</java.version>
</properties>

<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- log4j 日誌記錄 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
<!--aop依賴包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- 引入mybatis 數據庫操作包 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

<!-- 引入mybatis 分頁插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.0</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>


</project>
在application.properties配置文件中增加數據庫連接
#server.port=8090

#標示使用的是mysql/oracle/sqlserver
datasource.type=mysql
#mysql數據連接
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
#spring.datasource.max-active=20
#spring.datasource.max-idle=8
#spring.datasource.min-idle=8
#spring.datasource.initial-size=20

#mybatis 配置
# 配置映射文件加載
mybatis.mapper-locations=classpath*:mapper/**/*.xml
# 實體類通過別名使用
#mybatis.type-aliases-package=


自定義註解類

package com.example.springboot.aop.annotation;

import java.lang.annotation.*;

/**
*自定義註解 攔截Controller
*/

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemControllerLog {
String LogAction() default "";
String LogContent() default "";
int ModuleID() default 0;
}
實體類

package com.example.springboot.aop.entity;

public class SystemLogModel {
private String LogAction;
private String LogContent;
private String FlagID;
private String FlagName;
private String LogIP;
private String TimeFlag;
private int ModuleID;

自定義切面類

package com.example.springboot.aop.aspect;

import com.example.springboot.aop.annotation.SystemControllerLog;
import com.example.springboot.aop.dao.SystemLogMapper;
import com.example.springboot.aop.entity.SystemLogModel;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* 切點類
*/
@Aspect
@Component
public class SystemLogAspect {

// 本地異常日誌記錄對象
private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);

@Autowired
private SystemLogMapper systemLogMapper;

// Controller層切點,針對在業務模塊標註SystemControllerLog註解記錄日誌
@Pointcut("@annotation( com.example.springboot.aop.annotation.SystemControllerLog )")
public void controllerAspect() {
}

/**
* 前置通知 用於攔截Controller層記錄用戶的操作
*
* @param joinPoint 切點
*/
@Before("controllerAspect()")
public void doBefore(JoinPoint joinPoint) {

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();
try {
// 請求的IP
String logIP = request.getHeader("X-Real-IP");
// if (StringUtils.isEmpty(logIP)) {
// logIP = request.getRemoteAddr();
// }
String userID = request.getParameter("UserID");
String userName = request.getParameter("UserName");
// if (StringUtils.isEmpty(userID) || StringUtils.isEmpty(userName)) {
// logger.debug("操作日誌-->日誌添加:用戶名或用戶ID為空,返回不添加日誌!");
// return;
// }

SystemLogModel slm = getControllerMethodDescription(joinPoint);
slm.setLogIP(logIP);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:MM:ss");
String date = dateFormat.format(new Date());
slm.setTimeFlag(date);
slm.setFlagID(userID);
slm.setFlagName(userName);

// *========控制臺輸出=========*//
logger.debug("=====註解參數獲取開始=====");
logger.debug("請求方法:"
+ (joinPoint.getTarget().getClass().getName() + "."
+ joinPoint.getSignature().getName() + "()"));
logger.debug("操作模塊:" + slm.getModuleID());
logger.debug("操作方法:" + slm.getLogAction());
logger.debug("操作內容:" + slm.getLogContent());
logger.debug("請求IP:" + slm.getLogIP());
logger.debug("FlagID:" + slm.getFlagID());
logger.debug("FlagName:" + slm.getFlagName());
// *========數據庫日誌=========*//
int res = systemLogMapper.saveOrUpdate(slm);
if (res > 0) {
logger.info(">>>>>>>>保存日誌成功");
}
} catch (Exception e) {
// 記錄本地異常日誌
logger.error("前置通知異常,保存日誌異常信息:{}", e.getMessage());
}
}

/**
* 獲取註解中對方法的描述信息 用於Controller層註解
*
* @param joinPoint 切點
* @return 方法描述
* @throws Exception
*/
public static SystemLogModel getControllerMethodDescription(
JoinPoint joinPoint) throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String description = "";
SystemControllerLog log;
SystemLogModel logM = new SystemLogModel();
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
log = method.getAnnotation(SystemControllerLog.class);
logM.setModuleID(log.ModuleID());
logM.setLogAction(log.LogAction());
logM.setLogContent(log.LogContent());
break;
}
}
}
return logM;
}
}

mapper接口

package com.example.springboot.aop.dao;

import com.example.springboot.aop.entity.SystemLogModel;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface SystemLogMapper {

//保存日誌
public int saveOrUpdate(SystemLogModel systemLogModel);
}
mapper配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.springboot.aop.dao.SystemLogMapper">

<insert id="saveOrUpdate" parameterType="com.example.springboot.aop.entity.SystemLogModel">
insert into test_system_Operation_log(FlagID,FlagName,LogAction,LogContent,LogIP,ModuleID,TimeFlag)
values(#{FlagID},#{FlagName},#{LogAction},#{LogContent},#{LogIP},#{ModuleID},#{TimeFlag})
</insert>

</mapper>
創建controller類

package com.example.springboot.aop.controller;

import com.example.springboot.aop.annotation.SystemControllerLog;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
* @desc aop測試日誌記錄
* @Author wangsh
* @date 2018/5/7 20:57
*/
@RestController
@RequestMapping("/aop")
public class AopController {

@SystemControllerLog(LogAction = "查詢", ModuleID = 12, LogContent = "測試aop示例")
@ResponseBody
@RequestMapping("/hello")
public String hello() {

return "hello";
}
}

創建啟動服務類

package com.example.springboot.aop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

//配置掃描指定的包及包下的所以子集
@ComponentScan("com.example.springboot.aop")
@SpringBootApplication
public class SpringbootAopApplication {

public static void main(String[] args) {
SpringApplication.run(SpringbootAopApplication.class, args);
}
}
啟動服務測試
瀏覽器訪問: http://localhost:8080//aop/hello

查看數據庫記錄:

以上就是aop切面及註解的使用。
---------------------
作者:1057718341_h
來源:CSDN
原文:https://blog.csdn.net/seashouwang/article/details/80232811
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

springboot-aop面向切面編程