Spring Boot 使用AOP記錄操作日誌
阿新 • • 發佈:2018-12-18
前言
在寫Aurora這個專案之前,我是通過攔截器去記錄使用者操作日誌,而這裡講解如何使用AOP配合自定義註解去實現使用者日誌記錄,使用攔截器的方式,下一章貼出
匯入依賴
<!-- aop依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
部分配置檔案
spring:
datasource:
url : jdbc:mysql://localhost:3306/log
username: root
password: 123456
jpa:
hibernate:
ddl-auto: update
自定義log註解
定義一個方法級別的@Log註解,用於標註需要監控的方法:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
String value() default "";
}
建立實體類
@Entity
@Data
@Table (name = "syslog")
public class SysLog implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String operation;
private Integer time;
private String method;
private String params;
private String ip;
/**
* ip地址來源
*/
private String location;
@CreationTimestamp
private Timestamp createTime;
}
建立 repository
@Repository
public interface SysLogRepo extends JpaRepository<SysLog,Long>{
}
切面和切點
定義一個LogAspect類,使用@Aspect標註讓其成為一個切面,切點為使用@Log註解標註的方法,使用@Around環繞通知,部門工具程式碼,這裡就不貼出了,可以到原始碼中檢視
@Slf4j
@Aspect
@Component
public class LogAspect {
@Autowired
private SysLogRepo sysLogRepo;
@Pointcut("@annotation(me.zhengjie.annotation.Log)")
public void pointcut() {
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint point){
Object result = null;
long beginTime = System.currentTimeMillis();
try {
// 執行方法
result = point.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
// 執行時長(毫秒)
long time = System.currentTimeMillis() - beginTime;
//儲存日誌
saveLog(point, time);
return result;
}
public void saveLog(ProceedingJoinPoint joinPoint, long time){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SysLog sysLog = new SysLog();
Log logAnnotation = method.getAnnotation(Log.class);
if (logAnnotation != null) {
// 註解上的描述
sysLog.setOperation(logAnnotation.value());
}
// 請求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
String username = null;
sysLog.setMethod(className + "." + methodName + "()");
// 請求的方法引數值
Object[] args = joinPoint.getArgs();
// 請求的方法引數名稱
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paramNames = u.getParameterNames(method);
if (args != null && paramNames != null) {
String params = "";
for (int i = 0; i < args.length; i++) {
params += " " + paramNames[i] + ": " + args[i];
}
sysLog.setParams(params);
}
// 獲取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
// 設定IP地址
sysLog.setIp(AddressUtils.getIpAddr(request));
sysLog.setLocation(AddressUtils.getCityInfo(sysLog.getIp()));
//模擬一個使用者名稱
sysLog.setUsername("admin");
sysLog.setTime((int) time);
sysLogRepo.save(sysLog);
}
}
專案結構如下
測試
編寫TestController
@RestController
public class TestController {
@Autowired
private SysLogRepo sysLogRepo;
@Log("記錄測試")
@GetMapping(value = "/test")
public String test1(String test){
return test;
}
@GetMapping(value = "/list")
public ModelAndView list(Model model){
List<SysLog> sysLogs = sysLogRepo.findAll();
model.addAttribute("sysLogs",sysLogs);
return new ModelAndView("/index");
}
}
依次訪問:
專案原始碼
開源後臺管理系統
歡迎體驗Aurora