1、实现前准备,Mysql数据库中创建表 CREATE TABLE `sys_log` ( `oper_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志主键', `ti
CREATE TABLE `sys_log` ( `oper_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志主键', `title` varchar(50) DEFAULT '' COMMENT '模块标题', `business_type` int(11) DEFAULT '0' COMMENT '业务类型(0其它 1新增 2修改 3删除)', `method` varchar(100) DEFAULT '' COMMENT '方法名称', `request_method` varchar(10) DEFAULT '' COMMENT '请求方式', `operator_type` int(11) DEFAULT '0' COMMENT '操作类别( 0、用户端 1、平台管理端)', `oper_name` varchar(50) DEFAULT '' COMMENT '操作人员', `oper_url` varchar(255) DEFAULT '' COMMENT '请求URL', `oper_ip` varchar(128) DEFAULT '' COMMENT '主机地址', `oper_location` varchar(255) DEFAULT '' COMMENT '操作地点', `oper_param` varchar(2000) DEFAULT '' COMMENT '请求参数', `JSON_result` varchar(2000) DEFAULT '' COMMENT '返回参数', `status` int(11) DEFAULT '0' COMMENT '操作状态(1正常 0异常)', `error_msg` varchar(2000) DEFAULT '' COMMENT '错误消息', `oper_time` datetime DEFAULT NULL COMMENT '操作时间', PRIMARY KEY (`oper_id`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='操作日志记录';
2、依赖(aop依赖,至于其他依赖(Druid,mybatisPlus)自行处理)
org.springframework.boot spring-boot-starter-aop
3、自定义注解(具体如何自定义注解,请自行学习,这里不做详细说明)
import com.xiarg.genius.annotation.entry.BusinessTypeEnum;import java.lang.annotation.*;@Target({ElementType.METHOD,ElementType.PARAMETER})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Log { public String title() default ""; public BusinessTypeEnum businessType() default BusinessTypeEnum.OTHER;}
4、切面
import com.alibaba.fastjson2.JSON;import com.xiarg.genius.annotation.annotation.Log;import com.xiarg.genius.annotation.entry.SysLog;import com.xiarg.genius.annotation.service.ISysLogService;import lombok.Data;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import org.springframework.validation.BindingResult;import org.springframework.WEB.bind.annotation.RequestMethod;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import org.springframework.web.multipart.MultipartFile;import org.springframework.web.servlet.HandlerMapping;import javax.servlet.Http.httpservletRequest;import javax.servlet.http.HttpServletResponse;import java.time.LocalDateTime;import java.util.Collection;import java.util.Map;@Data@Aspect@Componentpublic class LoGConfig { private static final Logger log = LoggerFactory.getLogger(LogConfig.class); private final ISysLogService sysLogService; @Pointcut("@annotation(com.xiarg.genius.annotation.annotation.Log)") public void logPointCut() {} @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult){ handleLog(joinPoint, controllerLog, null, jsonResult); } @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e") public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e){ handleLog(joinPoint, controllerLog, e, null); } protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult){ try { MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); // 获取当前的用户 String userName = "genius"; // *========数据库日志=========*// SysLog sysLog = new SysLog(); sysLog.setStatus(1); // 请求的地址 ip和localtion是前端获取到传过来的 ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); assert requestAttributes != null; HttpServletRequest request = requestAttributes.getRequest(); Map parameterMap = request.getParameterMap(); String ip = getIpAddr(request); sysLog.setOperIp(ip); sysLog.setOperLocation(request.getHeader("location")); sysLog.setOperParam(JSON.toJSONString(parameterMap)); sysLog.setOperUrl(request.getRequestURI()); sysLog.setOperName(userName); if (e != null) { sysLog.setStatus(0); int length = e.getMessage().length(); sysLog.setErrorMsg(e.getMessage().substring(0,length>2000?2000:length)); } // 设置方法名称 String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); sysLog.setMethod(className + "." + methodName + "()"); // 设置请求方式 sysLog.setRequestMethod(request.getMethod()); // 处理设置注解上的参数 getControllerMethodDescription(joinPoint, controllerLog, sysLog, jsonResult, request); // 保存数据库 sysLog.setOperTime(LocalDateTime.now()); // 返回数据 sysLog.setJsonResult(jsonResult==null?"":jsonResult.toString()); // 将处理好的日至对象存储进数据库 sysLogService.save(sysLog); } catch (Exception exp) { // 记录本地异常日志 log.error("==前置通知异常=="); log.error("异常信息:{}", exp.getMessage()); exp.printStackTrace(); } } public static String getIpAddr(HttpServletRequest request) { if (request == null) { return "unknown"; } String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("X-Forwarded-For"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("X-Real-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysLog sysLog, Object jsonResult, HttpServletRequest request) throws Exception { // 设置action动作 sysLog.setBusinessType(log.businessType().ordinal()); sysLog.setTitle(log.title()); } private void setRequestValue(JoinPoint joinPoint, SysLog sysLog, HttpServletRequest request) throws Exception { String requestMethod = sysLog.getRequestMethod(); if (RequestMethod.PUT.name().equals(requestMethod) || RequestMethod.POST.name().equals(requestMethod)) { String params = argsArrayToString(joinPoint.getArgs()); sysLog.setOperParam(params.substring(0,2000)); } else { Map, ?> paramsMap = (Map, ?>) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); sysLog.setOperParam(paramsMap.toString().substring(0,2000)); } } private String argsArrayToString(Object[] paramsArray) { StringBuilder params = new StringBuilder(); if (paramsArray != null && paramsArray.length > 0) { for (Object o : paramsArray) { if (o != null && !isFilterObject(o)) { try { Object jsonObj = JSON.toJSON(o); params.append(jsonObj.toString()).append(" "); } catch (Exception e) { log.error(e.getMessage()); } } } } return params.toString().trim(); } @SuppressWarnings("rawtypes") public boolean isFilterObject(final Object o) { Class> clazz = o.getClass(); if (clazz.isArray()) { return clazz.getComponentType().isAssignableFrom(MultipartFile.class); } else if (Collection.class.isAssignableFrom(clazz)) { Collection collection = (Collection) o; for (Object value : collection) { return value instanceof MultipartFile; } } else if (Map.class.isAssignableFrom(clazz)) { Map map = (Map) o; for (Object value : map.entrySet()) { Map.Entry entry = (Map.Entry) value; return entry.getValue() instanceof MultipartFile; } } return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse || o instanceof BindingResult; }}
5、枚举和实体类
public enum BusinessTypeEnum { OTHER, INSERT, UPDATE, DELETE, GRANT,}
import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.TableId;import lombok.Data;import java.time.LocalDateTime;@Datapublic class SysLog { @TableId(value = "oper_id", type = IdType.AUTO) private Long operId; private String title; private Integer businessType; private String method; private String requestMethod; private String operName; private String operUrl; private String operIp; private String operLocation; private String operParam; private String jsonResult; private Integer status; private String errorMsg; private LocalDateTime operTime;}
6、具体的控制层应用
import com.xiarg.genius.annotation.annotation.Log;import com.xiarg.genius.annotation.entry.BusinessTypeEnum;import org.springframework.web.bind.annotation.*;@RestController@RequestMapping("test")public class TestController { @Log(title = "查询列表",businessType = BusinessTypeEnum.OTHER) @GetMapping() public String list(@RequestParam("id") String id) { return "返回数据列表"; } @Log(title = "添加数据",businessType = BusinessTypeEnum.INSERT) @PostMapping public String save() { try { System.out.println(1/0); } catch (Exception e) { throw e; } return "数据添加成功"; } @Log(title = "修改数据",businessType = BusinessTypeEnum.UPDATE) @PutMapping public String update() { return "修改数据成功"; } @Log(title = "删除数据",businessType = BusinessTypeEnum.DELETE) @DeleteMapping public String delete() { return "删除数据成功"; }}
7、综上即实现功能,但是注意:ip和localtion是前端获取到传过来的,要不然无法获取到。
来源地址:https://blog.csdn.net/m0_65014849/article/details/129818219
--结束END--
本文标题: Java自定义注解@Log和AOP实现用户操作日志
本文链接: https://www.lsjlt.com/news/422937.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-05-10
2024-05-10
2024-05-10
2024-05-10
2024-05-10
2024-05-10
2024-05-10
2024-05-10
2024-05-10
2024-05-10
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0