在任何一个开发框架中都会涉及到日志模块,在MkFramework中同样也有日志模块,只是日志模块没有那么复杂比较简单,下面就来介绍下框架中日志模块如何实现的。
框架中日志主要使用slf4j和logback进行文件日志记录,后续也会讲到如何在基本不改动代码的情况下将日志记录到数据库中。日常的info、error这些日志的记录方式和大家常见的用法一样,今天在框架中增加的系统日志是切面日志的功能,通过注解来实现系统日志的记录,框架中的系统日志记录的数据结构大家可以根据自己公司的要求进行定制,不局限在我这里列出的。
下面说下实现的效果,就是在需要记录系统日志的方法前面加上注解@SysLog就可以自动记录这个方法的入参、方法耗时、操作用户,如果是针对网络接口的方法还可以记录请求ip地址、url等相关信息,具体记录哪些都是由开发者自己决定,可以根据框架的现有代码进行定制修改。
@SysLog("测试")
@PostMapping("/test")
public String testController(@RequestBody Map req){
return "hello";
}
加了注解之后会自动记录到文件或数据库中,具体记录到哪里根据代码实现和配置来决定,本篇介绍下记录到文件中的方案。
自动记录的日志信息如下:
2018-09-06 17:09:10.455 c.m.c.service.impl.SysLogServiceImpl : {id=null, username='null', operation='测试', method='com.monkey01.modules.module1.controller.TestController.testController()', url='http://localhost:8090/mk/test', params='{"test":"1234"}', time=22, ip='0:0:0:0:0:0:0:1', createDate=Thu Sep 06 17:09:10 CST 2018}
是不是很方便,用来查问题的关键信息都可以根据你的要求写到日志,不用在在logger后面加一堆信息了,在要记录日志的方法前面加上一个@SysLog注解就可以自动记录这些日志信息了,是不是很方便,下面看看如何来实现的。
首先定义SysLog注解,因为是环绕注解定义的类型是METHOD,只能适用于函数方法。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
String value() default "";
}
定义好了注解,下面就要开始定义处理注解的类,这里为了进行全局处理我们定义了切面类。这里就不介绍具体如何进行自定义注解了,想了解的同学可以看下我之前的一篇文章Java自定义注解详解+实例。我将在切面类中记录日志的主要操作都写了注释,具体实现看注释就很容易理解了。
@Aspect
@Component
public class SysLogAspect {
@Autowired
private SysLogService sysLogService;
@Pointcut("@annotation(com.monkey01.common.annotation.SysLog)")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
//执行方法
Object result = point.proceed();
//执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//保存日志
saveSysLog(point, time);
return result;
}
private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
SysLogDO sysLog = new SysLogDO();
SysLog syslog = method.getAnnotation(SysLog.class);
if(syslog != null){
//记录注解上的描述,在实际使用过程中可以将具体的业务描述信息写在里面,这样查询日志比较方便
sysLog.setOperation(syslog.value());
}
//获取请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
sysLog.setMethod(className + "." + methodName + "()");
//获取请求的参数并转换成json字符串方便查看
Object[] args = joinPoint.getArgs();
try{
String params = new Gson().toJson(args[0]);
sysLog.setParams(params);
}catch (Exception e){
}
//如果是针对网络请求的系统日志可以获取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
//设置IP地址
sysLog.setIp(IPUtils.getIpAddr(request));
//设置请求URL
sysLog.setUrl(request.getRequestURL().toString());
sysLog.setTime(time);
sysLog.setCreateDate(new Date());
//保存系统日志
sysLogService.saveSysLog(sysLog);
}
}
从代码中大家可以发现还需要定义SysLog的实体类、SysLogService处理类,这里就不贴具体代码了具体代码参看github上源码,SysLog实体类中主要是定义了需要系统日志记录的关键信息,这里大家可以自己根据需要定制。在SysLogService中主要是对日志处理进行了抽象,第一版是只记录到文件,后续的版本会支持记录到数据库或者文件数据库同时记录。大家可以通过TestController里的测试接口进行测试,看看在控制台和日志文件里是不是按照你的需要自动记录了系统日志。
这篇比较简单先让大家热热身后面会讲到很多大家在实际项目中用到的数据库操作、接口安全防护、异常统一处理等等。
为了方便大家根据自己的进度看代码,我将每篇文章对应的可执行工程都单独打了tag发布到github上,例如本篇是篇1,那么对应的tag是v0.1-SysLog , 大家可以点击直接下载,也可以通过git clone –b v0.1-SysLog https://github.com/feiweiwei/MkFramework4java.git
进行下载,欢迎大家对项目star或fork。
网友评论