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. url的构成

    url的构成:一般来说,http请求都会和URL地址有关,对于url来说一般由下面5个部分构成 .协议:通常就是第一个冒号之前的内容常见协议:http,https(http+ssl),ftp,ssh, ...

  2. Python 实现远程服务器批量执行命令

    paramiko 远程控制介绍 Python paramiko是一个相当好用的远程登录模块,采用ssh协议,可以实现linux服务器的ssh远程登录.首先来看一个简单的例子 import parami ...

  3. python-python基础5(模块)

    一.模块介绍 定义:本质上就是.py结尾的python文件.模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用 ...

  4. C语言学习巩固(泛型选择)

    在程序设计中,没有特定类型,但是一旦指定一种类型,就可以转换成指定类型的代码, 例如C++有一个关键tmeplate关键字用于声明模板,而模板的最大应用便是创建泛型算法.可惜的是c没有这个关键字 但是 ...

  5. HihoCoder 1245:王胖浩与三角形 三角形边长与面积

    #1245 : 王胖浩与三角形 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 王胖浩有一个三角形,三边长为a,b,c.他有特殊的能力,能增加三条边的边长,增加的总长度不能 ...

  6. ArrayList和LinkedList、Vector的优缺点?

    一般在面试中可能会被问到ArrayList.LinkedList.Vector三者相关的区别! 一般来说我想大概都会回答如下的这些: ArrayList底层是数组结构,查询快,增删慢,线程不安全,效率 ...

  7. chromedriver版本问题

    最新的chromedriver 66.0.3359.117 的对应chromedriver版本为2.38 http://npm.taobao.org/mirrors/chromedriver/ Web ...

  8. R 创建一个空的数据框

    k = 16 #数据框的行数 z = data.frame( a = numeric(k), b = numeric(k), c = numeric(k), d = numeric(k) )

  9. dwr??

    官方网站:http://directwebremoting.org/dwr/index.html http://m.blog.csdn.net/u013628152/article/details/5 ...

  10. maven详解 之 pom.xml

    Maven  一个项目管理工具  其作用就是用来管理jar 包的 maven的核心    pom.xml配置文件 <project xmlns="http://maven.apache ...