1. 创建自定义注解
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationDetail {
/**
* 方法描述
*/
String detail() default "";
/**
* 日志操作级别
*/
int level() default 0;
/**
* 操作了类型,默认为未知
*/
OperationType operationType() default OperationType.UNKNOWN;
/**
* 操作对象,默认为未知
*/
OperationUnit operationUnit() default OperationUnit.UNKNOWN;
/**
* 操作人
*/
String operator() default "UNKNOWN" ;
}
上面代码用到的枚举类
public enum OperationType {
/**
* 操作类型
*/
UNKNOWN("unknown"),
DELETE("delete"),
SELECT("select"),
UPDATE("update"),
INSERT("insert");
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
OperationType(String s) {
this.value = s;
}
}
public enum OperationUnit {
/**
* 被操作的单元
*/
UNKNOWN("unknown"),
DELETE("delete"),
SELECT("select"),
UPDATE("update"),
INSERT("insert"),
// 导出
EXPORT("export"),
// 下载
DOWNLOAD("download"),
// 修改密码
UPDATE_PASSWORD("update_password"),
// 登录
LOGIN_SYSTEM("login"),
// 退出登录
LOGOUT("logout");
private String value;
OperationUnit(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
2.创建切面
@Slf4j
@Aspect
@Component
public class OperationLogAspect {
@Autowired
ApplicationContext applicationContext;
OperationLogRecordService operationLogRecordService;
/**
* 注解方式的切点
*/
@Pointcut("@annotation(com.c2m.log.annotation.OperationDetail)")
public void operationDetail(){}
/**
*环绕增强
* @return
*/
@Around("operationDetail()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable{
Object res = null;
JSONObject json = new JSONObject();
try {
json = this.resolvingArgs(joinPoint);
res = joinPoint.proceed();
json.put("requestResult", res);
return res;
}finally {
try{
operationLogRecordService = applicationContext.getBean(OperationLogRecordService.class);
operationLogRecordService.record(json);
}catch (NoSuchBeanDefinitionException e){
log.info("操作日志:"+json.toJSONString());
}catch (Exception e){
e.printStackTrace();
}
}
}
private JSONObject resolvingArgs(ProceedingJoinPoint joinPoint){
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
OperationDetail annotation = signature.getMethod().getAnnotation(OperationDetail.class);
String methodName,operationType,operationUnit,operationDetail,operator;
// 方法名称
methodName = signature.getMethod().getName();
// 操作类型("insert、delete、update、select")
operationType = annotation.operationType().getValue();
// 业务功能("用户登陆、审核信息、导出文件、删除用户···")
operationUnit = annotation.operationUnit().getValue();
// 操作描述
String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
operationDetail = this.replaceParams(argNames, joinPoint.getArgs(), annotation.detail());
//操作人
operator = this.replaceParams(argNames, joinPoint.getArgs(), annotation.operator());
// 请求参数
Object[] objects = joinPoint.getArgs();
String params = "";
if (objects.length > 0) {
if (objects[0] instanceof String) {
params = objects[0].toString();
} else {
params = JSONObject.toJSONString(objects[0]);
}
}
Map<String,Object> resMap = new HashMap<>();
resMap.put("requestParameters",params);
resMap.put("methodName",methodName);
resMap.put("operationType",operationType);
resMap.put("operationUnit",operationUnit);
resMap.put("operationDetail",operationDetail);
resMap.put("operator",operator);
return new JSONObject(resMap);
}
/**
* 对当前登录用户和占位符处理
*
* @param argNames 方法参数名称数组
* @param args 方法参数数组
* @param str 被替换的字符串
* @return
*/
private String replaceParams(String[] argNames,Object[] args,String str){
Map<Object, Object> map = new HashMap<>(5);
for(int i = 0;i < argNames.length;i++){
map.put(argNames[i],args[i]);
}
try {
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Object k = entry.getKey();
Object v = entry.getValue();
str = str.replace("$"+k, JSON.toJSONString(v));
}
str = str.replaceAll("\"","");
}catch (Exception e){
e.printStackTrace();
}
return str;
}
/**
* 前置通知
* @param joinPoint
*/
@Before("operationDetail()")
public void doBeforeAdvice(JoinPoint joinPoint){
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
log.info("进入"+signature.getMethod()+"方法前执行.....");
}
/**
* 处理完请求,返回内容
* @param res
*/
@AfterReturning(returning = "res", pointcut = "operationDetail()")
public void doAfterReturning(Object res) {
log.info("方法的返回值 : " + res);
}
/**
* 后置异常通知
*/
@AfterThrowing("operationDetail()")
public void throwsException(JoinPoint joinPoint){
log.info("方法异常时执行.....");
}
/**
* 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
*/
@After("operationDetail()")
public void after(JoinPoint joinPoint){
log.info("方法最后执行.....");
}
}
3. 这里有一个operationLogRecordService,代码如下:
public interface OperationLogRecordService {
/**
* 记录日志
*/
void record(JSONObject json);
}
4.使用方式
在方法上加上这个注解
@OperationDetail(detail = "修改密码", operationUnit = OperationUnit.UPDATE_PASSWORD,operationType = OperationType.UPDATE,operator = "$userName")