Spring AOP 記錄日誌
阿新 • • 發佈:2019-02-08
Spring AOP 最常用的地方之一就是記錄日誌,這裡記錄除了記錄日誌描述外,還記錄了方法請求的引數,並將記錄儲存到資料庫。這裡用到了自定義註解,使用如下
1. 建立 log 日誌類,並生產相應的pojo,pojo如下
public class OperationLog implements Serializable {
/**
*
*/
private static final long serialVersionUID = 7087799444017468909L;
private Integer id;
private String userId;
private String operatType;
private String content;
private String remarks;
private Date create;
// getXXX()和setXXX()省略
}
2. 建立註解類 SystemServiceLog
/**
* AOP 日誌記錄,自定義註解
* @author xxx
* @since JDK1.8
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemServiceLog {
// 日誌描述
String description() default "";
// 操作型別
int tableType() default 0;
}
省略建立dao和service的程式碼
3. 建立攔截方法,這裡只在請求前攔截
@Aspect
@Component
public class SystemLogAspect {
@Autowired
private OperationLogService operationLogService;
@Pointcut ("@annotation(com.xxx.common.annotation.SystemServiceLog)")
public void serviceAspect() {
}
@After("serviceAspect()")
public void doServiceLog(JoinPoint joinPoint) {
// 獲取使用者資訊
Session session = SecurityUtils.getSubject().getSession();
UserInfo user = (UserInfo) session.getAttribute(ShiroDbRealm.SESSIOIN_USER_KEY);
OperationLog log = new OperationLog();
try {
String content = getServiceMthodDescription(joinPoint);
log.setContent(user.getRealName() + content);
log.setRemarks(getServiceMethodParams(joinPoint));
log.setUserId(user.getId());
String operatType = getServiceMthodTableType(joinPoint);
log.setOperatType(operatType);
operationLogService.insert(log);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 獲取註解中對方法的描述資訊 用於service層註解
* @param joinPoint 切點
* @return 方法描述
* @throws ClassNotFoundException
*/
private String getServiceMthodDescription(JoinPoint joinPoint) throws ClassNotFoundException {
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 = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
description = method.getAnnotation(SystemServiceLog.class).description();
break;
}
}
}
return description;
}
/**
* 獲取註解方法中的描述資訊 用於 Service 層註解
* @param joinPoint 切點
* @return 方法描述
* @throws ClassNotFoundException
*/
private String getServiceMthodTableType(JoinPoint joinPoint) throws ClassNotFoundException {
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 = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
description = method.getAnnotation(SystemServiceLog.class).description();
break;
}
}
}
return description;
}
/**
* 獲取json格式的引數<br>
*
* @param joinPoint
* @return
* @since JDK1.8
*/
private String getServiceMethodParams(JoinPoint joinPoint) {
Object[] arguments = joinPoint.getArgs();
if (arguments == null || arguments.length == 0) {
return "無引數";
}
List<Object> list = new ArrayList<>(Arrays.asList(arguments));
String params = JsonUtil.getJsonStringFromPOJO(list);
return params;
}
}
4. 在service的實現類的方法上使用自定義註解記錄日誌
@Override
@Transactional
@SystemServiceLog(description=Constants.CLIENT_SELECT_LIST, tableType=Constants.USER_TABLE_TYPE)
public Map<String, Object> queryXXX(String name, String address) {
Map<String, Object> map = new HashMap<>();
// 省略
return map;
}