当前位置:   article > 正文

springboot 404_spring boot 异常(exception)处理

springboot http status 404 – not found

章节

  • Spring Boot 介绍
  • Spring Boot 开发环境搭建(Eclipse)
  • Spring Boot Hello World (restful接口)例子
  • spring boot 连接Mysql
  • spring boot配置druid连接池连接mysql
  • spring boot集成mybatis(1)
  • spring boot集成mybatis(2) – 使用pagehelper实现分页
  • spring boot集成mybatis(3) – mybatis generator 配置
  • spring boot 接口返回值封装
  • spring boot输入数据校验(validation)
  • spring boot rest 接口集成 spring security(1) – 最简配置
  • spring boot rest 接口集成 spring security(2) – JWT配置
  • spring boot 异常(exception)处理
  • spring boot 环境配置(profile)切换
  • spring boot redis 缓存(cache)集成

概述

异常处理注解

spring中处理异常可以通过2个注解:

  • @ControllerAdvice 全局,处理所有控制器中的异常
  • @ExceptionHandler 局部,只针对某个控制器中的异常

先有ExceptionHandler,再有ControllerAdviceExceptionHandler不能集中处理异常,ControllerAdvice为弥补此缺点引入,推荐使用ControllerAdvice。本文介绍ControllerAdvice的用法,对ExceptionHandler不作介绍,如需了解可参考相关资料。

错误处理页面:ErrorController

ErrorController的作用是为servlet设置错误页,默认错误页是Whitelabel,访问不存在的页面就会显示此错误页。

c117a3a66f84c7e8ab6318e2658d6a03.png

通过继承ErrorController接口可以设置自定义的错误页。

  1. @RestController
  2. public class MyErrorController implements ErrorController {
  3. @RequestMapping(value = "/error")
  4. public ResponseEntity<Result> error() {
  5. Result res = new Result(404, "页面未找到");
  6. return new ResponseEntity<Result>(res, HttpStatus.NOT_FOUND);
  7. }
  8. @Override
  9. public String getErrorPath() {
  10. return "/error";
  11. }
  12. }

如果ControllerAdvice中没有直接返回http响应,继续抛出异常,将会调用ErrorController显示错误页。如果在ControllerAdvice中捕获异常并直接返回http响应,就没必要配置ErrorController中的错误页了。

404 异常

spring boot默认不会抛出404异常(NoHandlerFoundException),所以在ControllerAdvice中捕获不到该异常,导致404总是跳过ContollerAdvice,直接显示ErrorController的错误页。需要改变配置,让404错误抛出异常(NoHandlerFoundException),这样便可在ControllerAdvice中捕获此异常。改变配置,在application.properties中添加:

  1. spring.mvc.throw-exception-if-no-handler-found=true
  2. spring.resources.add-mappings=false

过滤器异常

ContollerAdvice不能捕获过滤器抛出的异常,对于此类异常需要特别处理。

如 [spring boot rest 接口集成 spring security(2) – JWT配置] 章节中的jwt过滤器,异常处理需要设置特别的处理类。

使用ContollerAdvice可以实现对所有控制器异常的集中处理,下面通过一个实际项目介绍此过程。

项目内容

模拟一个用户注册的接口,抛出各类异常让ContollerAdvice处理。

要求

  • JDK1.8或更新版本
  • Eclipse开发环境

如没有开发环境,可参考前面章节 [spring boot 开发环境搭建(Eclipse)]。

项目创建

创建spring boot项目

打开Eclipse,创建spring boot的spring starter project项目,选择菜单:File > New > Project ...,弹出对话框,选择:Spring Boot > Spring Starter Project,在配置依赖时,勾选web,完成项目创建。

243a6167fb2aa7c676ba1da869390752.png

项目配置

application.properties配置

  1. ## 服务器端口,默认是8080
  2. server.port=8096
  3. ## 让404错误抛出异常,需要同时设置spring.resources.add-mappings为false
  4. # 让404错误抛出异常
  5. spring.mvc.throw-exception-if-no-handler-found=true
  6. # 禁用静态资源的自动映射,如不禁用,不存在的url将被映射到/**,servlet不有机会抛出异常
  7. spring.resources.add-mappings=false
  8. ## log级别设置为debug, 通过log.debug打印异常信息
  9. logging.level.root=DEBUG

