天天看點

spring異常處理

還是上次資料不能為空的問題,寫到了

C

層測試。

先寫一行測試代碼,先期待一個

200

,但是我們是知道的,因為沒有學科類别,這肯定會抛出異常,我們就是想看看

Spring

捕獲這個異常之後給出的回報是什麼狀态碼。

@Test
public void saveTest() throws Exception {
    logger.debug("基礎測試資料準備");
    MeasurementUnitCategory measurementUnitCategory = new MeasurementUnitCategory();
    String json = JSON.toJSONString(measurementUnitCategory);

    this.mockMvc.perform(post(baseUrl)
                        .header(xAuthKey, xAuthToken)
                        .contentType(MediaType.APPLICATION_JSON_UTF8)
                        .content(json))
                .andExpect(status().isOk());
}           

測試一下,果然,控制台報錯。

但是看一下報錯資訊,發現并不是我們期待的一個錯誤的狀态碼,而是

200

。同時下面還有異常抛出。

這說明

Spring

為我們抛出了這個

DataIntegrityViolationException

異常,但是卻沒有幫我們處理,這就需要我們手動處理然後傳回給前台狀态碼。

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Application-Context=[application:-1], Content-Type=[application/json;charset=UTF-8], x-auth-token=[1b2b8d9f-3457-4277-879e-2ada48e3599e]}
     Content type = application/json;charset=UTF-8
             Body = {"id":8,"name":"","username":"usersdfdfwef23dfvdfwewef","mobile":"","pinyin":null,"createTime":1528338758059,"updateTime":1528338758059,"status":0,"department":{"id":1,"name":"内蒙古自治區管理部門","code":"","postalCode":"","address":"","legalName":"","legalPhone":"","registrantName":"","registrantPhone":"","registrantTel":null,"registrantMail":"","phone":"","pinyin":"neimengguzishiquguanglibumeng","registerDate":null,"createTime":1528338752423,"updateTime":1528338752423,"status":null,"createUser":null,"departmentType":{"id":1,"name":"管理部門","pinyin":"guanlibumen","createTime":1528338751963,"updateTime":1528338751963,"createUser":null},"district":{"id":1,"districtType":{"id":1,"name":"省","pinyin":"sheng"},"name":"内蒙古自治區","createUser":null,"pinyin":"neimengguzizhiqu","createTime":null,"updateTime":null},"checkAbility":false,"outOfRange":null,"standard":false},"roles":[],"createUser":null,"updateUser":null}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
Caused by: org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "DISCIPLINE_ID"; SQL statement:
insert into measurement_unit_category (id, discipline_id, is_asc) values (null, ?, ?) [23502-194]           

理論上我們所有的異常都是由

M

層抛出,直接捕獲或全局異常處理,是不會将異常抛給控制器的。

是以,我們需要全局異常處理,

M

層抛出異常,直接處理,傳回

xx

狀态碼,而不将異常抛給控制器。

/**
 * 手動捕獲資料沖突異常,經測試,該異常系由Spring抛出,但未捕獲
 * @return HttpStatus.CONFLICT
 * 沖突錯誤,409
 * 參考:
 * https://stackoverflow.com/questions/37248719/couldnt-catch-dataintegrityviolationexception-with-spring-data-rest
 */
@ExceptionHandler(value = DataIntegrityViolationException.class)
public ResponseEntity<JsonErrorResult> dataIntegrityViolationException(HttpServletRequest httpServletRequest, Exception exception) {
    logger.error("---資料不合法:---Host {} invokes url {} ERROR: {}", httpServletRequest.getRemoteHost(), httpServletRequest.getRequestURL(), exception.getMessage());
    return new ResponseEntity<>(new JsonErrorResult(httpServletRequest, exception), HttpStatus.CONFLICT);
}           

我這裡對狀态碼也不是很熟悉,去

StackOverflow

上看到一個老哥是和我遇到了一樣的問題,他解決的方案是捕獲異常傳回

409

(沖突),

參考原文

異常捕獲後,修改測試,期待狀态碼為

409

Conflict

@Test
public void saveTest() throws Exception {
    logger.debug("基礎測試資料準備");
    MeasurementUnitCategory measurementUnitCategory = new MeasurementUnitCategory();
    String json = JSON.toJSONString(measurementUnitCategory);

    logger.debug("無學科的計量機關類别儲存,期待409,沖突狀态碼");
    this.mockMvc.perform(post(baseUrl)
                        .header(xAuthKey, xAuthToken)
                        .contentType(MediaType.APPLICATION_JSON_UTF8)
                        .content(json))
                .andExpect(status().isConflict());
}           

重新運作單元測試,通過。