资讯专栏INFORMATION COLUMN

Spring 异常处理

LiveVideoStack / 1930人阅读

摘要:异常抛出但是看一下报错信息,发现并不是我们期待的一个错误的状态码,而是。所以,我们需要全局异常处理,层抛出异常,直接处理,返回状态码,而不将异常抛给控制器。异常捕获后,修改测试,期待状态码为,。

控制器测试

还是上次数据不能为空的问题,写到了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状态码,而不将异常抛给控制器。

@RestController     // 以rest形式返回异常信息
@ControllerAdvice   // 全局异常处理器
public class GlobalExceptionHandler {

    private final static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class.getName());

    /**
     * 手动捕获数据冲突异常,经测试,该异常系由Spring抛出,但未捕获
     * @return HttpStatus.CONFLICT
     * 冲突错误,409
     * 参考:
     * https://stackoverflow.com/questions/37248719/couldnt-catch-dataintegrityviolationexception-with-spring-data-rest
     */
    @ExceptionHandler(value = DataIntegrityViolationException.class)
    public ResponseEntity 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());
}

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69677.html

相关文章

  • (六讲)Spring Boot REST API异常处理指南

    摘要:在本讲中,通过一个精简的项目,着重介绍一些的异常处理技巧。现在,为了快熟实现自定义异常信息处理类,并让其正常工作,我们可以直接扩展提供的类来定义用户异常信息处理类。将异常报告封装到对象中,并回传给。 能够正确的处理REST API程序抛出的异常以及返回友好的异常信息是一件非常重要的事情,因为它可以帮助API客户端正确的对服务端的问题作出正确的响应。这有助于提高REST API的服务质量。Sp...

    bbbbbb 评论0 收藏0
  • Spring Boot 2.x 系列教程:WebFlux REST API 全局异常处理 Error

    摘要:挺多人咨询的,异常处理用切面注解去实现去全局异常处理。全局异常处理类,代码如下代码解析如下抽象类是用来处理全局错误时进行扩展和实现注解标记的切面排序,值越小拥有越高的优先级,这里设置优先级偏高。 本文内容 为什么要全局异常处理? WebFlux REST 全局异常处理实战 小结 摘录:只有不断培养好习惯,同时不断打破坏习惯,我们的行为举止才能够自始至终都是正确的。 一、为什么要全局...

    BicycleWarrior 评论0 收藏0
  • Spring Boot & Spring MVC 异常处理的N种方法

    摘要:定制特定异常返回结果根据官方文档的例子,可以使用和对特定异常返回特定的结果。下面是用浏览器和访问的结果无输出注意上方表格的错误,产生这个的原因前面已经讲过。不过需要注意的是,无法通过设定,由或者容器决定里一律是。 github:https://github.com/chanjarste... 参考文档: Spring Boot 1.5.4.RELEASE Documentation ...

    h9911 评论0 收藏0
  • SpringBoot RESTful 应用中的异常处理小结

    摘要:和的区别方法注解作用于级别注解为一个定义一个异常处理器类注解作用于整个工程注解定义了一个全局的异常处理器需要注意的是的优先级比高即抛出的异常如果既可以让标注的方法处理又可以让标注的类中的方法处理则优先让标注的方法处理处理中的异常为了方便地展 @ControllerAdvice 和 @ExceptionHandler 的区别 ExceptionHandler, 方法注解, 作用于 Co...

    jackzou 评论0 收藏0
  • spring中的统一异常处理

    摘要:首先,定义一个存放异常处理函数的类,并使用修饰。修饰的方法的写法和内的异常处理函数写法是一样的。控制生效的范围注意到,我是这样编写注解的它用来限定这些异常处理函数起作用的的范围。使用的机制,做统一异常处理。 在具体的SSM项目开发中,由于Controller层为处于请求处理的最顶层,再往上就是框架代码的。因此,肯定需要在Controller捕获所有异常,并且做适当处理,返回给前端一个友...

    paraller 评论0 收藏0
  • [Spring cloud 一步步实现广告系统] 4. 通用代码模块设计

    摘要:对的配置和行为进行定制修改匹配路由请求规则注册自定义的和添加静态资源处理器添加自定义视图控制器添加自定义方法参数处理器配置消息转换器清空所有转换器做一个好人。博客园掘金简书头条知乎 一个大的系统,在代码的复用肯定是必不可少的,它能解决: 统一的响应处理(可以对外提供统一的响应对象包装) showImg(https://segmentfault.com/img/remote/146000...

    since1986 评论0 收藏0

发表评论

0条评论

LiveVideoStack

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<