亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解Java如何優(yōu)雅的實(shí)現(xiàn)異常捕獲

 更新時(shí)間:2023年09月08日 14:57:55   作者:烽火戲諸諸諸侯  
在一個(gè)優(yōu)秀的項(xiàng)目中一定少不了對(duì)程序流程良好的異常捕獲與日志打印,所以本文主要為大家介紹了如何優(yōu)雅的實(shí)現(xiàn)異常捕獲與日志打印輸出,有需要的可以參考下

在一個(gè)優(yōu)秀的項(xiàng)目中一定少不了對(duì)程序流程良好的異常捕獲與日志打印,通過二者結(jié)合可實(shí)現(xiàn)異常程序的快速定位,本片文章將詳細(xì)介紹如何優(yōu)雅的實(shí)現(xiàn)異常捕獲與日志打印輸出。

話不多說,下面我們就直奔主題開始介紹相關(guān)知識(shí)吧。

一、異常捕獲

1. 處理方式

程序異常是開發(fā)時(shí)不可避免的,很多時(shí)候我們需要針對(duì)不同異常進(jìn)行不同的處理,最常用的就是try{} catch(){}語句,這里主要說明一下兩種常見異常處理的異同。

堆棧打印

當(dāng)用 printStackTrace() 處理異常時(shí),當(dāng)程序出現(xiàn)異常將會(huì)在控制臺(tái)打印異常信息,然后繼續(xù)執(zhí)行之后的代碼。

public void Exception1Demo() {
    try {
        Integer.parseInt("abc");
    } catch (Exception e) {
        e.printStackTrace()
    }
    // 打印正常輸出
    System.out.println("This is will show.");
}

異常拋出

通過 throw new xxxException() 則會(huì)將異常信息根據(jù)調(diào)用層級(jí)逐層向上拋出,程序?qū)⒃诋惓L幹袛?,不?huì)繼續(xù)執(zhí)行后續(xù)代碼。

public void Exception2Demo() {
    try {
        Integer.parseInt("abc");
    } catch (Exception e) {
        throw new IllegalArgumentException();
    }
    // 打印不會(huì)被輸出
    System.out.println("This is will not show.");
}

2. 捕獲示例

在上一點(diǎn)中介紹了兩種捕獲異常的處理方式,那在實(shí)際的程序開發(fā)中應(yīng)該如何進(jìn)行選擇呢?

最常見的一種規(guī)范即底層異常永遠(yuǎn)向上拋出,由最頂層統(tǒng)一處理。如下示例中 demo() 調(diào)用了 task() 方法,相對(duì)而言 task() 更為底層因此其捕獲異常時(shí)通過 throw 關(guān)鍵字向上拋出,而 demo() 為最頂層則可以通過 printStackTrace() 打印異常堆棧,當(dāng)然也可以選擇繼續(xù)拋出由系統(tǒng)處理異常。

