目录
- 依赖引入
- 创建表
- 对象实体类
- 注解方法
- service方法
- 工具类
- 注解实现方法
依赖引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
创建表
DROP TABLE IF EXISTS `logger_record`;
CREATE TABLE `logger_record` (
`id` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'id',
`description` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
`package_name` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作所在的包',
`class_name` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作的类名',
`method_name` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作的方法名',
`request_params` text CHARACTER SET utf COLLATE utf8_general_ci NULL COMMENT '操作方法的参数',
`response_params` text CHARACTER SET utf COLLATE utf8_general_ci NULL COMMENT '操作方法的出参',
`running_time` bigint NULL DEFAULT NULL COMMENT '运行时间',
`created_by` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人ID',
`date_created` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS =;
对象实体类
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.**.app.common.util.TimeUtils;
import lombok.Data;
import org.springframework.data.annotation.Id;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
/**
* Created by cb on/11/15 10:07
*/
//@Entity
@Data
public class LoggerRecord implements Serializable {
@Id
@TableId(value = "id",type = IdType.ID_WORKER_STR)//可不引入注解,UUID生成
private String id;
/**
* 操作方法的描述
*/
private String description;//实际没用上
/**
* 操作所在的包
*/
private String packageName;
/**
* 操作的类名
*/
private String className;
/**
* 操作的方法名
*/
private String methodName;
/**
* 操作方法的参数
*/
private String requestParams;
/**
* 操作方法的出参
*/
private String responseParams;
/**
* 运行时间
*/
private Long runningTime;
/** 创建时间 */
@JsonFormat(pattern = TimeUtils.PATTERN)
private LocalDateTime dateCreated;//可以用date
/** 创建人ID */
private String createdBy;//实际没用上
}
注解方法
package com.**.app.server.annotation;
import java.lang.annotation.*;
/**
* Created by cb on/11/15 10:05
* 日志描述的注解
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LoggerManager {
}
service方法
可根据自己项目去相应改动
/**
* 日志增删改的接口
* Created by cb on/11/15 10:11
*/
@Service
public class LoggerRecordRepository extends ServiceImpl<LoggerRecordMapper, LoggerRecord> {
}
工具类
package com.**.app.server.util;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* Created by cb on/11/15 10:24
*/
public class AopUtil {
/**
* 获取切点处的方法
* @param joinPoint
* @return
*/
public static Method getMethod(JoinPoint joinPoint){
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
return method;
}
/**
// * 将参数数组转化为字符串
// * @param params 参数数组
// * @return 参数字符串
// */
public static String getStringOfParams(Object[] params) {
if (params.length <= || params.length > 1024 || null == params) {
return "";
}
StringBuffer paramString = new StringBuffer("参数: ");
for (Object param : params) {
//将参数转换成字符串
String s = ToStringBuilder.reflectionToString(param);
paramString.append(s).append("||");
}
return paramString.toString();
}
/**
* 转换request 请求参数
* @param paramMap request获取的参数数组
*/
public static Map<String, String> converMap(Map<String, String[]> paramMap) {
Map<String, String> rtnMap = new HashMap<String, String>();
for (String key : paramMap.keySet()) {
rtnMap.put(key, paramMap.get(key)[]);
}
return rtnMap;
}
}
注解实现方法
package com.**.app.server.annotation;
import com.alibaba.fastjson.JSON;
import com.**.app.server.entity.log.LoggerRecord;
import com.**.app.server.service.LoggerRecordRepository;
import com.**.app.server.util.AopUtil;
import lombok.extern.slfj.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Map;
/**
* Created by cb on/11/15 10:19
*/
@Aspect
@Service
@Slfj
public class LoggerAdvice {
@Resource
private LoggerRecordRepository loggerRecordRepository;
/**
* 切点,在注解处切入
*/
@Pointcut("@annotation(com.safety.app.server.annotation.LoggerManager)")
public void AroundPointCut(){
}
/**
* 环绕通知 @Around , 当然也可以使用 @Before (前置通知) @After (后置通知)
* @param point
* @return
* @throws Throwable
*/
@Around("AroundPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
Object result = point.proceed();
long time = System.currentTimeMillis() - beginTime;
try {
LoggerRecord loggerRecord = saveLog(point, time);
loggerRecord.setResponseParams(JSON.toJSONString(result));
loggerRecordRepository.save(loggerRecord);
} catch (Exception e) {
}finally {
return result;
}
}
/**
* 保存日志
* @param joinPoint
* @param time
*/
private LoggerRecord saveLog(ProceedingJoinPoint joinPoint, long time) {
// 获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
//获取该切点处的方法
Method method = AopUtil.getMethod(joinPoint);
LoggerRecord loggerRecord = new LoggerRecord();
//获取切点处的注解
LoggerManager loggerManager = method.getAnnotation(LoggerManager.class);
if (null == loggerManager) {
return loggerRecord;
}
//获取请求的描述
// String description = loggerManager.
//获取请求包名
Signature signature = joinPoint.getSignature();
//获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
//获取请求的方法名
String methodName = method.getName();
//获取请求的参数
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, String> stringStringMap = AopUtil.converMap(parameterMap);
log.info("执行===" + methodName + "===开始");
//打印方法名
log.info("方法名:" + signature.toString());
//打印方法参数
log.info("方法参数:" + JSON.toJSONString(stringStringMap));
log.info("执行===" + methodName + "===结束");
//将日志保存
// loggerRecord.setDescription(description);
loggerRecord.setPackageName(signature.toString());
loggerRecord.setClassName(className);
loggerRecord.setMethodName(methodName);
loggerRecord.setRunningTime(time);
loggerRecord.setRequestParams(JSON.toJSONString(stringStringMap));
return loggerRecord;
}
}
最后只需要在自己的接口上加注解@LoggerManager就可以实现此方法的入参出参日志保存
/**
* 测试
*/
@GetMapping("/test")
@ResponseBody
@LoggerManager
public ResponseResult test(@RequestParam("userName") String userName) throws BusinessException {
Map<String, Object> verifyCodeMap = VerifyCodeUtils.verifyCode();
redisUtils.set(VERIFY_CODE + userName, verifyCodeMap,);
return new ResponseResult(verifyCodeMap);
}
保存数据库后的图片:
注:所有‘**’的地方为自己项目的包名。 好了,下期会改版此日志保存方法,在数据库配置接口名称 就可以实现日志的打印保存。