首頁  >  問答  >  主體

java - 如何在Spring的@Transaction層面上對異常進行日誌記錄?

在沒使用@Transaction之前,我的商業程式碼模型大概就是下面這樣:

        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(def);

        try {
            studentMapper.insertOnestdent(student);
            logger.info("Insert one record successfully: " + student.toString());
        } catch (Exception ex) {
            dataSourceTransactionManager.rollback(transactionStatus);
            // ex.printStackTrace();
            logger.error("Insert one record unsuccessfully: " + student.toString());
            return false;
        }
        dataSourceTransactionManager.commit(transactionStatus);
        return true;

類似上面這樣的話不管我上面的資料庫操作執行成功還是執行失敗,我在日誌中都可以得到回饋。

但是上面這樣的做法,會造成大量的程式碼的重複,利用spring提供的aop可以實現這樣的日誌功能,但是後來看文檔發現有一個@Transaction註解,使用這個註解,程式碼可以簡化成下面這個樣子:

    @Transactional(rollbackFor = Exception.class)
    public boolean insertOneStudent(Student student) {
        studentMapper.insertOneStudent(student);
        logger.info("Insert one student successfully" + student.toString());
        return true;
    }

這樣當資料庫操作執行成功的時候我可以日誌中成功的進行記錄,但是這樣的話當插入操作執行失敗的時候我應該如何在日誌中進行記錄。

我現在的初步想法是自己手動實作一個類似@Transaction的動態反射的功能,這樣每個要影響資料庫中的資料修改的方法執行的時候我都在動態反射的invoke()方法中進行異常的try catch的處理。 但是不知道spring是否內建這樣的功能?

p.s: 我盡量想將資料庫的操作與處理全部放在service層面來處理,不想將日誌記錄的往上面拋。

某草草某草草2691 天前636

全部回覆(2)我來回復

  • 伊谢尔伦

    伊谢尔伦2017-06-06 09:53:47

    insertOneStudent方法整個try catch

    try {
    ...
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
        throw e;
    }

    或實作@RestControllerAdvice,在裡面統一列印異常日誌
    像這樣:

    @RestControllerAdvice
    public class MyExceptionHandler {
    
        @ExceptionHandler(value = Exception.class)
        public Object exceptionHandler(HttpServletRequest request,
                                             Exception exception) {
            logger.warn("异常:", exception);
            ...
        }
    }

    回覆
    0
  • 世界只因有你

    世界只因有你2017-06-06 09:53:47

    spring也有提供切面的異常處理

    <!--aop配置 -->
        <aop:config>
            <!-- 业务类切面 -->
            <aop:pointcut id="【切面ID】"
                expression="【这里填写切面的匹配规则】" />
            <!-- 异常处理 -->
            <aop:aspect ref="【处理异常的类ID】">
                <aop:after-throwing method="【处理异常的方法名称】" pointcut-ref="【切面ID】" throwing="e" />
            </aop:aspect>
        </aop:config>

    當然,有xml配置就會有註解配置。主要有下面幾個註解

    • @Aspect 聲明切面配置

    • @Pointcut 聲明切面

    • @AfterThrowing 宣告處理方法

    注意事項:

    1. 處理異常的類別是不需要實作任何介面和繼承任何類別的。

    2. 處理異常的方法要聲明兩個參數(不聲明也可以,取得不了異常資訊而已),舉個例子

      public void test(JoinPoint joinPoint, Exception e)

      其中joinPoint參數可以取得拋出異常的方法參數訊息,Exception物件就不用說了吧。

    3. 以上內容只做參考,spring的版本不同也可能會導致上述說明和實際情況有差異,想取得標準的說明請參閱Spring的官方文件

    回覆
    0
  • 取消回覆