记录日志方便排错,记录操作记录。通常有俩层需要加日志:controller层和service层。
controller层的日志使用Log打印信息,service层的日志使用数据库记录操作日志。
Controller层 | 通过添加一个AOP切面,监控controller层的所有方法: 调用之前打印请求信息,包含URL,HTTP_METHOD,IP,CLASS_METHOD,ARGS; 在方法完成后,打印返回的请求结果,包含code, msg。 |
ServiceImpl层 | 创建一张日志表sys_log, 创建一个SysLogService接口和一个SysLogServiceImpl实现类。里面包含一个saveSysLog(...)方法,该方法加@Transactional注解,内置的传播行为为PROPAGATION_REQUIRES_NEW。 在每个其他的service层中注入SysLogService,在每个方法最后加一个插入日志表的操作。 此处不展示。 |
package com.yzx.operateplatform.aspect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yzx.operateplatform.vo.ResultVO;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* 日志切面类
*/
@Aspect
@Component
public class LogAspect {
private final static Logger logger = LoggerFactory.getLogger(LogAspect.class);
// ..表示包及子包 该方法代表controller层的所有方法
@Pointcut("execution(public * com.yzx.operateplatform.controller..*.*(..))")
public void controllerMethod() {
}
@Before("controllerMethod()")
public void LogRequestInfo(JoinPoint joinPoint) throws Exception {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
StringBuffer requestLog = new StringBuffer();
requestLog.append("请求信息:")
.append("URL = {" + request.getRequestURI() + "},\t")
.append("HTTP_METHOD = {" + request.getMethod() + "},\t")
.append("IP = {" + request.getRemoteAddr() + "},\t")
.append("CLASS_METHOD = {" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName() + "},\t");
if(joinPoint.getArgs().length == 0) {
requestLog.append("ARGS = {} ");
} else {
requestLog.append("ARGS = " + new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL)
.writeValueAsString(joinPoint.getArgs()[0]) + "");
}
logger.info(requestLog.toString());
}
@AfterReturning(returning = "resultVO", pointcut = "controllerMethod()")
public void logResultVOInfo(ResultVO resultVO) throws Exception {
logger.info("请求结果:" + resultVO.getCode() + "\t" + resultVO.getMsg());
}
}
注意:
如果有BaseController的话,不需要被日志扫描,可以通过添加不扫描路径即可。如下:
package com.yzx.codedemo.vo;
import io.swagger.annotations.ApiModelProperty;
/**
* 返回结果类
*
* @param 类型
*/
public class ResultVO {
@ApiModelProperty("状态码 0失败 1成功 ")
private Integer code;
@ApiModelProperty("返回信息")
private String msg;
@ApiModelProperty("返回数据")
private T data;
public ResultVO(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public ResultVO(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
/**
* 请求成功 状态码 1
*
* @param msg 返回信息
* @param 类型
* @return ResultVO
*/
public static ResultVO getSuccess(String msg) {
return new ResultVO(1, msg);
}
/**
* 请求成功 状态码 1
*
* @param msg 返回信息
* @param data 返回对象
* @param 类型
* @return ResultVO
*/
public static ResultVO getSuccess(String msg, T data) {
return new ResultVO(1, msg, data);
}
/**
* 请求失败 状态码 0
*
* @param msg 返回信息
* @param 类型
* @return ResultVO
*/
public static ResultVO getFailed(String msg) {
return new ResultVO(0, msg);
}
/**
* 请求失败 状态 0
*
* @param msg 返回信息
* @param data 返回数据
* @param 类型
* @return ResultVO
*/
public static ResultVO getFailed(String msg, T data) {
return new ResultVO(0, msg, data);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
package com.yzx.codedemo.controller.user;
import com.yzx.codedemo.entity.user.SysUser;
import com.yzx.codedemo.service.user.SysUserService;
import com.yzx.codedemo.vo.PageVO;
import com.yzx.codedemo.vo.ResultVO;
import com.yzx.codedemo.vo.user.SysUserVO;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;
import java.util.List;
@Api(tags = {"SysUserController"}, description = "用户Controller")
@RestController
@RequestMapping(value = "/sysuser")
public class SysUserController {
@Autowired
private SysUserService sysUserService;
@ApiOperation("查询用户分页列表")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "query", dataType = "Long", name = "currentPage", value = "当前页码", required = true),
@ApiImplicitParam(paramType = "query", dataType = "Long", name = "pageSize", value = "每页记录数", required = true),
@ApiImplicitParam(paramType = "query", dataType = "String", name = "userName", value = "用户名称", required = false),
@ApiImplicitParam(paramType = "query", dataType = "String", name = "phone", value = "手机号", required = false),
@ApiImplicitParam(paramType = "query", dataType = "Long", name = "userState", value = "用户状态: 0删除 1正常", required = false),
@ApiImplicitParam(paramType = "query", dataType = "String", name = "starttime", value = "开始时间 格式:yyyy-MM-dd HH:mm:ss", required = false),
@ApiImplicitParam(paramType = "query", dataType = "String", name = "endtime", value = "结束时间 格式:yyyy-MM-dd HH:mm:ss", required = false)
})
@GetMapping(value = "/page")
public ResultVO> selectSysUserPage(@ApiIgnore SysUserVO sysUserVO) {
try {
return this.sysUserService.selectSysUserPage(sysUserVO);
} catch (Exception e) {
e.printStackTrace();
return ResultVO.getSuccess("查询用户分页列表失败");
}
}
}
每次调用controller层的代码的方法,都会打印日志信息:
2018-08-22 16:17:12.251 INFO 12200 --- [nio-8080-exec-1] com.yzx.codedemo.aspect.LogAspect : 请求信息:URL = {/sysuser/page}, HTTP_METHOD = {GET}, IP = {0:0:0:0:0:0:0:1}, CLASS_METHOD = {com.yzx.codedemo.controller.user.SysUserController.selectSysUserPage}, ARGS = {"currentPage":1,"pageSize":10}
2018-08-22 16:17:12.319 DEBUG 12200 --- [nio-8080-exec-1] c.y.c.m.u.S.selectSysUserPage_COUNT : ==> Preparing: SELECT count(0) FROM sys_user WHERE 1 = 1
2018-08-22 16:17:12.336 DEBUG 12200 --- [nio-8080-exec-1] c.y.c.m.u.S.selectSysUserPage_COUNT : ==> Parameters:
2018-08-22 16:17:12.351 DEBUG 12200 --- [nio-8080-exec-1] c.y.c.m.u.S.selectSysUserPage_COUNT : <== Total: 1
2018-08-22 16:17:12.356 DEBUG 12200 --- [nio-8080-exec-1] c.y.c.m.u.S.selectSysUserPage : ==> Preparing: SELECT id AS user_id, user_name, password, phone, createtime FROM sys_user WHERE 1=1 ORDER BY createtime DESC LIMIT ?
2018-08-22 16:17:12.357 DEBUG 12200 --- [nio-8080-exec-1] c.y.c.m.u.S.selectSysUserPage : ==> Parameters: 10(Integer)
2018-08-22 16:17:12.363 DEBUG 12200 --- [nio-8080-exec-1] c.y.c.m.u.S.selectSysUserPage : <== Total: 10
2018-08-22 16:17:12.365 INFO 12200 --- [nio-8080-exec-1] com.yzx.codedemo.aspect.LogAspect : 请求结果:1 查询分页列表成功