@Test
public void demo() {
    try {
        task();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
private void task() {
    try {
        Integer.parseInt("abc");
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

但如果將上述示例的 task() 方法中捕獲異常替換為 e.printStackTrace();demo() 在調(diào)用 task() 時(shí)將無法捕獲到程序異常,從而導(dǎo)致代碼的執(zhí)行順序可能將與我們?cè)O(shè)想的有所偏差。

當(dāng)然還有一種情景是需要執(zhí)行批量操作,但是我們又想每一批之間可以互不影響,此時(shí)底層模塊也可以選擇不向上拋出異常。

稍微修改一下上述的 task() 方法為如下,這里通過 continue 跳過,替換為 e.printStackTrace() 效果一致。

private void task() {
    for(int i = 0; i < 5; i++) {
        try {
            Integer.parseInt("abc");
        } catch (Exception e) {
            // 不拋出異常,繼續(xù)下一循環(huán)
            continue;
        }
    }
}

3. 自定義異常

自定義異常類十分簡單,只需繼承 RuntimeException ,并編寫相應(yīng)的構(gòu)造方法即可,使用方法同上。

public class BaseException extends RuntimeException {
    public BaseException() {
        super();
    }
    public BaseException(String message, Throwable cause) {
        super(message, cause);
    }
    public BaseException(String message) {
        super(message);
    }
    public BaseException(Throwable cause) {
        super(cause);
    }
}

4. 斷言處理

JDK 1.4 中引入斷言語法更簡潔的實(shí)現(xiàn)異常拋出,在 try catch 中是無法預(yù)判異常環(huán)節(jié)從而用其實(shí)現(xiàn)捕獲,斷言則更多的用于條件判斷。

即通過斷言用于判斷是否滿足先決條件,若否則在該處拋出異常,若是則正常執(zhí)行后續(xù)代碼,下面通過示例說明。

assert

通過 assert 可實(shí)現(xiàn)更便捷的數(shù)據(jù)合法性驗(yàn)證,其基本語法如下,當(dāng)表達(dá)式 <expression> 返回值為 false 時(shí)將拋出一個(gè)異常,通過 <message> 定義異常信息提示。

assert <expression> : <message>;

下面通過一個(gè)具體示例演示效果,兩個(gè)示例的作用效果相同,除了拋出的異常類型不同。

public void AssertDemo() {
    int y = -1;
    assert y > 0 : "The value of y is lower then zero";
}
public void AssertDemo() {
    int y = -1;
    if(y < 0) {
        throw new RuntimeException("The value of y is lower then zero");
    }
}

Assert

更簡潔的語法規(guī)則,效果同上,當(dāng)捕獲到異常后將中斷程序,不會(huì)繼續(xù)執(zhí)行后續(xù)內(nèi)容。

public void Assert2Demo() {
    String msg = "";
    // 打印異常,效果等同 printStackTrace()
    Assert.hasLength(msg, "不允許為空");
    System.out.println("1111");
}

二、日志監(jiān)控

在開發(fā)時(shí)如果需要查看某一處代碼信息時(shí)我們可以直接使用 println() 進(jìn)行打印輸出,但生成環(huán)境下控制臺(tái)信息顯然變得沒有意義,此時(shí)我們就需要通過日志進(jìn)行信息打印。

1. 日志打印

Java 提供原生日志工具類,導(dǎo)入包即可使用。

import java.util.logging.Logger;
public void LogDemo() {
    Logger logger = Logger.getGlobal();
    logger.info("start process...");
    logger.warning("memory is running out...");
    logger.fine("ignored.");
    logger.severe("process will be terminated...");
}

2. Log4j框架

除了自帶的日志框架,Log4j 是當(dāng)下較為流行的日志插件,在項(xiàng)目工程中引入下列依賴,其中 slf4j 指的是日志規(guī)范。

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>2.0.7</version>
</dependency>

其提供了一下兩種初始化方式,區(qū)別在于使用 getClass() 定義的實(shí)例對(duì)象其子類仍可使用。

// 只能當(dāng)前類可用
Logger logger = LoggerFactory.getLogger(LogTest.class);
// 當(dāng)前類與其子類都可用
Logger logger = LoggerFactory.getLogger(getClass());

Slf4j 規(guī)范針對(duì)不同級(jí)別的日志提供不同的接口方法如:info()、 warn()、 debug()、 error(), 基本使用示例如下:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogTest{
    Logger logger = LoggerFactory.getLogger(LogTest.class);
    public static void main(String[] args) {
        logger.info("info ...");
        logger.warn("warn ...");
        logger.debug("debug ...");
        logger.error("error ...");
    }
}

三、Logbak配置

1. 項(xiàng)目配置

在工程的 application.yml 添加 logging.config 用于指定日志配置文件路徑。

# 日志配置文件
logging:
  config: classpath:logback-spring.xml

2. 日志級(jí)別

這里單獨(dú)介紹一下 logger 標(biāo)簽的作用,它可以用于控制指定包路徑下的日志是否輸出。

如配置了 <logger name="xyz.ibudai.slf4j.error" level="ERROR"/>xyz.ibudai.slf4j.error 包路徑下的 info, debug, warn 將不會(huì)出現(xiàn)在配置的輸出日志文件中。

logger 標(biāo)簽中不同的 level 配置輸出的信息如下:

  • INFO:輸出 info, warn, error 級(jí)別日志。
  • DEBUG:輸出 info, debug, warn, error 級(jí)別日志。
  • WARN:只輸出 error 級(jí)別日志。
  • ERROR:只輸出 error 級(jí)別日志。
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!-- 指定包路徑的日志輸出級(jí)別, 過濾低級(jí)別日志 -->
    <logger name="xyz.ibudai.slf4j.info" level="INFO"/>
    <logger name="xyz.ibudai.slf4j.debug" level="DEBUG"/>
    <logger name="xyz.ibudai.slf4j.warn" level="WARN"/>
    <logger name="xyz.ibudai.slf4j.error" level="ERROR"/>
</configuration>

3. 配置格式

resources 目錄下新建 logback-spring.xml 配置文件,常見標(biāo)簽參考下表。

標(biāo)簽作用
property定義全局變量,可通過 ${} 表達(dá)式獲取。
appender搭配 appender-ref 可為不同級(jí)別日志設(shè)置文件輸出配置。
logger用于控制指定包下文件的日志輸出。

如下配置示例中即分別為 INFO, DEBUG, ERROR 三種日志級(jí)別配置了日志內(nèi)容文件輸出,具體作用參考備注信息。

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!-- 設(shè)置日志存儲(chǔ)路徑 -->
    <property name="LOG_HOME" value="./logs"/>
    <!-- 指定基礎(chǔ)的日志輸出級(jí)別 -->
    <root level="INFO">
        <!-- appender 將會(huì)添加到這個(gè) logger -->
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="INFO"/>
        <appender-ref ref="DEBUG"/>
        <appender-ref ref="ERROR"/>
    </root>
    <!-- 控制臺(tái)日志輸出 -->
    <!-- 設(shè)置彩色輸出: -Dlog4j.skipJansi=false -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!-- 設(shè)置輸出格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!-- 格式化輸出 -->
            <!-- (1) %d: 表示日期 -->
            <!-- (2) %thread: 表示線程名 -->
            <!-- (3) %-5level: 日志級(jí)別, 從左顯示 4 個(gè)字符寬度 -->
            <!-- (4) %msg: 表示日志消息 -->
            <!-- (5) %n: 表示換行符 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-4level) %cyan(%logger{50}:%L) - %msg%n</pattern>
            <!-- 設(shè)置編碼 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!-- 按照 INFO 每天生成日志文件 -->
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 日志名, 指定最新的文件名, 其他文件名使用 FileNamePattern  -->
        <file>${LOG_HOME}/info.log</file>
        <!-- 文件滾動(dòng)模式 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志輸出的文件名 -->
            <!-- (1) %i: 表示序號(hào), 當(dāng)日文件多份時(shí)用于區(qū)分 -->
            <!-- (1) gz: 文件類型, 開啟文件壓縮 -->
            <FileNamePattern>${LOG_HOME}/bak/info.log.%d{yyyy-MM-dd}.%i.log.gz</FileNamePattern>
            <!-- 日志文件保留天數(shù) -->
            <MaxHistory>7</MaxHistory>
            <!-- 按大小分割同一天的 -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>128MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 日志級(jí)別過濾, 過濾低級(jí)別日志 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <!-- 日志內(nèi)容輸出格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %thread %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!-- 按照 DEBUG 每天生成日志文件 -->
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${LOG_HOME}/debug.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME}/bak/info.%d{yyyy-MM-dd}.%i.log.gz</FileNamePattern>
            <MaxHistory>7</MaxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>128MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!-- 按照 ERROR 每天生成日志文件 -->
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/error.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME}/bak/error.log.%d{yyyy-MM-dd}.%i.log.gz</FileNamePattern>
            <MaxHistory>7</MaxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>128MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %thread %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <!-- MyBatis log configure -->
    <logger name="com.apache.ibatis" level="INFO"/>
    <logger name="java.sql.Connection" level="ERROR"/>
    <logger name="java.sql.Statement" level="ERROR"/>
    <logger name="java.sql.PreparedStatement" level="ERROR"/>
