最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot中使用AOP實(shí)現(xiàn)日志記錄功能

 更新時間:2024年05月19日 09:33:08   作者:哈__  
AOP的全稱是Aspect-Oriented Programming,即面向切面編程(也稱面向方面編程),它是面向?qū)ο缶幊蹋∣OP)的一種補(bǔ)充,目前已成為一種比較成熟的編程方式,本文給大家介紹了SpringBoot中使用AOP實(shí)現(xiàn)日志記錄功能,需要的朋友可以參考下

AOP簡介

AOP的全稱是Aspect-Oriented Programming,即面向切面編程(也稱面向方面編程)。它是面向?qū)ο缶幊蹋∣OP)的一種補(bǔ)充,目前已成為一種比較成熟的編程方式。

在傳統(tǒng)的業(yè)務(wù)處理代碼中,通常都會進(jìn)行事務(wù)處理、日志記錄等操作。雖然使用OOP可以通過組合或者繼承的方式來達(dá)到代碼的重用,但如果要實(shí)現(xiàn)某個功能(如日志記錄),同樣的代碼仍然會分散到各個方法中。這樣,如果想要關(guān)閉某個功能,或者對其進(jìn)行修改,就必須要修改所有的相關(guān)方法。這不但增加了開發(fā)人員的工作量,而且提高了代碼的出錯率。

為了解決這一問題,AOP思想隨之產(chǎn)生。AOP采取橫向抽取機(jī)制,將分散在各個方法中的重復(fù)代碼提取出來,然后在程序編譯或運(yùn)行時,再將這些提取出來的代碼應(yīng)用到需要執(zhí)行的地方。這種采用橫向抽取機(jī)制的方式,采用傳統(tǒng)的OOP思想顯然是無法辦到的,因?yàn)镺OP只能實(shí)現(xiàn)父子關(guān)系的縱向的重用。雖然AOP是一種新的編程思想,但卻不是OOP的替代品,它只是OOP的延伸和補(bǔ)充。

創(chuàng)建日志數(shù)據(jù)庫 

創(chuàng)建日志記錄表

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
 
-- ----------------------------
-- Table structure for sys_oper_log
-- ----------------------------
DROP TABLE IF EXISTS `sys_oper_log`;
CREATE TABLE `sys_oper_log`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志主鍵',
  `operation` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '操作',
  `business_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '0' COMMENT '業(yè)務(wù)類型',
  `method` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '方法名稱',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '操作時間',
  `oper_name` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '操作用戶',
  `params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '參數(shù)',
  `ip` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '請求的ip地址',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2058 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '操作日志記錄' ROW_FORMAT = Dynamic;
 
SET FOREIGN_KEY_CHECKS = 1;

創(chuàng)建用戶表 

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
 
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
  `name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名 ',
  `age` int(11) NULL DEFAULT NULL COMMENT '年齡 ',
  `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '郵箱 ',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
 
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (2, 'Jack', 20, 'test2@baomidou.com');
INSERT INTO `user` VALUES (3, 'Tom', 28, 'test3@baomidou.com');
INSERT INTO `user` VALUES (4, 'Sandy', 21, 'test4@baomidou.com');
INSERT INTO `user` VALUES (5, 'Billie', 24, 'test5@baomidou.com');
INSERT INTO `user` VALUES (6, 'sss', 18, '123@qq.com');
INSERT INTO `user` VALUES (8, 'sss', 18, '123@qq.com');
 
SET FOREIGN_KEY_CHECKS = 1;

簡單看一下表格的結(jié)構(gòu),我這里的數(shù)據(jù)就不給大家展示了。

SpringBoot使用AOP

一、導(dǎo)入依賴

下邊的三個依賴是我們的核心依賴。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
         <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

二、創(chuàng)建我們的項(xiàng)目結(jié)構(gòu)

  • 創(chuàng)建UserMapper
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
  • 創(chuàng)建UserService
public interface UserService extends IService<User> {
}
  • 創(chuàng)建UserServiceImpl
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
  • 創(chuàng)建UserController
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Log(operation = "查找用戶",businessType = BusinessType.LIST)
    @RequestMapping("/find-user")
    public String findUser(){
        return userService.list().toString();
    }
}

創(chuàng)建兩個實(shí)體

  • 創(chuàng)建User
@Data
public class User {
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    private String name;
    private Integer age;
    private String email;
    
}
  • 創(chuàng)建SysOperLog
@Data
@TableName("sys_oper_log")
public class SysOperLog {
 