如果使用静态资源的自动映射,不存在的url将被映射到/**,servlet不有机会抛出异常。在rest api的项目中没有静态资源的处理,完全可以禁止。

代码实现

项目目录结构如下图,我们添加了几个类,下面将详细介绍。

cba02628cf50b0d34d63de35528682b9.png

异常处理类 ErrorHandler.java

这个类就是加ControllerAdvice注解的异常处理类,所有控制器的异常,都在这里集中处理。这里我们实现了2类特殊异常的处理函数,以及1个缺省的异常处理函数。

  • 输入参数校验异常处理
  • 404异常处理
  • 缺省的异常处理函数,处理所有其他异常
  1. @ControllerAdvice //表明这是控制器的异常处理类
  2. public class ErrorHandler {
  3. private static final org.slf4j.Logger log = LoggerFactory.getLogger(ErrorHandler.class);
  4. /**
  5. * 输入参数校验异常
  6. */
  7. @ExceptionHandler(value = MethodArgumentNotValidException.class)
  8. public ResponseEntity<Result> NotValidExceptionHandler(HttpServletRequest req, MethodArgumentNotValidException e) throws Exception {
  9. log.debug("异常详情", e);
  10. BindingResult bindingResult = e.getBindingResult();
  11. //rfc4918 - 11.2. 422: Unprocessable Entity
  12. Result res = MiscUtil.getValidateError(bindingResult);
  13. return new ResponseEntity<Result>(res, HttpStatus.UNPROCESSABLE_ENTITY);
  14. }
  15. /**
  16. * 404异常处理
  17. */
  18. @ExceptionHandler(value = NoHandlerFoundException.class)
  19. public ResponseEntity<Result> NoHandlerFoundExceptionHandler(HttpServletRequest req, Exception e) throws Exception {
  20. log.debug("异常详情", e);
  21. Result res = new Result(404, "页面不存在");
  22. return new ResponseEntity<Result>(res, HttpStatus.NOT_FOUND);
  23. }
  24. /**
  25. * 默认异常处理,前面未处理
  26. */
  27. @ExceptionHandler(value = Throwable.class)
  28. public ResponseEntity<Result> defaultHandler(HttpServletRequest req, Exception e) throws Exception {
  29. Result res = new Result(500, "服务器内部错误");
  30. log.debug("异常详情", e);
  31. return new ResponseEntity<Result>(res, HttpStatus.INTERNAL_SERVER_ERROR);
  32. }
  33. }

输入参数校验异常处理,在 [spring boot输入数据校验(validation)] 章节里,是直接在控制器返回bindingResult,现在放在这里统一处理,好处是无需再在每个接口里重复写返回bindingResult的代码。

控制器 AuthController

AuthController实现了一个模拟用户注册的接口,数据校验返回bindingResult的代码被去除,spring boot将直接抛出MethodArgumentNotValidException,然后由ErrorHandler捕获处理。

  1. @RestController
  2. @RequestMapping("/auth")
  3. public class AuthController {
  4. @RequestMapping(value = "/register", method = RequestMethod.POST, produces="application/json")
  5. public ResponseEntity<Result> register(
  6. @Valid @RequestBody RegisterRequest register
  7. // , BindingResult bindingResult
  8. ) throws Exception {
  9. // if(bindingResult.hasErrors()) {
  10. //
  11. // Result res1 = MiscUtil.getValidateError(bindingResult);
  12. // return new ResponseEntity<Result>(res1, HttpStatus.UNPROCESSABLE_ENTITY);
  13. // }
  14. Result res = new Result(200, "ok");
  15. return ResponseEntity.ok(res);
  16. }
  17. }

RegisterRequest (DTO/数据传输对象)

RegisterRequest类接受并校验用户注册时输入的信息。关于数据校验可参考教程 [spring boot输入数据校验(validation)]。

  1. public class RegisterRequest {
  2. @SuppressWarnings("unused")
  3. private static final org.slf4j.Logger log = LoggerFactory.getLogger(RegisterRequest.class);
  4. @NotNull(message="手机号必须填")
  5. @Pattern(regexp = "^[1]([3][0-9]{1}|59|58|88|89)[0-9]{8}$", message="账号请输入11位手机号") // 手机号
  6. private String mobile;
  7. @NotNull(message="昵称必须填")
  8. @Size(min=1, max=20, message="昵称1~20个字")
  9. private String nickname;
  10. @NotNull(message="密码必须填")
  11. @Size(min=6, max=16, message="密码6~16位")
  12. private String password;
  13. public String getMobile() {
  14. return mobile;
  15. }
  16. public void setMobile(String mobile) {
  17. this.mobile = mobile;
  18. }
  19. public String getNickname() {
  20. return nickname;
  21. }
  22. public void setNickname(String nickname) {
  23. this.nickname = nickname;
  24. }
  25. public String getPassword() {
  26. return password;
  27. }
  28. public void setPassword(String password) {
  29. this.password = password;
  30. }
  31. }

辅助类

  • Result 结果封装类
  • MiscUtil 杂项功能

运行

Eclipse左侧,在项目根目录上点击鼠标右键弹出菜单,选择:run as -> spring boot app运行程序。 打开Postman访问接口,运行结果如下:

用户注册,输入错误的信息

1ee0be5c1b436d92033eb0abc1221da7.png

访问不存在的网址

f81b40639834ecdddcbb4d72d633cb56.png

总结

完整代码

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/624951
推荐阅读
相关标签
  

闽ICP备14008679号