spring异常处理

简介: 还是上次数据不能为空的问题,写到了C层测试。先写一行测试代码,先期待一个200,但是我们是知道的,因为没有学科类别,这肯定会抛出异常,我们就是想看看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(冲突),参考原文

异常捕获后,修改测试,期待状态码为409Conflict

@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());
}

重新运行单元测试,通过。

clipboard.png

目录
相关文章
|
1月前
|
Java 开发者 UED
Spring Boot的全局异常处理机制
【2月更文挑战第13天】
58 0
|
3月前
|
Java Spring
【Spring Boot】logback和log4j日志异常处理
【1月更文挑战第25天】【Spring Boot】logback和log4j日志异常处理
|
3月前
|
Dubbo Java 应用服务中间件
微服务框架(十四)Spring Boot @ControllerAdvice异常处理
此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。   本文为Spring Boot使用@ControllerAdvice进行自定义异常捕捉
|
6月前
|
前端开发 Java API
Spring MVC异常处理
Spring MVC异常处理
33 0
|
4月前
|
应用服务中间件
Spring-boot启动失败 Unregistering JMX-exposed beans on shutdown 异常处理
Spring-boot启动失败 Unregistering JMX-exposed beans on shutdown 异常处理
56 0
|
4月前
|
安全 前端开发 Java
Spring Security 自定义异常失效?从源码分析到解决方案
Spring Security 自定义异常失效?从源码分析到解决方案
|
28天前
|
Java 编译器 API
Spring Boot 异常处理
Java异常分为 Throwable 类的两个子类:Error 和 Exception。Error 是不可捕获的,由JVM处理并可能导致程序终止,如 OutOfMemoryError。Exception 是可捕获的,包括运行时异常如 ArrayIndexOutOfBoundsException 和编译时异常如 IOException。
13 1
|
1月前
|
前端开发 Java 数据安全/隐私保护
Spring Boot3自定义异常及全局异常捕获
Spring Boot3自定义异常及全局异常捕获
45 1
|
1月前
|
Java 数据库 开发者
|
6月前
|
JSON 前端开发 Java
构建健壮的Spring MVC应用:JSON响应与异常处理
构建健壮的Spring MVC应用:JSON响应与异常处理
35 0