spring boot 异常(exception)处理
Spring Boot 集成教程
- 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
,再有ControllerAdvice
,ExceptionHandler
不能集中处理异常,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)处理的更多相关文章
- 启动spring boot 异常
再我搭建spring boot工程后,run application的时候抛出下面异常 Exception /slf4j-log4j12-.jar). If you are using WebLogi ...
- spring boot 异常汇总
spring boot JPA 异常: org.springframework.data.mapping.PropertyReferenceException: No property role fo ...
- Spring boot异常统一处理方法:@ControllerAdvice注解的使用、全局异常捕获、自定义异常捕获
一.全局异常 1.首先创建异常处理包和类 2.使用@ControllerAdvice注解,全局捕获异常类,只要作用在@RequestMapping上,所有的异常都会被捕获 package com.ex ...
- Spring Boot 全局Exception处理
一.代码如下 package com.zxguan; import org.springframework.web.bind.annotation.ControllerAdvice; import o ...
- spring boot异常积累
1.异常:Error resolving template "xxx", template might not exist or might not be accessible.. ...
- Java异常机制,自定义异常以及spring boot异常设计方案
异常机制: 异常概念 异常分类 异常的处理方法 自定义异常 springboot 的异常解决方案
- spring boot集成mybatis(1)
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
- spring boot配置druid连接池连接mysql
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
- spring boot 连接Mysql介绍
Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...
随机推荐
- Jquery元素筛选、html()和text()和val三者区别
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 006.CI4框架CodeIgniter, 加载框架的helper辅助类,调用helper类中的各种函数
01. CI4框架作为一个很成熟的框架,给我们提供了很多helper辅助类,我们在代码中可以很方便的使用,如下所示,我们在Controllers中调用Cookies类的set_cookie函数 < ...
- DOM基础1
Document Object Model 文档对象模型 1.改内容: innerHTML 例:div1.innerHTML = "我能干<br />什么"; ...
- 使用conda创建虚拟环境
conda创建python虚拟环境 前言 conda常用的命令: conda list 查看安装了哪些包. conda env list 或 conda info -e 查看当前存在哪些虚拟环境 co ...
- NO5 grep-head-tail命令
·*****grep:#过滤需要的内容(linux三剑客). -v:排除内容.eg:grep -v oldboy test.txt ·head: #头,头部.读取文 ...
- js中const,val,let 的区别
1. const定义的变量不可以修改,而且必须初始化. 2. var定义的变量可以修改,如果不初始化会输出undefined,不会报错. 3. let是块级作用域,函数内部使用let定义后,对函数外部 ...
- 10 分钟彻底理解 Redis 的持久化和主从复制
在这篇文章,我们继续有关Redis方面知识的学习,一起了解一下其中一个非常重要的内容:Redis的持久化机制. 什么是Redis持久化? Redis作为一个键值对内存数据库(NoSQL),数据都存储在 ...
- 基于共享内存、信号、命名管道和Select模型实现聊天窗口
问题模型 A.B两个进程通过管道通信,A 进程每次接收到的数据通过共享内存传递给A1进程显示,同理,B进程每次接收到的数据通过共享内存传递给B1进程显示: 对于A.B 进程,采用ctrl+c(实际为S ...
- poker2的配置使用
1.映射Win键的诸多功能 切换输入法,shift+alt本身已经支持了,所以Win+Space就不管了 Win+Space映射为Fn+Space Win+E映射为Fn+E Win+R映射为Fn+R ...
- 虚拟化安全服务器のIP修改配置
1)进入网卡配置文件目录(以centos7.6为例) cd /etc/sysconfig/network-scripts 2)编辑配置文件(根据自己机器实际网卡进行编辑), 如Vi ifcfg ...