内容不算原创,是自己东拼西凑整理的,大致框架和操作流程就是这样,需要细化的可以自己再修改
具体实现步骤
1、在pom.xml中添加AOP依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、设计操作日志记录表
3、创建一个操作日志记录的注解
import java.lang.annotation.*;
/**
* @author mei
* @since 2021/9/23
*/
//注解放置的目标位置即方法级别
@Target(ElementType.METHOD)
//注解在哪个阶段执行
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemLogAnnotation {
String optModul() default ""; // 操作模块
String optType() default ""; // 操作类型
String optDesc() default ""; // 操作说明
String optParam() default ""; // 参数
String optUpdateParam() default ""; // 修改内容
}
4、创建操作日志的切面类,将操作日志数据保存到数据库
/**
* 操作日志切面处理类
* @author mei
*/
@Aspect
@Component
public class WebLogAspect {
@Autowired
SystemLogService systemLogService;//保存记录的表service
/**
* 注解的全类名
*/
@Pointcut("@annotation(com.*.*.*.SystemLogAnnotation)")
public void webLogPoinCut() {
}
/**
* 记录操作日志
* @param joinPoint 方法的执行点
* @param result 方法返回值
* @throws Throwable
*/
@AfterReturning(returning = "result", value = "webLogPoinCut()")
public void saveOptLog(JoinPoint joinPoint, Object result) throws Throwable {
//判断是否操作成功
JSONObject jsonObject = (JSONObject) JSONObject.toJSON(result);
if(!"1".equals(jsonObject.getString("code"))){
return;
}
// 获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
try {
SystemLog log = new SystemLog();
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取切入点所在的方法
Method method = signature.getMethod();
//获取切入点所在的类名
//String className=joinPoint.getTarget().getClass().getSimpleName();
//获取操作
SystemLogAnnotation annotation = method.getAnnotation(SystemLogAnnotation.class);
//模块名称
if (annotation != null) {
//操作人{optuser}{增删改查}{原内容}{模块名}为{修改内容}
//操作用户 填自己的
String content = "userName";
//操作类型
if(StringUtils.isNotEmpty(annotation.optType())){
String optType = getOptType(method.getName());
content += "-" + optType;
}else {
content += "-" + annotation.optType();
}
//内容
if(StringUtils.isNotEmpty(getAnnotationValue(joinPoint,annotation.optParam()))){
content += "-" + getAnnotationValue(joinPoint,annotation.optParam());
}
//操作模块和操作说明
content += "-" + annotation.optModul() + "-" + annotation.optDesc();
//修改内容
if(StringUtils.isNotEmpty(getAnnotationValue(joinPoint,annotation.optUpdateParam()))){
content += "为" + getAnnotationValue(joinPoint,annotation.optUpdateParam());
}
log.setContent(content);
}
//操作用户 填自己的
log.setOptUser("userId");
//客户端真实IP
log.setLoginIp(ClientIPUtil.getClientIP(request));
//保存日志
systemLogService.save(log);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取注解中传递的动态参数的参数值
*
* @param joinPoint
* @param name
* @return
*/
public String getAnnotationValue(JoinPoint joinPoint, String name) {
String paramName = name;
// 获取方法中所有的参数
Map<String, Object> params = getParams(joinPoint);
// 参数是否是动态的:#{paramName}
if (paramName.matches("^#\\{\\D*\\}")) {
// 获取参数名
paramName = paramName.replace("#{", "").replace("}", "");
// 是否是复杂的参数类型:对象.参数名
if (paramName.contains(".")) {
String[] split = paramName.split("\\.");
// 获取方法中对象的内容
Object object = getValue(params, split[0]);
// 转换为JsonObject
JSONObject jsonObject = (JSONObject) JSONObject.toJSON(object);
// 获取值
Object o = jsonObject.get(split[1]);
return String.valueOf(o);
}
// 简单的动态参数直接返回
return String.valueOf(getValue(params, paramName));
}
// 非动态参数直接返回
return name;
}
/**
* 根据参数名返回对应的值
*
* @param map
* @param paramName
* @return
*/
public Object getValue(Map<String, Object> map, String paramName) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getKey().equals(paramName)) {
return entry.getValue();
}
}
return null;
}
/**
* 获取方法的参数名和值
*
* @param joinPoint
* @return
*/
public Map<String, Object> getParams(JoinPoint joinPoint) {
Map<String, Object> params = new HashMap<>(8);
Object[] args = joinPoint.getArgs();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String[] names = signature.getParameterNames();
for (int i = 0; i < args.length; i++) {
params.put(names[i], args[i]);
}
return params;
}
public String getOptType(String methodName){
String method = "";
switch (methodName){
case "save":
case "create":
method = "新增";
break;
case "update":
case "edit":
method = "修改";
break;
case "del":
case "delete":
method = "删除";
break;
case "get":
case "list":
method = "查询";
break;
default:
method = "";
break;
}
return method;
}
}
5、客户端真实IP
import javax.servlet.http.HttpServletRequest;
/**
* @author mei
*/
public class ClientIPUtil {
public static String getClientIP(HttpServletRequest request) {
String ip = "";
String ipAddresses = request.getHeader("X-Forwarded-For");
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
ipAddresses = request.getHeader("Proxy-Client-IP");
}
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
ipAddresses = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
ipAddresses = request.getHeader("HTTP_CLIENT_IP");
}
if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
ipAddresses = request.getHeader("X-Real-IP");
}
if (ipAddresses != null && ipAddresses.length() != 0) {
ip = ipAddresses.split(",")[0];
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
6、实际操作-在controller层的方法上加入@SystemLogAnnotation注解
@PostMapping
@SystemLogAnnotation(optModul = "区域模块",optType = "创建",optParam = "#{po}",optDesc = "创建区域")
public Result create(@RequestBody @Validated(value={ValidAdd.class}) Area po) {
areaService.save(po);
return RespUtil.success();
}
@DeleteMapping("/{id}")
@SystemLogAnnotation(optModul = "区域模块",optType = "删除",optParam = "#{id}",optDesc = "删除区域")
public Result delete(@PathVariable Long id) {
areaService.removeById(id);
return RespUtil.success();
}
7、操作结果
版权声明:本文为weixin_38006002原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。