        @TableId(type = IdType.AUTO)
        private Long id;
 
        private String operation;
 
        private String businessType;
 
        private String method;
 
        @TableField(fill = FieldFill.INSERT)
        private LocalDateTime createTime;
 
        private String operName;
 
        private String params;
 
        private String ip;
}

三、使用AOP

1.創(chuàng)建枚舉類

這個枚舉類的作用就是記錄我們調(diào)用的接口是什么樣的一個類型的,是查找、刪除還是其他。

public enum BusinessType {
    /**
     * 其它
     */
    OTHER,
 
    /**
     * 新增
     */
    INSERT,
 
    /**
     * 修改
     */
    UPDATE,
 
    /**
     * 刪除
     */
    DELETE,
    
    /**
     * 瀏覽
     */
    LIST
}

2..創(chuàng)建Log注解

默認(rèn)的操作為空,默認(rèn)的操作類型是OTHER。

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
    /**
     * 操作名稱
     * @return
     */
    String operation() default "";
 
    /**
     * 操作的類型
     * @return
     */
    BusinessType businessType() default BusinessType.OTHER;
}

3.創(chuàng)建切面類

@Aspect
@Component
public class LogAspect {
    @Pointcut("@annotation(com.qcby.annotation.Log)")
    public void pointCut(){}
 
    @Autowired
    HttpServletRequest request;
    @Autowired
    SysOperLogMapper sysOperLogMapper;
 
    @After(value = "pointCut()")
    public void afterLogWrite(JoinPoint joinPoint){
        // 創(chuàng)建日志對象
        SysOperLog sysOperLog = new SysOperLog();
        // 獲取我們調(diào)用的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
 
        // 獲取方法上的Log注解,因?yàn)槲覀円@取注解中的一些信息
        Log log = method.getAnnotation(Log.class);
 
        // 獲取我們調(diào)用的類的名稱
        String className = joinPoint.getTarget().getClass().getName();
        // 獲取調(diào)用的方法的名稱
        String methodName = method.getName();
        // 重新修改一下我們調(diào)用的方法 是全路徑的
        methodName = className + methodName;
 
        // 獲取方法的參數(shù)
        Object[] args = joinPoint.getArgs();
        ObjectMapper objectMapper = new ObjectMapper();
        String params = "";
        try {
            params =  objectMapper.writeValueAsString(args);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
 
        // 獲取注解中的操作名稱
        String operation = log.operation();
        // 獲取注解中的操作類型
        String businessType = log.businessType().toString();
 
        // 這里的操作人員僅靠后端是寫不了的  需要前端的token認(rèn)證  我直接把操作人員改為admin
        String username = "admin";
 
        // 獲取ip地址
        String ipAddress = IpUtil.getIpAddr(request);
 
        sysOperLog.setBusinessType(businessType);
        sysOperLog.setOperation(operation);
        sysOperLog.setMethod(methodName);
        sysOperLog.setParams(params);
        sysOperLog.setIp(ipAddress);
        sysOperLog.setOperName(username);
        sysOperLog.setCreateTime(LocalDateTime.now());
        
        sysOperLogMapper.insert(sysOperLog);
        
    }
}

4.IpUtil

public class IpUtil {
    private static final String UNKNOWN = "unknown";
    private static final String LOCALHOST = "127.0.0.1";
    private static final String SEPARATOR = ",";
 
