Spring AOP實(shí)現(xiàn)接口請(qǐng)求記錄到數(shù)據(jù)庫(kù)的示例代碼
1.引入AOP依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2.創(chuàng)建日志記錄表
DROP TABLE IF EXISTS `rule_operate_log`; CREATE TABLE `rule_operate_log` ( id INT(11) NOT NULL AUTO_INCREMENT COMMENT '日志id', path VARCHAR(4000) NULL DEFAULT NULL COMMENT '接口地址', http_method VARCHAR(32) NULL DEFAULT NULL COMMENT '請(qǐng)求方法', status_code VARCHAR(32) NULL DEFAULT NULL COMMENT '請(qǐng)求返回狀態(tài)碼', create_time_char VARCHAR(32) NULL DEFAULT NULL COMMENT '日志時(shí)間', create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '日志時(shí)間戳', ip varchar(200) NULL DEFAULT NULL COMMENT '請(qǐng)求ip', params mediumtext NULL COMMENT '請(qǐng)求參數(shù)', result mediumtext NULL COMMENT '返回值', exception mediumtext NULL COMMENT '接口異常', user_id VARCHAR(32) NULL DEFAULT NULL COMMENT '操作用戶', user_account VARCHAR(32) NULL DEFAULT NULL COMMENT '操作用戶賬號(hào)', user_name VARCHAR(200) NULL DEFAULT NULL COMMENT '操作用戶名稱', user_org_id VARCHAR(32) NULL DEFAULT NULL COMMENT '操作用戶機(jī)構(gòu)id', user_org_name VARCHAR(200) NULL DEFAULT NULL COMMENT '操作用戶機(jī)構(gòu)名稱', operate_name VARCHAR(200) NULL DEFAULT NULL COMMENT '操作名稱', operate_position VARCHAR(200) NULL DEFAULT NULL COMMENT '操作位置', log_type VARCHAR(32) NULL DEFAULT NULL COMMENT '日志類(lèi)型 error:錯(cuò)誤日志 operate:操作日志', category_id VARCHAR(32) NULL DEFAULT NULL COMMENT '分類(lèi)機(jī)構(gòu)id', cost INT(11) NULL DEFAULT NULL COMMENT '接口耗時(shí)', PRIMARY KEY (id) ) COMMENT = '操作日志表';
3.日志實(shí)體類(lèi)
import java.util.Date; public class RuleOperateLog { /** * id */ private Integer id; /** * 接口地址 */ private String path; /** * 請(qǐng)求方法 */ private String httpMethod; /** * 請(qǐng)求返回狀態(tài)碼 */ private String statusCode; /** * 日志時(shí)間 */ private String createTimeChar; /** * 日志時(shí)間戳 */ private Date createTime; /** * 請(qǐng)求ip */ private String ip; /** * 請(qǐng)求參數(shù) */ private String params; /** * 返回值 */ private String result; /** * 接口異常 */ private String exception; /** * 操作用戶 */ private String userId; /** * 操作用戶賬號(hào) */ private String userAccount; /** * 操作用戶名稱 */ private String userName; /** * 操作用戶機(jī)構(gòu) */ private String userOrgId; /** * 操作用戶機(jī)構(gòu)名稱 */ private String userOrgName; /** * 操作名稱 */ private String operateName; /** * 操作位置 */ private String operatePosition; /** * 日志類(lèi)型 */ private String logType; /** * 分類(lèi)機(jī)構(gòu)id */ private String categoryId; /** * 請(qǐng)求耗時(shí) */ private Integer cost; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getHttpMethod() { return httpMethod; } public void setHttpMethod(String httpMethod) { this.httpMethod = httpMethod; } public String getStatusCode() { return statusCode; } public void setStatusCode(String statusCode) { this.statusCode = statusCode; } public String getCreateTimeChar() { return createTimeChar; } public void setCreateTimeChar(String createTimeChar) { this.createTimeChar = createTimeChar; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getParams() { return params; } public void setParams(String params) { this.params = params; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } public String getException() { return exception; } public void setException(String exception) { this.exception = exception; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getUserAccount() { return userAccount; } public void setUserAccount(String userAccount) { this.userAccount = userAccount; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserOrgId() { return userOrgId; } public void setUserOrgId(String userOrgId) { this.userOrgId = userOrgId; } public String getUserOrgName() { return userOrgName; } public void setUserOrgName(String userOrgName) { this.userOrgName = userOrgName; } public String getOperateName() { return operateName; } public void setOperateName(String operateName) { this.operateName = operateName; } public String getOperatePosition() { return operatePosition; } public void setOperatePosition(String operatePosition) { this.operatePosition = operatePosition; } public String getLogType() { return logType; } public void setLogType(String logType) { this.logType = logType; } public String getCategoryId() { return categoryId; } public void setCategoryId(String categoryId) { this.categoryId = categoryId; } public Integer getCost() { return cost; } public void setCost(Integer cost) { this.cost = cost; } }
4.Dao+Mapper+service
import com.xxx.xxx.xxx.entity.RuleOperateLog; /** * 操作日志(RuleOperateLog)表數(shù)據(jù)庫(kù)訪問(wèn)層 * * @author hx * @since 2022-08-23 */ public interface RuleOperateLogDao { /** * 新增數(shù)據(jù) * * @param operateLog * @return */ int insert(RuleOperateLog operateLog); }
<?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.xxx.xxx.xxx.dao.RuleOperateLogDao"> <resultMap type="com.xxx.xxx.xxx.entity.RuleOperateLog" id="RuleOperateLogMap"> <result property="id" column="id" jdbcType="INTEGER"/> <result property="path" column="path" jdbcType="VARCHAR"/> <result property="httpMethod" column="http_method" jdbcType="VARCHAR"/> <result property="statusCode" column="status_code" jdbcType="VARCHAR"/> <result property="createTimeChar" column="create_time_char" jdbcType="VARCHAR"/> <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> <result property="ip" column="ip" jdbcType="VARCHAR"/> <result property="params" column="params" jdbcType="VARCHAR"/> <result property="result" column="result" jdbcType="VARCHAR"/> <result property="exception" column="exception" jdbcType="VARCHAR"/> <result property="userId" column="user_id" jdbcType="VARCHAR"/> <result property="userAccount" column="user_account" jdbcType="VARCHAR"/> <result property="userName" column="user_name" jdbcType="VARCHAR"/> <result property="userOrgId" column="user_org_id" jdbcType="VARCHAR"/> <result property="userOrgName" column="user_org_name" jdbcType="VARCHAR"/> <result property="operateName" column="operate_name" jdbcType="VARCHAR"/> <result property="operatePosition" column="operate_position" jdbcType="VARCHAR"/> <result property="logType" column="log_type" jdbcType="VARCHAR"/> <result property="categoryId" column="category_id" jdbcType="VARCHAR"/> <result property="cost" column="cost" jdbcType="INTEGER"/> </resultMap> <insert id="insert" keyProperty="id" useGeneratedKeys="true"> insert into rule_operate_log (id, path, http_method, status_code, create_time_char, create_time, ip, params, result, exception, user_id, user_account, user_name, user_org_id, user_org_name, operate_name, operate_position, log_type, category_id, cost) values (#{id}, #{path}, #{httpMethod}, #{statusCode}, #{createTimeChar}, #{createTime}, #{ip}, #{params}, #{result}, #{exception},#{userId}, #{userAccount}, #{userName}, #{userOrgId}, #{userOrgName}, #{operateName}, #{operatePosition}, #{logType}, #{categoryId}, #{cost}) </insert> </mapper>
import com.xxx.xxx.xxx.entity.RuleOperateLog; /** * 操作日志(RuleOperateLog)表服務(wù)接口 * * @author hx * @since 2022-08-23 */ public interface RuleOperateLogService { /** * 保存日志 * * @param ruleOperateLog * @return */ void saveLog(RuleOperateLog ruleOperateLog); }
import com.xxx.xxx.xxx.dao.RuleOperateLogDao; import com.xxx.xxx.xxx.entity.RuleOperateLog; import com.xxx.xxx.xxx.service.RuleOperateLogService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * 操作日志(RuleOperateLog)表服務(wù)實(shí)現(xiàn)類(lèi) * * @author hx * @since 2022-08-23 */ @Service("RuleOperateLogService") public class RuleOperateLogServiceImpl implements RuleOperateLogService { @Autowired private RuleOperateLogDao operateLogDao; @Override public void saveLog(RuleOperateLog ruleOperateLog) { operateLogDao.insert(ruleOperateLog); } }
5.自定義注解
import java.lang.annotation.*; @Target({ ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface LogResource { /** * 服務(wù)名稱 * @return */ String name(); /** * 操作位置描述 * @return */ String position() default ""; /** * 日志類(lèi)型 * @return */ String logType() default ""; }
6.操作日志切面類(lèi)
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; import com.com.xxx.xxx.xxx.annotation.LogResource; import com.com.xxx.xxx.xxx.constants.LogTypeConstants; import com.com.xxx.xxx.xxx.entity.RuleOperateLog; import com.com.xxx.xxx.xxx.service.RuleOperateLogService; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Date; /** * 操作日志切面類(lèi) * * @author hx * @since 2022-08-23 */ @Aspect @Component public class OperateLogAspect { @Autowired private RuleOperateLogService operateLogService; //掃描使用@LogResource注解的方法 @Pointcut("@annotation(com.com.xxx.xxx.xxx.annotation.LogResource)") public void logPointCut() { }; @Around("logPointCut()") public Object around(ProceedingJoinPoint point) throws Throwable { Date startTime = new Date(); String exception = null; String result = null; try { Object obj = point.proceed(); if (obj != null) { result = JSONObject.toJSONString(obj); } return obj; } catch (Exception e) { //請(qǐng)求時(shí)報(bào)錯(cuò) exception = e.toString(); throw e; } finally { //操作和報(bào)錯(cuò)日志都記錄 HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); int statusCode = response.getStatus(); if (exception != null) { /** CHECKSTYLE:OFF:MagicNumber */ statusCode = 500; /** CHECKSTYLE:ON:MagicNumber */ } syncSaveLog(point, startTime, new Date(), exception, result, statusCode); } } @Async void syncSaveLog(ProceedingJoinPoint joinPoint, Date startTime, Date endTime, String exception, String result, int statusCode) { RuleOperateLog log = new RuleOperateLog(); try { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); LogResource annotation = method.getAnnotation(LogResource.class); if (annotation != null) { //注解上的描述 log.setOperateName(annotation.name()); } Date nowDate = new Date(); log.setCreateTimeChar(new SimpleDateFormat("yyyyMMddhhmmss").format(nowDate)); log.setCreateTime(nowDate); //入?yún)? if (joinPoint.getArgs() != null) { try { log.setParams(JSONObject.toJSONString(joinPoint.getArgs(), SerializerFeature.IgnoreNonFieldGetter)); } catch (Exception e) { e.printStackTrace(); } } Long cost = endTime.getTime() - startTime.getTime(); log.setCost(cost.intValue()); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); if (request != null) { log.setUserName(request.getHeader(HttpHeaders.USER_AGENT)); log.setPath(request.getRequestURI()); log.setHttpMethod(request.getMethod()); log.setIp(request.getRemoteAddr()); } log.setStatusCode(String.valueOf(statusCode)); log.setResult(result); /** CHECKSTYLE:OFF:MagicNumber */ if (statusCode > 400 && exception != null) { log.setException(exception); log.setLogType(LogTypeConstants.ERROR); } else { log.setLogType(LogTypeConstants.OPERATE); } /** CHECKSTYLE:ON:MagicNumber */ operateLogService.saveLog(log); } catch (Exception e) { e.printStackTrace(); } /* //啟動(dòng)一個(gè)線程,執(zhí)行報(bào)錯(cuò)日志防止影響主請(qǐng)求 new Thread() { @Override public void run() { try { //保存到數(shù)據(jù)庫(kù) operLogMapper.insertOper(operLog); } catch (Exception e) { e.printStackTrace(); } } }.start();*/ } }
7.使用
到此這篇關(guān)于Spring AOP實(shí)現(xiàn)接口請(qǐng)求記錄到數(shù)據(jù)庫(kù)的文章就介紹到這了,更多相關(guān)Spring AOP接口請(qǐng)求記錄數(shù)據(jù)庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot結(jié)合mybatis-plus基于session模擬短信注冊(cè)功能
本文主要介紹了springboot結(jié)合mybatis-plus基于session模擬短信注冊(cè)功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-11-11Java使用jxl包寫(xiě)Excel文件適合列寬實(shí)現(xiàn)
用jxl.jar包,讀寫(xiě)過(guò)Excel文件。也沒(méi)有注意最適合列寬的問(wèn)題,但是jxl.jar沒(méi)有提供最適合列寬的功能,上次用到寫(xiě)了一下,可以基本實(shí)現(xiàn)最適合列寬。2013-11-11SpringBoot通過(guò)ip獲取歸屬地的幾種方式分享
在日常我們逛網(wǎng)站的時(shí)候會(huì)發(fā)現(xiàn)我們登錄后會(huì)出現(xiàn)歸屬地信息,例如:我在廣州登錄會(huì)顯示廣東廣州,有些更加精確的會(huì)顯示到區(qū)縣,那么我們來(lái)看看有哪些方式來(lái)獲取歸屬地信息,今天我們來(lái)聊一聊2023-09-09解決在Idea 2020.2下使用 Lombok的注解不生效的問(wèn)題(插件安裝了,依賴也寫(xiě)了,自動(dòng)注解也設(shè)置了)
這篇文章主要介紹了在Idea 2020.2下使用 Lombok的注解不生效的問(wèn)題(插件安裝了,依賴也寫(xiě)了,自動(dòng)注解也設(shè)置了),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08Java實(shí)現(xiàn)簡(jiǎn)單的學(xué)生教師管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單的學(xué)生教師管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02Java通用BouncyCastle實(shí)現(xiàn)的DES3加密的方法
這篇文章主要介紹了Java通用BouncyCastle實(shí)現(xiàn)的DES3加密的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12