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

SpringBoot使用log4j2將日志記錄到文件及自定義數(shù)據(jù)庫的配置方法

 更新時(shí)間:2024年03月16日 10:51:35   作者:你小子在看什么……  
這篇文章主要介紹了SpringBoot使用log4j2將日志記錄到文件及自定義數(shù)據(jù)庫的配置方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧

一、環(huán)境說明     

        Spring Boot2+MyBatis-Plus+Log4j2

二、進(jìn)行配置

1、pom.xml

        由于Spring Boot內(nèi)置的日志框架是logback,會(huì)導(dǎo)致和log4j2沖突,所以要先排除項(xiàng)目中l(wèi)ogback的依賴。同時(shí)引入log4j2。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions> <!-- 去掉springboot默認(rèn)配置 -->
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency> <!-- 引入log4j2依賴 -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

2、log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
    Configuration 標(biāo)簽用于配置 Log4j2,其中 status 屬性設(shè)置為 "WARN",表示僅記錄警告級別的日志用于運(yùn)行時(shí)狀態(tài)。
    monitorInterval 屬性設(shè)置為 "30",表示每隔 30 秒自動(dòng)檢查配置文件更改。
-->
<Configuration status="WARN" monitorInterval="30">
    <Properties>
        <!--
            定義名為 "baseDir" 的屬性,用于指定日志文件的基本目錄。其他地方可以使用 "${baseDir}" 引用這個(gè)值。
        -->
        <Property name="baseDir">./logs</Property>
        <!--
            定義名為 "logPattern" 的屬性,用于指定日志的格式,以便在后續(xù)配置中引用。
        -->
        <Property name="logPattern">
            %d{yyyy-MM-dd HH:mm:ss} %highlight{%6p} %style{%5pid}{bright,magenta} --- [%15.15t]
            %style{%-40.40logger{39}}{bright,cyan} : %m%n
        </Property>
        <!-- 文件輸出的格式 -->
        <Property name="fileLayout">
            %d{yyyy-MM-dd HH:mm:ss} %p --- [%t] %logger : %m%n"
        </Property>
        <!-- <Property name="logPattern">%highlight{%d{HH:mm:ss:SSS} [%-5p] - %l - %m%n}{FATAL=red, ERROR=red, WARN=yellow, INFO=default, DEBUG=default}</Property> -->
        <!--
            定義名為 "fileSize" 的屬性,用于指定日志文件的最大大小。其他地方可以使用 "${fileSize}" 引用這個(gè)值。
        -->
        <Property name="fileSize">10MB</Property>
    </Properties>
    <!-- OFF	0 -->
    <!-- FATAL	100 -->
    <!-- ERROR	200 -->
    <!-- WARN	300 -->
    <!-- INFO	400 -->
    <!-- DEBUG	500 -->
    <!-- TRACE	600 -->
    <!-- ALL	Integer.MAX_VALUE -->
    <CustomLevels>
        <CustomLevel name="CUSTOM_LOG" intLevel="90"/>
        <CustomLevel name="EXCEPTION_LOG" intLevel="91"/>
        <CustomLevel name="OPERATION_LOG" intLevel="92"/>
        <CustomLevel name="LOGIN_LOG" intLevel="93"/>
    </CustomLevels>
    <Appenders>
        <!-- Console Appender 用于將日志輸出到控制臺(tái)。-->
        <Console name="Console" target="SYSTEM_OUT">
            <!-- 只輸出 DEBUG 級別及以上的日志 -->
            <ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
            <!-- 使用定義的日志格式 -->
            <PatternLayout pattern="${logPattern}"/>
        </Console>
        <!-- DEBUG 級別的日志文件輸出 -->
        <RollingFile name="DebugAppender" fileName="${baseDir}/app_debug.log"
                     filePattern="${baseDir}/debug_%d{yyyy-MM-dd}_%i.log">
            <!-- 僅接受 DEBUG 級別的日志 -->
            <Filters>
                <ThresholdFilter level="DEBUG"/>
                <ThresholdFilter level="INFO" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <!-- 使用定義的日志格式 -->
            <PatternLayout pattern="${fileLayout}"/>
            <Policies>
                <!-- 每隔 1 天滾動(dòng)一次日志,"modulate" 表示即使沒有日志產(chǎn)生,也會(huì)在下一天創(chuàng)建新文件 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 當(dāng)日志文件大小達(dá)到指定大小時(shí)觸發(fā)滾動(dòng) -->
                <SizeBasedTriggeringPolicy size="${fileSize}"/>
            </Policies>
        </RollingFile>
        <!-- INFO 級別的日志文件輸出 -->
        <RollingFile name="InfoAppender" fileName="${baseDir}/app_info.log"
                     filePattern="${baseDir}/info_%d{yyyy-MM-dd}_%i.log">
            <Filters>
                <!-- 僅接受 INFO 級別的日志 -->
                <!-- onMatch="ACCEPT" onMismatch="DENY" -->
                <ThresholdFilter level="INFO"/>
                <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <!-- 使用定義的日志格式 -->
            <PatternLayout pattern="${fileLayout}"/>
            <Policies>
                <!-- 每隔 1 天滾動(dòng)一次日志,"modulate" 表示即使沒有日志產(chǎn)生,也會(huì)在下一天創(chuàng)建新文件 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 當(dāng)日志文件大小達(dá)到指定大小時(shí)觸發(fā)滾動(dòng) -->
                <SizeBasedTriggeringPolicy size="${fileSize}"/>
            </Policies>
        </RollingFile>
        <!--處理 WARN 級別的日志-->
        <RollingFile name="WarnAppender" fileName="${baseDir}/app_warn.log"
                     filePattern="${baseDir}/info_%d{yyyy-MM-dd}_%i.log">
            <Filters>
                <ThresholdFilter level="WARN"/>
                <ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <!-- 使用定義的日志格式 -->
            <PatternLayout pattern="${fileLayout}"/>
            <Policies>
                <!-- 每隔 1 天滾動(dòng)一次日志,"modulate" 表示即使沒有日志產(chǎn)生,也會(huì)在下一天創(chuàng)建新文件 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 當(dāng)日志文件大小達(dá)到指定大小時(shí)觸發(fā)滾動(dòng) -->
                <SizeBasedTriggeringPolicy size="${fileSize}"/>
            </Policies>
        </RollingFile>
        <!-- ERROR 級別的日志文件輸出 -->
        <RollingFile name="ErrorAppender" fileName="${baseDir}/app_error.log"
                     filePattern="${baseDir}/error_%d{yyyy-MM-dd}_%i.log">
            <!-- 僅接受 ERROR 級別的日志 -->
            <Filters>
                <ThresholdFilter level="ERROR"/>
                <ThresholdFilter level="FATAL" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <!-- 使用定義的日志格式 -->
            <PatternLayout pattern="${fileLayout}"/>
            <Policies>
                <!-- 每隔 1 天滾動(dòng)一次日志,"modulate" 表示即使沒有日志產(chǎn)生,也會(huì)在下一天創(chuàng)建新文件 -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 當(dāng)日志文件大小達(dá)到指定大小時(shí)觸發(fā)滾動(dòng) -->
                <SizeBasedTriggeringPolicy size="${fileSize}"/>
            </Policies>
        </RollingFile>
        <!-- 配置 HikariSqlFile Appender,將 SQL 日志輸出到文件的日志記錄追加器 -->
        <!-- <RollingFile name="HikariSqlAppender" fileName="${baseDir}/app_sql.log" -->
        <!--              filePattern="${baseDir}/app_sql_%d{yyyy-MM-dd}_%i.log"> -->
        <!--     &lt;!&ndash; 使用定義的日志格式 &ndash;&gt; -->
        <!--     <PatternLayout pattern="${fileLayout}"/> -->
        <!--     <Policies> -->
        <!--         &lt;!&ndash; 每隔 1 天滾動(dòng)一次日志,"modulate" 表示即使沒有日志產(chǎn)生,也會(huì)在下一天創(chuàng)建新文件 &ndash;&gt; -->
        <!--         <TimeBasedTriggeringPolicy interval="1" modulate="true"/> -->
        <!--         &lt;!&ndash; 當(dāng)日志文件大小達(dá)到指定大小時(shí)觸發(fā)滾動(dòng) &ndash;&gt; -->
        <!--         <SizeBasedTriggeringPolicy size="${fileSize}"/> -->
        <!--     </Policies> -->
        <!-- </RollingFile> -->
        <!-- 配置JDBC Appender -->
        <!-- 登錄日志表 -->
        <JDBC name="LoginDatabase" tableName="sys_log_login">
            <ConnectionFactory class="com.cj.blog.common.logs.ConnectionFactory" method="getDatabaseConnection"/>
            <Filters>
                <ThresholdFilter level="LOGIN_LOG"/>
                <ThresholdFilter level="OPERATION_LOG" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <Column name="user_id" pattern="%X{user_id}"/>
            <Column name="user_name" pattern="%X{user_name}"/>
            <Column name="client_ip" pattern="%X{client_ip}"/>
            <Column name="device_info" pattern="%X{device_info}"/>
            <Column name="remarks" pattern="%X{remarks}"/>
            <Column name="login_time" pattern="%d{yyyy-MM-dd HH:mm:ss}"/>
        </JDBC>
        <!-- 操作日志表 -->
        <JDBC name="OperationDatabase" tableName="sys_log_operation">
            <ConnectionFactory class="com.cj.blog.common.logs.ConnectionFactory" method="getDatabaseConnection"/>
            <Filters>
                <ThresholdFilter level="OPERATION_LOG"/>
                <ThresholdFilter level="EXCEPTION_LOG" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <Column name="user_id" pattern="%X{user_id}"/>
            <Column name="user_name" pattern="%X{user_name}"/>
            <Column name="v_before" pattern="%X{v_before}"/>
            <Column name="v_after" pattern="%X{v_after}"/>
            <Column name="remarks" pattern="%X{remarks}"/>
            <Column name="operation_time" pattern="%d{yyyy-MM-dd HH:mm:ss}"/>
        </JDBC>
        <!-- 異常日志表 -->
        <JDBC name="ExceptionDatabase" tableName="sys_log_exception">
            <ConnectionFactory class="com.cj.blog.common.logs.ConnectionFactory" method="getDatabaseConnection"/>
            <Filters>
                <ThresholdFilter level="EXCEPTION_LOG"/>
                <ThresholdFilter level="CUSTOM_LOG" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
            <Column name="user_id" pattern="%X{user_id}"/>
            <Column name="user_name" pattern="%X{user_name}"/>
            <Column name="request_mode" pattern="%X{request_mode}"/>
            <Column name="absolute_uri" pattern="%X{absolute_uri}"/>
            <Column name="form_data" pattern="%X{form_data}"/>
            <Column name="source" pattern="%X{source}"/>
            <Column name="message" pattern="%X{message}"/>
            <!-- <Column name="stack_trace" pattern="%X{stack_trace}"/> -->
            <Column name="exception_time" pattern="%d{yyyy-MM-dd HH:mm:ss}"/>
        </JDBC>
    </Appenders>
    <Loggers>
        <Root level="DEBUG">
            <!-- 控制臺(tái) -->
            <AppenderRef ref="Console" level="INFO"/>
            <!-- 文件 -->
            <AppenderRef ref="ErrorAppender" level="ERROR"/>
            <AppenderRef ref="WarnAppender" level="WARN"/>
            <AppenderRef ref="InfoAppender" level="INFO"/>
            <AppenderRef ref="DebugAppender" level="DEBUG"/>
            <!-- 數(shù)據(jù)庫源 -->
            <AppenderRef ref="LoginDatabase" level="LOGIN_LOG"/>
            <AppenderRef ref="OperationDatabase" level="OPERATION_LOG"/>
            <AppenderRef ref="ExceptionDatabase" level="EXCEPTION_LOG"/>
        </Root>
        <!-- <Logger name="com.cj.config.logs.ConnectionFactory" level="INFO"> -->
        <!--     <AppenderRef ref="DatabaseAppender" level="INFO"/> -->
        <!-- </Logger> -->
        <!-- <Root level="TRACE"> -->
        <!--     &lt;!&ndash; 引用控制臺(tái)輸出和文件輸出的 appender &ndash;&gt; -->
        <!--     <AppenderRef ref="Console"/> -->
        <!--     <AppenderRef ref="DebugAppender"/> -->
        <!--     <AppenderRef ref="InfoAppender"/> -->
        <!--     <AppenderRef ref="WarnAppender"/> -->
        <!--     <AppenderRef ref="ErrorAppender"/> -->
        <!--     <AppenderRef ref="LoginDatabase"/> -->
        <!--     <AppenderRef ref="OperationDatabase" /> -->
        <!--     &lt;!&ndash; <AppenderRef ref="ExceptionDatabase" level="Exception"/> &ndash;&gt; -->
        <!-- </Root> -->
        <Logger name="org.apache.logging.log4j" level="DEBUG" additivity="false">
            <AppenderRef ref="Console"/>
        </Logger>
        <!--額外配置的logger-->
        <!--log4j2 自帶過濾日志-->
        <!-- Apache Tomcat Web服務(wù)器配置加載的日志 -->
        <Logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR">
            <!-- 僅記錄錯(cuò)誤級別的日志,通常用于記錄嚴(yán)重的配置錯(cuò)誤 -->
        </Logger>
        <!-- 與 Apache Tomcat 相關(guān)的組件生命周期信息 -->
        <Logger name="org.apache.catalina.util.LifecycleBase" level="ERROR">
            <!-- 僅記錄錯(cuò)誤級別的信息 -->
        </Logger>
        <!-- Apache Tomcat HTTP 協(xié)議處理器的日志記錄 -->
        <Logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN">
            <!-- 記錄警告級別及更高級別的信息,通常用于記錄一般警告信息 -->
        </Logger>
        <!-- Apache SSHD(SSH Server)庫的日志記錄 -->
        <Logger name="org.apache.sshd.common.util.SecurityUtils" level="WARN">
            <!-- 記錄警告級別及更高級別的信息,通常用于記錄一般警告信息 -->
        </Logger>
        <!-- 與 Apache Tomcat 相關(guān)的 NIO 選擇器池的日志記錄 -->
        <Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN">
            <!-- 記錄警告級別及更高級別的信息 -->
        </Logger>
        <!-- 與 CRaSH(Common Reusable SHell)相關(guān)的庫和 SSH 支持的日志記錄 -->
        <Logger name="org.crsh.plugin" level="WARN">
            <!-- 記錄警告級別及更高級別的信息 -->
        </Logger>
        <Logger name="org.crsh.ssh" level="WARN">
            <!-- 記錄警告級別及更高級別的信息 -->
        </Logger>
        <!-- Eclipse Jetty Web服務(wù)器的組件生命周期的日志記錄 -->
        <Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="ERROR">
            <!-- 僅記錄錯(cuò)誤級別的信息 -->
        </Logger>
        <!-- Hibernate Validator相關(guān)日志 -->
        <Logger name="org.hibernate.validator.internal.util.Version" level="WARN">
            <!-- 記錄警告級別及更高級別的信息 -->
        </Logger>
        <!-- 與 Spring Boot Actuator 相關(guān)的日志記錄 -->
        <Logger name="org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration" level="WARN">
            <!-- 記錄警告級別及更高級別的信息 -->
        </Logger>
        <Logger name="org.springframework.boot.actuate.endpoint.jmx" level="WARN">
            <!-- 記錄警告級別及更高級別的信息 -->
        </Logger>
        <!-- Thymeleaf模板引擎的日志記錄 -->
        <Logger name="org.thymeleaf" level="WARN">
            <!-- 記錄警告級別及更高級別的信息 -->
        </Logger>
    </Loggers>