</configuration>

到此這篇關(guān)于詳解Java如何優(yōu)雅的實(shí)現(xiàn)異常捕獲的文章就介紹到這了,更多相關(guān)Java異常捕獲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java面試必問之ThreadLocal終極篇分享

    Java面試必問之ThreadLocal終極篇分享

    ThreadLocal是什么呢?其實(shí)ThreadLocal并非是一個(gè)線程的本地實(shí)現(xiàn)版本,它并不是一個(gè)Thread,而是thread local variable(線程局部變量),這篇文章主要給大家介紹了關(guān)于Java面試必問之ThreadLocal終極篇的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • Java 遞歸查詢部門樹形結(jié)構(gòu)數(shù)據(jù)的實(shí)踐

    Java 遞歸查詢部門樹形結(jié)構(gòu)數(shù)據(jù)的實(shí)踐

    本文主要介紹了Java 遞歸查詢部門樹形結(jié)構(gòu)數(shù)據(jù)的實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 23種設(shè)計(jì)模式(9) java橋接模式

    23種設(shè)計(jì)模式(9) java橋接模式

    這篇文章主要為大家詳細(xì)介紹了java設(shè)計(jì)模式之橋接模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Spring實(shí)戰(zhàn)之使用Resource作為屬性操作示例

    Spring實(shí)戰(zhàn)之使用Resource作為屬性操作示例

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之使用Resource作為屬性,結(jié)合實(shí)例形式分析了spring載人Resource作為屬性相關(guān)配置與使用技巧,需要的朋友可以參考下
    2020-01-01
  • Java?8?的異步編程利器?CompletableFuture的實(shí)例詳解

    Java?8?的異步編程利器?CompletableFuture的實(shí)例詳解

    這篇文章主要介紹了Java?8?的異步編程利器?CompletableFuture?詳解,本文通過一個(gè)例子給大家介紹下Java?8??CompletableFuture異步編程的相關(guān)知識(shí),需要的朋友可以參考下
    2022-03-03
  • 詳解Spring cloud使用Ribbon進(jìn)行Restful請(qǐng)求

    詳解Spring cloud使用Ribbon進(jìn)行Restful請(qǐng)求

    這篇文章主要介紹了詳解Spring cloud使用Ribbon進(jìn)行Restful請(qǐng)求,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-04-04
  • Logback配置文件這么寫,還說你不會(huì)整理日志?

    Logback配置文件這么寫,還說你不會(huì)整理日志?

    logback框架會(huì)默認(rèn)加載classpath下命名為logback-spring.xml或logback.xml的配置文件。這篇文章主要介紹了Logback配置文件寫法,需要的朋友可以參考下
    2020-07-07
  • Java使用poi實(shí)現(xiàn)excel的導(dǎo)入操作指南

    Java使用poi實(shí)現(xiàn)excel的導(dǎo)入操作指南

    使用Apache Poi是一種流行且廣泛使用的方式,可以幫助開發(fā)人員直接從Java代碼中讀取、寫入和處理Excel文件,因此在這篇文章我們將著重介紹如何實(shí)現(xiàn)excel的導(dǎo)入,感興趣的朋友可以跟著小編一起來學(xué)習(xí)
    2023-06-06
  • log4j的配置文件詳細(xì)解析

    log4j的配置文件詳細(xì)解析

    以下小編主要為大家介紹一下log4j的配置文件各個(gè)配置項(xiàng)的含義。需要的朋友可以過來參考下
    2013-08-08
  • 在Spring Boot中從類路徑加載文件的示例

    在Spring Boot中從類路徑加載文件的示例

    創(chuàng)建Spring Boot Web應(yīng)用程序時(shí),有時(shí)有時(shí)需要從類路徑中加載文件;war和jar的加載文件格式是不一樣的,在下面,您將找到在WAR和JAR中加載文件的解決方案。
    2020-10-10

最新評(píng)論