Logs 实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel
public class Logs implements Serializable {
private static final long serialVersionUID = -89998567097386518L;
/**
* 日志ID
*/
@ApiModelProperty(hidden = true)
private Integer opid;
/**
* 操作时间
*/
@ApiModelProperty(name = "optime",value = "操作时间",
dataType = "string",example = "2021-12-28")
private String optime;
/**
* 操作ip
*/
@ApiModelProperty(name = "ip",value = "操作IP",
dataType = "string",example = "192.168.1.1")
private String ip;
/**
* 操作方法
*/
@ApiModelProperty(name = "methods",value = "操作方法",
dataType = "string",example = "save")
private String methods;
/**
* 操作方法描述
*/
@ApiModelProperty(name = "ddesc",value = "操作方法描述",
dataType = "string",example = "添加xxx数据")
private String ddesc;
}
AdministratorsController
@RestController
@RequestMapping("/administrators")
@Api(tags = "管理员控制器")
@CrossOrigin //解决跨域访问
public class AdministratorsController {
@Resource
private AdministratorsService administratorsService;
@ApiImplicitParams({
@ApiImplicitParam(name = "page",value = "分页起始数据",example = "1",required = true,dataType = "integer"),
@ApiImplicitParam(name = "size",value = "每页显示最大记录数",example = "10",required = true,dataType = "integer"),
@ApiImplicitParam(name = "username",value = "管理员姓名",example = "小杨",dataType = "string")
})
@GetMapping("/listPage")
@ApiOperation("分页查询管理员信息")
@SystemControllerLog(description = "分页查询管理员信息") //一会儿的自定义注解
public CommonResult listpage(int page, int size, String username){
Map<String,Object> map= new HashMap();
map.put("data",administratorsService.listpage(page,size,username));
map.put("count",administratorsService.count(username));
return CommonResult.success(map);
}
}
LogsService
package com.vrms.app.service;
import com.vrms.app.entity.Logs;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface LogsService {
List<Logs> listPage(@Param("page") int page,
@Param("size") int size);
int count();
boolean save(Logs logs);
}
LogsServiceImpl
@Service
public class LogsServiceImpl implements LogsService {
@Resource
private LogsDao logsDao;
@Override
public List<Logs> listPage(int page, int size) {
return logsDao.listPage((page - 1) * size, size);
}
@Override
public int count() {
return logsDao.count();
}
@Override
public boolean save(Logs logs) {
return logsDao.save(logs) > 0;
}
}
LogsDao
package com.vrms.app.dao;
import com.vrms.app.entity.Logs;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface LogsDao {
List<Logs> listPage(@Param("page") int page,
@Param("size") int size);
int count();
int save(Logs logs);
}
LogsDao.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.vrms.app.dao.LogsDao">
<insert id="save">
insert into logs(optime, ip, methods, ddesc)
values (#{optime}, #{ip}, #{methods}, #{ddesc})
</insert>
<select id="listPage" resultType="com.vrms.app.entity.Logs">
select *
from logs
order by opid desc
limit #{page},#{size}
</select>
<select id="count" resultType="java.lang.Integer">
select count(*)
from logs
</select>
</mapper>
自定义注解SystemControllerLog
package com.vrms.app.aop;
import java.lang.annotation.*;
@Target({ElementType.PARAMETER, ElementType.METHOD})//作用在参数和方法上
@Retention(RetentionPolicy.RUNTIME)//运行时注解
@Documented//表明这个注解应该被 javadoc工具记录
public @interface SystemControllerLog {
String description() default "";
}
SystemLogAspect
package com.vrms.app.aop;
import com.vrms.app.entity.Logs;
import com.vrms.app.service.LogsService;
import org.aspectj.lang.JoinPoint;
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.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
@Aspect
@Component
public class SystemLogAspect {
private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);
@Resource
private LogsService logsService;
//Controller层切点
@Pointcut("@annotation(SystemControllerLog)")
public void controllerAspect() {
}
@Before("controllerAspect()")
public void doBefore(JoinPoint joinPoint) {
HttpServletRequest request = ((ServletRequestAttributes)
RequestContextHolder.getRequestAttributes()).getRequest();
try {
Logs logs = new Logs();
logs.setMethods((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName()));
logs.setDdesc(getControllerMethodDescription(joinPoint));
logs.setIp(request.getRemoteAddr()); //获得访问IP地址记录到日志的IP属性中
logs.setOptime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
if(logsService.save(logs)){
System.out.println("日志添加成功");
}else{
System.out.println("日志添加失败");
}
} catch (Exception e) {
//记录本地异常日志
logger.error("==前置通知异常==");
logger.error("异常信息:{}", e.getMessage());
}
}
/**
* @Description 获取注解中对方法的描述信息 用于Controller层注解
*/
public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception {
String targetName = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();//目标方法名
Object[] arguments = joinPoint.getArgs();
Class targetClass = Class.forName(targetName);
Method[] methods = targetClass.getMethods();
String description = "";
for (Method method : methods) {
if (method.getName().equals(methodName)) {
Class[] clazzs = method.getParameterTypes();
if (clazzs.length == arguments.length) {
description = method.getAnnotation(SystemControllerLog.class).description();
break;
}
}
}
return description;
}
}
获取注解中对方法的描述信息其他方式
/**
* @Description 获取注解中对方法的描述信息 用于Controller层注解
*/
public static String getControllerMethodDescription(JoinPoint joinPoint) {
MethodSignature methodSignature =(MethodSignature) joinPoint.getSignature();
SystemLog systemLog = methodSignature.getMethod ().getAnnotation(SystemLog.class);
return systemLog.description();
}
获取注解中对方法的描述信息其他方式(环绕通知中参数为ProceedingJoinPoint)
/**
* @Description 获取注解中对方法的描述信息 用于Controller层注解 (环绕通知参数为 ProceedingJoinPoint)
*/
public static String getControllerMethodDescription(ProceedingJoinPoint joinPoint) {
MethodSignature methodSignature =(MethodSignature) joinPoint.getSignature();
SystemLog systemLog = methodSignature.getMethod ().getAnnotation(SystemLog.class);
return systemLog.description();
}