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. 设备树DTS 学习:2-设备树语法

    背景 通过上一讲了解完设备树DTS有关概念,我们这一讲就来基于设备树例程,学习设备树的语法规则. 参考:设备树详解dts.设备树语法详解.设备树使用总结 设备树框架 1个dts文件 + n个dtsi文 ...

  2. springboot整合quartz并持久化到数据库

    首先,这里的持久化是是如果当服务器宕机时,任务还在为我们保存.并且在启动服务器之后仍然可以自动执行 一.创建quartz 建表语句mysql的,quartz 2.3.0版本 DROP TABLE IF ...

  3. nodejs配置 https服务

    const port = normalizePort(process.env.PORT || '3000'); const path = require('path'); const https =  ...

  4. 剑指offer 按之字型顺序打印二叉树

    题目描述 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推.   使用两个栈进行存储,我们在打印某一行节点 ...

  5. Day6 - M - 动态逆序对 HYSBZ - 3295

    对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删 除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数 I ...

  6. Java集合基于JDK1.8的LinkedList源码分析

    上篇我们分析了ArrayList的底层实现,知道了ArrayList底层是基于数组实现的,因此具有查找修改快而插入删除慢的特点.本篇介绍的LinkedList是List接口的另一种实现,它的底层是基于 ...

  7. Python爬虫一爬取B站小视频源码

    如果要爬取多页的话 在最下方循环中 填写好循环的次数就可以了 项目源码 from fake_useragent import UserAgent import requests import time ...

  8. springboot 中单机 redis 实现分布式锁

    在微服务中经常需要使用分布式锁,来执行一些任务.例如定期删除过期数据,在多个服务中只需要一个去执行即可. 以下说明非严格意义的分布式锁,因为 redis 实现严格意义的分布式锁还是比较复杂的,对于日常 ...

  9. JS: 复选框——ALL与A、B、C(选中ALL同时选中各子项)

    <!DOCTYPE html><html> <head>  <meta charset="utf-8">  <title> ...

  10. Arrays类常用方法

    Arrays类 3.1 概述 java.util.Arrays 此类包含用来操作数组的各种方法,比如排序和搜索等.其所有方法均为静态方法. 3.2 操作数组的方法 1.将参数数组变成字符串 publi ...