3.基于spring aop和MongoDB的日志储存管理

封装的日志实体:

@Data
public class LogInfo {

private String requestMethod;
private String requestIp;
private String requestUrl;
private Map<String,String[]> parameters;
private Object[] args;
private Date gmtCreate;
private String requestTime;
private Object returnValue;
private String errorMsg;
}

service层

@Service
public class LogInfoServiceImpl implements LogInfoService {

@Autowired
private MongoTemplate mongoTemplate;

/**
* 插入
* @param logInfo
*/
@Override
public void insert(LogInfo logInfo) {
//插入
mongoTemplate.save(logInfo);
//可以使用save或者insert完成插入
//mongoTemplate.insert(logInfo,"collection_name");
}

@Override
public void update(String requestIp,LogInfo logInfo) {
//通过where来设置update依据的属性,然后在来选择update依据属性的依据值(类似jpa)
// 类似:gt:大于,gte:大于等于
// Query query1 = new Query(Criteria.where("requestIp").gt(requestIp));
Query query = new Query(Criteria.where("requestIp").is(requestIp));
//更新采用update对象
// 类似sql中的set,(属性,值)
Update update = new Update();
update.set("gmtCreate",logInfo.getGmtCreate());
//更新一条数据
mongoTemplate.updateFirst(query,update,LogInfo.class);
//更新多条数据
mongoTemplate.updateMulti(query,update,LogInfo.class);
//默认返回旧对象,然后更新新对象
mongoTemplate.findAndModify(query,update,LogInfo.class);
}

@Override
public void delete(String requestIp) {
//删除和更新类似
//通过where来设置update依据的属性,然后在来选择update依据属性的依据值(类似jpa)
// 类似:gt:大于,gte:大于等于
// Query query1 = new Query(Criteria.where("requestIp").gt(requestIp));
Query query = new Query(Criteria.where("requestIp").is(requestIp));
//调用remove删除
mongoTemplate.remove(query,LogInfo.class);
//带返回值的删除
List<LogInfo> list = mongoTemplate.findAllAndRemove(query,LogInfo.class);
}

/**
* 查询全部日志
* @return
*/
@Override
public List<LogInfo> select(){
return mongoTemplate.findAll(LogInfo.class);
//·条件查询
//mongoTemplate.find(query,LogInfo.class);
}
}

切面类

@Component
@Aspect
@Slf4j
public class AopUtils {

@Autowired
private LogInfoService logInfoService;

/**
* 切入点表达式
* 1.格式:方法修饰符 + 返回值类型 + 包名 + 类名 + 方法名 +方法参数
*/
@Pointcut("execution(public * com.springboot.learning.controller.*.*(..))")
public void log(){

}

//环绕通知
@Around("log()")
public Object arround(ProceedingJoinPoint joinPoint) {
LogInfo logInfo = new LogInfo();
try {
log.info("前置通知");
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//请求方式
String requestMethod = request.getMethod();
//请求的ip
String requestIp = request.getRemoteAddr();
//请求的url
String requestUrl = request.getRequestURI().toString();
//请求的参数
Map<String,String[]> parameters = request.getParameterMap();
Object[] args = joinPoint.getArgs();
logInfo.setArgs(args);
//请求时间
Date requestDate = new Date();
//请求精确时间
logInfo.setGmtCreate(requestDate);
//请求时间:yyyy-mm-dd
DateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
//格式转换
String requestTime = dateFormat.format(requestDate);
logInfo.setRequestTime(requestTime);
logInfo.setParameters(parameters);
logInfo.setRequestIp(requestIp);
logInfo.setRequestMethod(requestMethod);
logInfo.setRequestUrl(requestUrl);

//调用目标方法
/**
* Spring AOP的环绕通知和前置、后置通知有着很大的区别,主要有两个重要的区别:
* 1)目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,
* 而前置和后置通知是不能决定的,它们只是在方法的调用前后执行通知而已,
* 即目标方法肯定是要执行的。joinPoint.proceed()就是执行目标方法的代码。
* 2)环绕通知可以控制返回对象,即可以返回一个与目标对象完全不同的返回值。虽然这很危险,但是却可以做到。
*/
Object result = joinPoint.proceed();
log.info("后置通知");
//目标方法返回值
logInfo.setReturnValue(result);
return result;
} catch (Throwable e) {
//异常信息
String errorMsg = e.getMessage();
logInfo.setErrorMsg(errorMsg);
return null;
}finally {
//插入MongoDB
logInfoService.insert(logInfo);
}
}




//
// /**
// * 前置通知
// * 方法执行前通知
// */
// @Before("log()")
// public void before(JoinPoint joinPoint) throws Exception {
//
// }
//
//
// /**
// * 后置通知
// * 方法执行后通知
// */
// @After("log()")
// public void after(JoinPoint joinPoint){
// log.info("后置通知");
//
// }
//
// /**
// * 方法返回通知
// * 接收方法返回值
// * @param result
// */
// @AfterReturning(returning = "result",pointcut = "log()")
// public void afterReturning(Object result){
// //获取方法返回值
// LogInfo logInfo = new LogInfo();
// logInfo.setReturnValue(result);
// }
//
// /**
// * 后置异常通知
// * 当方法抛出异常时调用
// */
// @AfterThrowing("log()")
// public void afterThrowing(JoinPoint joinPoint){
//
// }
}

从controller层开始进行请求的监控,记录请求日志

基于spring aop和MongoDB的日志储存管理_MongoDB

​github​