</Configuration>

3、CustomDataSourceProperties

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "spring.datasource")
@Scope("singleton")
public class CustomDataSourceProperties {
    public String url;
    public String username;
    public String password;
    public String driverClassName;
}

4、ConfigReader

import com.cj.blog.model.base.CustomDataSourceProperties;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.InputStream;
import java.util.Map;
/**
 * 用于從YAML文件中讀取配置屬性的實(shí)用工具類。
 */
public class ConfigReader {
    private static final Logger logger = LogManager.getLogger(ConfigReader.class);
    /**
     * 從YAML配置文件中獲取數(shù)據(jù)源屬性。
     *
     * @return CustomDataSourceProperties對象,包含數(shù)據(jù)源屬性,如果未找到屬性則返回null。
     */
    public static CustomDataSourceProperties getDataSourceProperties() {
        String defaultActive = "dev"; // 默認(rèn)活動(dòng)配置
        String defaultConfigFile = "/application.yml"; // 默認(rèn)配置文件名
        // 從默認(rèn)配置文件中獲取Spring屬性
        Map<String, Object> properties = getSpringProperties(defaultActive, defaultConfigFile);
        if (properties != null) {
            Map<String, Object> springProperties = (Map<String, Object>) properties.get("spring");
            if (springProperties != null) {
                Map<String, Object> datasourceProperties = (Map<String, Object>) springProperties.get("datasource");
                if (datasourceProperties != null) {
                    CustomDataSourceProperties dataSourceProperties = new CustomDataSourceProperties();
                    dataSourceProperties.setUrl((String) datasourceProperties.get("url"));
                    dataSourceProperties.setUsername((String) datasourceProperties.get("username"));
                    dataSourceProperties.setPassword((String) datasourceProperties.get("password"));
                    dataSourceProperties.setDriverClassName((String) datasourceProperties.get("driver-class-name"));
                    logger.info("獲取數(shù)據(jù)源屬性成功!");
                    logger.info("數(shù)據(jù)源屬性:" + dataSourceProperties);
                    return dataSourceProperties;
                }
            }
        }
        return null;
    }
    /**
     * 從指定的配置文件中獲取Spring屬性。
     *
     * @param active     要使用的活動(dòng)配置。
     * @param configFile 配置文件的路徑。
     * @return 包含Spring屬性的Map,如果未找到屬性則返回null。
     */
    private static Map<String, Object> getSpringProperties(String active, String configFile) {
        // 讀取配置文件
        Map<String, Object> data = readConfigFile(configFile);
        if (data != null) {
            Map<String, Object> springProperties = (Map<String, Object>) data.get("spring");
            if (springProperties != null) {
                Map<String, Object> applicationProperties = (Map<String, Object>) springProperties.get("profiles");
                if (applicationProperties != null) {
                    active = (String) applicationProperties.get("active");
                    System.out.println("spring.application.active: " + active);
                }
            }
        }
        logger.info("spring.application.active: " + active);
        // 讀取活動(dòng)配置的配置文件
        return readConfigFile("/application-" + active + ".yml");
    }
    /**
     * 讀取指定的YAML配置文件并將其解析為Map。
     *
     * @param fileName YAML文件的路徑。
     * @return 包含解析后的YAML數(shù)據(jù)的Map,如果未找到文件或無法解析則返回null。
     */
    private static Map<String, Object> readConfigFile(String fileName) {
        try {
            // 創(chuàng)建用于解析YAML文件的ObjectMapper對象
            ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
            // 使用類加載器加載YAML文件
            InputStream inputStream = ConfigReader.class.getResourceAsStream(fileName);
            // 讀取YAML文件并解析為Map對象
            return mapper.readValue(inputStream, new TypeReference<Map<String, Object>>() {
            });
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

5、ConnectionFactory 連接工廠類,用于管理數(shù)據(jù)庫連接

import com.cj.blog.common.utils.ConfigReader;
import com.cj.blog.model.base.CustomDataSourceProperties;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnection;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
 * 連接工廠類,用于管理數(shù)據(jù)庫連接。通過Apache Commons DBCP提供數(shù)據(jù)庫連接池功能。
 */
@Component
public class ConnectionFactory {
    // 數(shù)據(jù)源,用于獲取數(shù)據(jù)庫連接
    private final DataSource dataSource;
    /**
     * 構(gòu)造函數(shù),初始化數(shù)據(jù)庫連接池配置,并創(chuàng)建數(shù)據(jù)源。
     *
     * @param dataSourceProperties 數(shù)據(jù)源屬性對象,包含數(shù)據(jù)庫連接信息
     */
    public ConnectionFactory(CustomDataSourceProperties dataSourceProperties) {
        // 初始化數(shù)據(jù)庫連接池配置
        Properties properties = new Properties();
        properties.setProperty("user", dataSourceProperties.getUsername());
        properties.setProperty("password", dataSourceProperties.getPassword());
        // 創(chuàng)建基于DriverManager的連接工廠和連接池
        GenericObjectPool<PoolableConnection> pool = new GenericObjectPool<>();
        pool.setMaxActive(10); // 設(shè)置最大連接數(shù)
        pool.setMinIdle(2); // 設(shè)置最小空閑連接數(shù)
        DriverManagerConnectionFactory connectionFactory = new DriverManagerConnectionFactory(dataSourceProperties.getUrl(), properties);
        // 創(chuàng)建可池化的數(shù)據(jù)庫連接工廠
        new PoolableConnectionFactory(connectionFactory, pool, null, "SELECT 1", 3, false, false, Connection.TRANSACTION_READ_COMMITTED);
        // 創(chuàng)建數(shù)據(jù)源
        this.dataSource = new PoolingDataSource(pool);
    }
    /**
     * 獲取數(shù)據(jù)庫連接。
     *
     * @return 數(shù)據(jù)庫連接
     * @throws SQLException 如果獲取連接時(shí)發(fā)生錯(cuò)誤
     */
    public static Connection getDatabaseConnection() throws SQLException {
        return Singleton.INSTANCE.dataSource.getConnection();
    }
    /**
     * 單例類,確保只有一個(gè)連接工廠實(shí)例。
     */
    private static class Singleton {
        static ConnectionFactory INSTANCE;
        static {
            // TODO 這里需要修改,在創(chuàng)建數(shù)據(jù)庫連接工廠時(shí),需要從配置文件中讀取數(shù)據(jù)源屬性
            // 從配置文件中讀取數(shù)據(jù)源屬性,并創(chuàng)建連接工廠實(shí)例
            CustomDataSourceProperties dataSourceProperties = ConfigReader.getDataSourceProperties();
            dataSourceProperties.setDriverClassName(dataSourceProperties.getDriverClassName());
            dataSourceProperties.setUrl(dataSourceProperties.getUrl());
            dataSourceProperties.setUsername(dataSourceProperties.getUsername());
            dataSourceProperties.setPassword(dataSourceProperties.getPassword());
            INSTANCE = new ConnectionFactory(dataSourceProperties);
        }
    }
}

三、進(jìn)行簡單測試配置

1、LogUtils

import org.apache.logging.log4j.ThreadContext;
/**
 * 日志工具類
 */
public class LogUtils {
    /**
     * 清除登錄日志上下文信息,以便在日志記錄操作結(jié)束后不保留上下文。
     */
    public static void clearLogContext() {
        ThreadContext.clearMap();
    }
}

2、LoginUserInfoHelper

/**
 * 用于存儲(chǔ)和獲取用戶信息的線程局部存儲(chǔ)輔助類。
 */
public class LoginUserInfoHelper {
    // 使用 ThreadLocal 來存儲(chǔ)用戶ID和用戶名
    private static final ThreadLocal<Long> userId = new ThreadLocal<>();
    private static final ThreadLocal<String> userName = new ThreadLocal<>();
    /**
     * 獲取當(dāng)前線程的用戶ID。
     *
     * @return 用戶ID
     */
    public static Long getUserId() {
        return userId.get();
    }
    /**
     * 設(shè)置當(dāng)前線程的用戶ID。
     *
     * @param _userId 用戶ID
     */
    public static void setUserId(Long _userId) {
        userId.set(_userId);
    }
    /**
     * 從當(dāng)前線程中移除用戶ID。
     */
    public static void removeUserId() {
        userId.remove();
    }
    /**
     * 獲取當(dāng)前線程的用戶名。
     *
     * @return 用戶名
     */
    public static String getUsername() {
        return userName.get();
    }
    /**
     * 設(shè)置當(dāng)前線程的用戶名。
     *
     * @param _username 用戶名
     */
    public static void setUsername(String _username) {
        userName.set(_username);
    }
    /**
     * 從當(dāng)前線程中移除用戶名。
     */
    public static void removeUsername() {
        userName.remove();
    }
}

3、LoginLogUtils

import com.cj.blog.common.utils.RequestUtils;
import com.cj.blog.model.auth.LoginUserInfoHelper;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.Optional;
/**
 * 登錄日志工具類。
 */
public class LoginLogUtils {
    private static final Logger logger = LogManager.getLogger(LoginLogUtils.class);
    /**
     * 設(shè)置用戶登錄日志,根據(jù)HttpServletRequest設(shè)置日志上下文信息。
     *
     * @param request 請求對象,用于獲取遠(yuǎn)程地址和用戶代理信息。
     * @param remarks 登錄日志的備注信息。
     */
    public static void setLogLogin(HttpServletRequest request, String remarks) {
        // 使用 LoginUserInfoHelper 中的用戶信息設(shè)置登錄日志
        setLogLogin(
                LoginUserInfoHelper.getUserId().toString(),
                LoginUserInfoHelper.getUsername(),
                request.getRemoteAddr(),
                RequestUtils.getUserAgent(request),
                remarks
        );
    }
    /**
     * 設(shè)置用戶登錄日志,根據(jù)指定的客戶端IP、設(shè)備信息和備注信息。
     *
     * @param clientIp   客戶端IP地址。
     * @param deviceInfo 設(shè)備信息。
     * @param remarks    登錄日志的備注信息。
     */
    public static void setLogLogin(String clientIp, String deviceInfo, String remarks) {
        // 使用 LoginUserInfoHelper 中的用戶信息設(shè)置登錄日志
        setLogLogin(
                LoginUserInfoHelper.getUserId().toString(),
                LoginUserInfoHelper.getUsername(),
                clientIp,
                deviceInfo,
                remarks
        );
    }
    /**
     * 設(shè)置用戶登錄日志,包含用戶ID、用戶名、客戶端IP、設(shè)備信息和備注信息。
     *
     * @param userId     用戶ID。
     * @param userName   用戶名。
     * @param clientIp   客戶端IP地址。
     * @param deviceInfo 設(shè)備信息。
     * @param remarks    登錄日志的備注信息。
     */
    public static void setLogLogin(String userId, String userName, String clientIp, String deviceInfo, String remarks) {
        logLogin(userId, userName, clientIp, deviceInfo, remarks);
    }
    /**
     * 設(shè)置用戶登錄日志,包含用戶ID、用戶名、客戶端IP、設(shè)備信息和備注信息。
     *
     * @param userId     用戶ID。
     * @param userName   用戶名。
     * @param clientIp   客戶端IP地址。
     * @param deviceInfo 設(shè)備信息。
     * @param remarks    登錄日志的備注信息。
     */
    public static void logLogin(String userId, String userName, String clientIp, String deviceInfo, String remarks) {
        try {
            // 設(shè)置上下文信息,這些信息將與日志消息關(guān)聯(lián)
            ThreadContext.put("user_id", Objects.toString(userId, "0"));
            ThreadContext.put("user_name", Objects.toString(userName, "0"));
            ThreadContext.put("client_ip", clientIp);
            ThreadContext.put("device_info", deviceInfo);
            ThreadContext.put("remarks", remarks);
            // 使用自定義的 Login 級別記錄消息
            logger.log(Level.getLevel("LOGIN_LOG"), remarks);
        } finally {
            LogUtils.clearLogContext(); // 在try塊之后清除上下文,確保上下文信息不泄漏
        }
    }
    /**
     * 設(shè)置用戶登錄日志,包含用戶ID、用戶名、客戶端IP、設(shè)備信息和備注信息。
     *
     * @param clientIp   客戶端IP地址。
     * @param deviceInfo 設(shè)備信息。
     * @param remarks    登錄日志的備注信息。
     * @param userParams 用戶ID、用戶名。
     */
    public static void setLogLogin(String clientIp, String deviceInfo, String remarks, String... userParams) {
        String userId = Optional.ofNullable(userParams.length > 0 ? userParams[0] : null).orElse("0");
        String userName = Optional.ofNullable(userParams.length > 1 ? userParams[1] : null).orElse("0");
        try {
            // 設(shè)置上下文信息,這些信息將與日志消息關(guān)聯(lián)
            ThreadContext.put("user_id", userId);
            ThreadContext.put("user_name", userName);
            ThreadContext.put("client_ip", clientIp);
            ThreadContext.put("device_info", deviceInfo);
            ThreadContext.put("remarks", remarks);
            // 使用自定義的 Login 級別記錄消息
            logger.log(Level.getLevel("LOGIN_LOG"), remarks);
        } finally {
            LogUtils.clearLogContext(); // 在try塊之后清除上下文,確保上下文信息不泄漏
        }
    }
}

4、寫日志

        LoginLogUtils.setLogLogin(
                customUser.getSysUser().getUserId().toString(),
                customUser.getUsername(),
                request.getRemoteAddr(),
                RequestUtils.getUserAgent(request),
                "登錄成功"
        );

到此這篇關(guān)于SpringBoot使用log4j2將日志記錄到文件及自定義數(shù)據(jù)庫的文章就介紹到這了,更多相關(guān)SpringBoot使用log4j2內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring IOC 三種配置方式詳解

    Spring IOC 三種配置方式詳解

    這篇文章主要介紹了Spring IOC 三種配置方式,基于xml配置方式組件管理,基于注解方式管理和配置類方式管理,這三種方式,通過圖文講解的非常詳細(xì),需要的朋友可以參考下
    2024-05-05
  • docusaurus如何添加一個(gè)搜索功能

    docusaurus如何添加一個(gè)搜索功能

    這篇文章主要介紹了docusaurus如何添加一個(gè)搜索功能,本文通過實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-04-04
  • Mybatis重置Criteria的正確姿勢分享

    Mybatis重置Criteria的正確姿勢分享

    這篇文章主要介紹了Mybatis重置Criteria的正確姿勢,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • springboot項(xiàng)目docker分層構(gòu)建的配置方式

    springboot項(xiàng)目docker分層構(gòu)建的配置方式

    在使用dockerfile構(gòu)建springboot項(xiàng)目時(shí),速度較慢,用時(shí)比較長,為了加快構(gòu)建docker鏡像的速度,采用分層構(gòu)建的方式,這篇文章主要介紹了springboot項(xiàng)目docker分層構(gòu)建,需要的朋友可以參考下
    2024-03-03
  • SpringBoot項(xiàng)目打包為window安裝包的實(shí)現(xiàn)

    SpringBoot項(xiàng)目打包為window安裝包的實(shí)現(xiàn)

    本文主要介紹了SpringBoot項(xiàng)目打包為window安裝包的實(shí)現(xiàn),通過jpackage及maven插件的方式將springboot項(xiàng)目打包為exe或msi,下面就一起來了解一下
    2026-03-03
  • java時(shí)間段查詢將00:00:00更換成23:59:59

    java時(shí)間段查詢將00:00:00更換成23:59:59

    本文主要介紹了java時(shí)間段查詢將00:00:00更換成23:59:59,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • Junit Mockito實(shí)現(xiàn)單元測試方法介紹

    Junit Mockito實(shí)現(xiàn)單元測試方法介紹

    JUnit是用于編寫和運(yùn)行可重復(fù)的自動(dòng)化測試開源測試項(xiàng)目框架,這樣可以保證我們的代碼按與其工作。JUnit可廣泛用于工業(yè)和作為支架(從命令行)或IDE(如IDE)內(nèi)單獨(dú)的java程序
    2022-09-09
  • java中類型轉(zhuǎn)換和變量理解及實(shí)例詳解

    java中類型轉(zhuǎn)換和變量理解及實(shí)例詳解

    由于java是強(qiáng)類型語言,所以要進(jìn)行有些運(yùn)算的時(shí)候,需要用到類型轉(zhuǎn)換,這篇文章主要介紹了java中類型轉(zhuǎn)換和變量理解的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-10-10
  • 將SpringBoot項(xiàng)目無縫部署到Tomcat服務(wù)器的操作流程

    將SpringBoot項(xiàng)目無縫部署到Tomcat服務(wù)器的操作流程

    SpringBoot 是一個(gè)用來簡化 Spring 應(yīng)用初始搭建以及開發(fā)過程的框架,我們可以通過內(nèi)置的 Tomcat 容器來輕松地運(yùn)行我們的應(yīng)用,本文給大家介紹 SpringBoot 項(xiàng)目部署到獨(dú)立 Tomcat 服務(wù)器的操作流程,需要的朋友可以參考下
    2024-05-05
  • 解決SpringBoot項(xiàng)目讀取yml文件中值為中文時(shí),在視圖頁面顯示亂碼

    解決SpringBoot項(xiàng)目讀取yml文件中值為中文時(shí),在視圖頁面顯示亂碼

    這篇文章主要介紹了解決SpringBoot項(xiàng)目讀取yml文件中值為中文時(shí),在視圖頁面顯示亂碼的問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08

最新評論

琼海市| 宁国市| 卢氏县| 西充县| 张家港市| 格尔木市| 南阳市| 乾安县| 蓝田县| 鄂伦春自治旗| 宜良县| 丰县| 招远市| 丰城市| 西平县| 桐柏县| 泰来县| 临汾市| 买车| 海南省| 正镶白旗| 新晃| 廉江市| 重庆市| 芒康县| 平远县| 手游| 大悟县| 龙门县| 浦县| 平顶山市| 靖江市| 托里县| 西昌市| 德江县| 万全县| 呼伦贝尔市| 太康县| 玉环县| 深水埗区| 惠安县|