实现思路:spring aop切入到bean,在需要写日志的方法加入注解AuditLog,如果没有注解的方法则不记录日志。
注解类
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuditLog {
String description() default "";//操作内容
StoreLogType logType() default StoreLogType.All;//操作类型
}
spring aop切入类
@Aspect
@Component
public class StoreLogCut {
private static final Logger logger = LoggerFactory.getLogger(StoreLogCut.class);
private static final String storeLogJsonParams = "storeLogJsonParams";//切入Controller请求参数为json类型需要将请求对象赋予该名称的属性,以便获取请求参数
private StoreLogService storeLogService;
/**
* Controller层切入点
*/
@Pointcut("execution(public * com.cd.store.controller.*.*(..))")
public void controllerAspect() {
}
/**
* 后置返回通知
*
* @param joinpoint
* @param returnValue
* @throws Throwable
*/
@AfterReturning(value = "controllerAspect()", returning = "returnValue")
public void after(JoinPoint joinpoint, Object returnValue) throws Throwable {
writeLog(joinpoint, returnValue);
}
/**
* 异常返回通知
*
* @param joinpoint
* @param errorMsg
*/
@AfterThrowing(value = "controllerAspect()", throwing = "errorMsg")
public void afterThrowException(JoinPoint joinpoint, Exception errorMsg) {
writeLog(joinpoint, errorMsg);
}
/**
* 记录日志
*
* @param joinpoint
* @param obj
*/
private void writeLog(JoinPoint joinpoint, Object obj) {
try {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
StoreLogDescDto storeLogDescDto = getControllerMethodDescription(joinpoint);
String action = storeLogDescDto.getAction();
// 如果加了日志注解类则写入日志到数据库
if (StringUtils.isNotBlank(action)) {
int result = StoreLogResultType.success.getType();
String returnMsg = "";
if (obj instanceof Exception) {// 异常通知
result = StoreLogResultType.Error.getType();
returnMsg = ((Exception) obj).getMessage();
} else {// 正常返回通知
returnMsg = String.valueOf(obj);
// 解析返回的数据(如返回false则为失败)
result = getProcessResult(returnMsg);
}
String userName = getUserName(request);// 获取操作人
String ip = Utils.getRequestIp(request);// 获取客户端ip地址
String param = Utils.getParam(request,joinpoint,storeLogJsonParams);// 获取请求参数
String requestUrl = String.valueOf(request.getRequestURL());
storeLogService.insertLog(userName, ip, param, action, storeLogDescDto.getType(), result, returnMsg,requestUrl);
}
} catch (Exception e) {
String errorMsg = new StringBuilder().append("write log to database error,").append(e.getMessage())
.toString();
logger.error(errorMsg);
}
}
private int getProcessResult(String returnMsg) {
if (StringUtils.isNotBlank(returnMsg) && "false".equalsIgnoreCase(returnMsg)) {
return StoreLogResultType.Error.getType();
}
return StoreLogResultType.success.getType();
}
/**
* 获取用户名
*
* @param request
* @return
*/
private String getUserName(HttpServletRequest request) {
HttpSession session = request.getSession();
Object userNameObj = session.getAttribute(Constants.SS_ACCOUNT);
String userName = "";
if (userNameObj != null) {
userName = (String) userNameObj;
}
return userName;
}
/**
* 获取注解中对方法的描述信息 用于Controller层注解
*
* @param joinPoint
* 切点
* @return 方法描述
* @throws Exception
*/
private StoreLogDescDto 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();
StoreLogDescDto storeLogDescDto = new StoreLogDescDto();
String description = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
AuditLog storeLogAnnotation = method.getAnnotation(AuditLog.class);
if (storeLogAnnotation != null) {
description = storeLogAnnotation.description();
int type = storeLogAnnotation.logType().getType();
storeLogDescDto.setAction(description);
storeLogDescDto.setType(type);
break;
}
}
}
}
return storeLogDescDto;
}
public StoreLogService getStoreLogService() {
return storeLogService;
}
@Autowired
@Required
public void setStoreLogService(StoreLogService storeLogService) {
this.storeLogService = storeLogService;
}