Spring Boot 集成教程


概述

异常处理注解

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

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

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

错误处理页面:ErrorController

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

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

@RestController
public class MyErrorController implements ErrorController { @RequestMapping(value = "/error")
public ResponseEntity<Result> error() {
Result res = new Result(404, "页面未找到");
return new ResponseEntity<Result>(res, HttpStatus.NOT_FOUND);
} @Override
public String getErrorPath() {
return "/error";
}
}

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

404 异常

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

spring.mvc.throw-exception-if-no-handler-found=true
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,完成项目创建。

项目配置

application.properties配置

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

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

代码实现

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

异常处理类 ErrorHandler.java

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

  • 输入参数校验异常处理
  • 404异常处理
  • 缺省的异常处理函数,处理所有其他异常

@ControllerAdvice //表明这是控制器的异常处理类
public class ErrorHandler { private static final org.slf4j.Logger log = LoggerFactory.getLogger(ErrorHandler.class); /**
* 输入参数校验异常
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public ResponseEntity<Result> NotValidExceptionHandler(HttpServletRequest req, MethodArgumentNotValidException e) throws Exception { log.debug("异常详情", e);
BindingResult bindingResult = e.getBindingResult(); //rfc4918 - 11.2. 422: Unprocessable Entity
Result res = MiscUtil.getValidateError(bindingResult);
return new ResponseEntity<Result>(res, HttpStatus.UNPROCESSABLE_ENTITY);
} /**
* 404异常处理
*/
@ExceptionHandler(value = NoHandlerFoundException.class)
public ResponseEntity<Result> NoHandlerFoundExceptionHandler(HttpServletRequest req, Exception e) throws Exception { log.debug("异常详情", e); Result res = new Result(404, "页面不存在");
return new ResponseEntity<Result>(res, HttpStatus.NOT_FOUND);
} /**
* 默认异常处理,前面未处理
*/
@ExceptionHandler(value = Throwable.class)
public ResponseEntity<Result> defaultHandler(HttpServletRequest req, Exception e) throws Exception { Result res = new Result(500, "服务器内部错误");
log.debug("异常详情", e); return new ResponseEntity<Result>(res, HttpStatus.INTERNAL_SERVER_ERROR);
}
}

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

控制器 AuthController

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

@RestController
@RequestMapping("/auth")
public class AuthController { @RequestMapping(value = "/register", method = RequestMethod.POST, produces="application/json")
public ResponseEntity<Result> register(
@Valid @RequestBody RegisterRequest register
// , BindingResult bindingResult
) throws Exception { // if(bindingResult.hasErrors()) {
//
// Result res1 = MiscUtil.getValidateError(bindingResult);
// return new ResponseEntity<Result>(res1, HttpStatus.UNPROCESSABLE_ENTITY);
// } Result res = new Result(200, "ok");
return ResponseEntity.ok(res);
}
}

RegisterRequest (DTO/数据传输对象)

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


public class RegisterRequest { @SuppressWarnings("unused")
private static final org.slf4j.Logger log = LoggerFactory.getLogger(RegisterRequest.class); @NotNull(message="手机号必须填")
@Pattern(regexp = "^[1]([3][0-9]{1}|59|58|88|89)[0-9]{8}$", message="账号请输入11位手机号") // 手机号
private String mobile; @NotNull(message="昵称必须填")
@Size(min=1, max=20, message="昵称1~20个字")
private String nickname; @NotNull(message="密码必须填")
@Size(min=6, max=16, message="密码6~16位")
private String password; public String getMobile() {
return mobile;
} public void setMobile(String mobile) {
this.mobile = mobile;
} public String getNickname() {
return nickname;
} public void setNickname(String nickname) {
this.nickname = nickname;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} }

辅助类

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

运行

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

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

访问不存在的网址

总结

完整代码

spring boot 异常(exception)处理的更多相关文章

  1. 启动spring boot 异常

    再我搭建spring boot工程后,run application的时候抛出下面异常 Exception /slf4j-log4j12-.jar). If you are using WebLogi ...

  2. spring boot 异常汇总

    spring boot JPA 异常: org.springframework.data.mapping.PropertyReferenceException: No property role fo ...

  3. Spring boot异常统一处理方法:@ControllerAdvice注解的使用、全局异常捕获、自定义异常捕获

    一.全局异常 1.首先创建异常处理包和类 2.使用@ControllerAdvice注解,全局捕获异常类,只要作用在@RequestMapping上,所有的异常都会被捕获 package com.ex ...

  4. Spring Boot 全局Exception处理

    一.代码如下 package com.zxguan; import org.springframework.web.bind.annotation.ControllerAdvice; import o ...

  5. spring boot异常积累

    1.异常:Error resolving template "xxx", template might not exist or might not be accessible.. ...

  6. Java异常机制,自定义异常以及spring boot异常设计方案

    异常机制: 异常概念 异常分类 异常的处理方法 自定义异常 springboot 的异常解决方案

  7. spring boot集成mybatis(1)

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  8. spring boot配置druid连接池连接mysql

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  9. spring boot 连接Mysql介绍

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

随机推荐

  1. Jquery元素筛选、html()和text()和val三者区别

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 006.CI4框架CodeIgniter, 加载框架的helper辅助类,调用helper类中的各种函数

    01. CI4框架作为一个很成熟的框架,给我们提供了很多helper辅助类,我们在代码中可以很方便的使用,如下所示,我们在Controllers中调用Cookies类的set_cookie函数 < ...

  3. DOM基础1

    Document Object Model 文档对象模型 1.改内容: innerHTML 例:div1.innerHTML = "我能干<br />什么";      ...

  4. 使用conda创建虚拟环境

    conda创建python虚拟环境 前言 conda常用的命令: conda list 查看安装了哪些包. conda env list 或 conda info -e 查看当前存在哪些虚拟环境 co ...

  5. NO5 grep-head-tail命令

    ·*****grep:#过滤需要的内容(linux三剑客).                   -v:排除内容.eg:grep -v oldboy test.txt ·head: #头,头部.读取文 ...

  6. js中const,val,let 的区别

    1. const定义的变量不可以修改,而且必须初始化. 2. var定义的变量可以修改,如果不初始化会输出undefined,不会报错. 3. let是块级作用域,函数内部使用let定义后,对函数外部 ...

  7. 10 分钟彻底理解 Redis 的持久化和主从复制

    在这篇文章,我们继续有关Redis方面知识的学习,一起了解一下其中一个非常重要的内容:Redis的持久化机制. 什么是Redis持久化? Redis作为一个键值对内存数据库(NoSQL),数据都存储在 ...

  8. 基于共享内存、信号、命名管道和Select模型实现聊天窗口

    问题模型 A.B两个进程通过管道通信,A 进程每次接收到的数据通过共享内存传递给A1进程显示,同理,B进程每次接收到的数据通过共享内存传递给B1进程显示: 对于A.B 进程,采用ctrl+c(实际为S ...

  9. poker2的配置使用

    1.映射Win键的诸多功能 切换输入法,shift+alt本身已经支持了,所以Win+Space就不管了 Win+Space映射为Fn+Space Win+E映射为Fn+E Win+R映射为Fn+R ...

  10. 虚拟化安全服务器のIP修改配置

    1)进入网卡配置文件目录(以centos7.6为例) cd /etc/sysconfig/network-scripts     2)编辑配置文件(根据自己机器实际网卡进行编辑), 如Vi ifcfg ...