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. JAVA编译

    1.javac 编译时的类路径 javac会到classpath+package+下寻找依赖 类路径=classpath+package 2.运行 java xx.class 运行时运行类,必须指定类 ...

  2. CPU、内存、硬盘之间的关系

    要完完全全地讲清楚cpu.内存.硬盘之间的关系,博客的篇幅是不够的.这里简单的介绍以下它们之间的关系,抛砖引玉. 1.CPU即中央处理器,是英语“Central Processing Unit”的缩写 ...

  3. HiBench成长笔记——(9) 分析源码monitor.py

    monitor.py 是主监控程序,将监控数据写入日志,并统计监控数据生成HTML统计展示页面: #!/usr/bin/env python2 # Licensed to the Apache Sof ...

  4. 苹果vs中国竞争者:瘦死的骆驼比马大?

    前不久,苹果调整2019年第一财季的营收指引,预计第一季度毛利率为38%,相关收入大约为55亿美元,全年总体营收约为840亿美元,运营开支约为87亿美元.针对2019年的运营状况,库克亲自给投资者写了 ...

  5. 用python实现在手机查看小姐姐的电脑在作什么!

    看上心意的小姐姐,想看她平时都浏览什么网页,如何才能看她的桌面呢,都说Python很厉害,这次我们做一个利用移动端访问电脑来查看电脑的界面的神器!不知道大家以前有没有做过这方面的东西呢?也许大家听起来 ...

  6. SpringBoot-属性配置yaml自定义属性和值

    SpringBoot-属性配置yaml自定义属性和值 SpringBoot-属性配置yaml自定义属性和值 在SpringBoot中yml/yaml文件可以自定义一些属性,以供注入给自定义bean对象 ...

  7. DStream-05 updateStateByKey函数的原理和源码

    Demo updateState 可以到达将每次 word count 计算的结果进行累加. object SocketDstream { def main(args: Array[String]): ...

  8. POJ 2796:Feel Good 单调栈经典题

    Feel Good Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 11626   Accepted: 3212 Case T ...

  9. Easy_vb

    拿到之后运行一下 之后使用ida打开先关键字搜索一下,结果就出来了

  10. jQuery省市联动(XML/JSON)

    准备: 导包 在src下导入c3p0-config.xml 导入JDBCUtil 创建数据库 新建js文件夹导入jQuery配置文件 NO01:创建city.jsp页面 <%@ page lan ...