    public static String getIpAddr(HttpServletRequest request) {
        System.out.println(request);
        String ipAddress;
        try {
            ipAddress = request.getHeader("x-forwarded-for");
            if (ipAddress == null || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (LOCALHOST.equals(ipAddress)) {
                    InetAddress inet = null;
                    try {
                        inet = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                    ipAddress = inet.getHostAddress();
                }
            }
            // 對于通過多個代理的情況,第一個IP為客戶端真實(shí)IP,多個IP按照','分割
            // "***.***.***.***".length()
            if (ipAddress != null && ipAddress.length() > 15) {
                if (ipAddress.indexOf(SEPARATOR) > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            ipAddress = "";
        }
        return ipAddress;
    }
}

5.進(jìn)行測試

我們在瀏覽器上輸入網(wǎng)址:

127.0.0.1:8080/user/find-user

數(shù)據(jù)是沒問題的,接下來我們只需要查看數(shù)據(jù)的日志文件是否插入了日志就好了。 

這里我查找了兩次,一次使用的localhost,另一次使用的127.0.0.1。日志可以成功記錄。 

以上就是SpringBoot中使用AOP實(shí)現(xiàn)日志記錄功能的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot AOP日志記錄的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Spring創(chuàng)建Bean的八種主要方式詳解

    Spring創(chuàng)建Bean的八種主要方式詳解

    Spring(尤其是 Spring Boot)提供了多種方式來讓容器創(chuàng)建和管理 Bean,@Component、@Configuration + @Bean、@EnableConfigurationProperties 都是常見方式,下面我為你系統(tǒng)地梳理 Spring 創(chuàng)建 Bean 的所有主要方式,并說明它們的使用場景和區(qū)別,需要的朋友可以參考下
    2025-08-08
  • 如何解決通過spring-boot-maven-plugin package失敗問題

    如何解決通過spring-boot-maven-plugin package失敗問題

    這篇文章主要介紹了如何解決通過spring-boot-maven-plugin package失敗問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • MyBatis?Generator快速生成實(shí)體類和映射文件的方法

    MyBatis?Generator快速生成實(shí)體類和映射文件的方法

    這篇文章主要介紹了MyBatis?Generator快速生成實(shí)體類和映射文件的方法,通過示例代碼介紹了MyBatis?Generator?的使用,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • 簡單易懂講解happens-before原則

    簡單易懂講解happens-before原則

    Java內(nèi)存模型中的happens-before是什么?為什么會有這東西的存在?一個新東西肯定是上手先,但是等我們空下來回過頭來,我們還是需要去理解這些知識,只有這樣我才能深刻的記住,并且運(yùn)用熟練。下來和小編來一起學(xué)習(xí)下
    2019-05-05
  • Java 轉(zhuǎn)義字符全解析從基礎(chǔ)語法到安全編碼實(shí)踐(最新推薦)

    Java 轉(zhuǎn)義字符全解析從基礎(chǔ)語法到安全編碼實(shí)踐(最新推薦)

    本文詳細(xì)介紹了Java中的轉(zhuǎn)義字符,包括基礎(chǔ)轉(zhuǎn)義序列、Unicode轉(zhuǎn)義、Java 15的文本塊特性以及在正則表達(dá)式和安全編碼中的應(yīng)用,通過實(shí)例和最佳實(shí)踐,幫助開發(fā)者正確使用轉(zhuǎn)義字符,提高代碼的正確性和安全性,感興趣的朋友跟隨小編一起看看吧
    2025-10-10
  • Java 連接Access數(shù)據(jù)庫的兩種方式

    Java 連接Access數(shù)據(jù)庫的兩種方式

    這篇文章主要介紹了Java 連接Access數(shù)據(jù)庫的兩種方式,本文著重講解使用JDBC連接操作Access數(shù)據(jù)庫,需要的朋友可以參考下
    2015-06-06
  • 基于ThreadLocal 的用法及內(nèi)存泄露(內(nèi)存溢出)

    基于ThreadLocal 的用法及內(nèi)存泄露(內(nèi)存溢出)

    這篇文章主要介紹了基于ThreadLocal 的用法及內(nèi)存泄露(內(nèi)存溢出),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • springboot~ObjectMapper~dto到entity的自動賦值

    springboot~ObjectMapper~dto到entity的自動賦值

    這篇文章主要介紹了springboot~ObjectMapper~dto到entity的自動賦值,本文分三種情況給大家介紹,需要的朋友可以參考下
    2018-08-08
  • Java源碼解析ThreadLocal及使用場景

    Java源碼解析ThreadLocal及使用場景

    今天小編就為大家分享一篇關(guān)于Java源碼解析ThreadLocal及使用場景,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Java多種方式動態(tài)生成doc文檔

    Java多種方式動態(tài)生成doc文檔

    這篇文章主要為大家詳細(xì)介紹了Java動態(tài)生成doc文檔的多種方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09

最新評論

淮滨县| 行唐县| 揭阳市| 赤水市| 乃东县| 吉首市| 江永县| 金溪县| 肇东市| 卢湾区| 张家口市| 西畴县| 中江县| 汨罗市| 威远县| 安徽省| 河曲县| 当雄县| 秭归县| 根河市| 筠连县| 普陀区| 和硕县| 平利县| 崇仁县| 酒泉市| 宜黄县| 仲巴县| 绍兴县| 盐源县| 南皮县| 湖北省| 拜城县| 增城市| 永清县| 孝昌县| 边坝县| 长海县| 民县| 桐城市| 龙山县|