创建业务 Exception

一般在实际项目中,推荐创建自己的 Exception 类型,这样在后期会更容易处理,也比较方便统一,否则,可能每个人都抛出自己喜欢的异常类型,而造成代码混乱

ServiceException 用于抛出业务逻辑校验异常

UnauthorizedException 用于抛出用户未登录异常

可根据自己的项目需求变化,但简单项目中这两个已经够用

ServiceException

package cn.myesn.exception;

public class ServiceException extends RuntimeException {

    /**
* Constructs a new runtime exception with {@code null} as its
* detail message. The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause}.
*/
public ServiceException() {
super();
} /**
* Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public ServiceException(String message) {
super(message);
} /**
* Constructs a new runtime exception with the specified detail message and
* cause. <p>Note that the detail message associated with
* {@code cause} is <i>not</i> automatically incorporated in
* this runtime exception's detail message.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link #getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A <tt>null</tt> value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public ServiceException(String message, Throwable cause) {
super(message, cause);
} /**
* Constructs a new runtime exception with the specified cause and a
* detail message of <tt>(cause==null ? null : cause.toString())</tt>
* (which typically contains the class and detail message of
* <tt>cause</tt>). This constructor is useful for runtime exceptions
* that are little more than wrappers for other throwables.
*
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A <tt>null</tt> value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public ServiceException(Throwable cause) {
super(cause);
} /**
* Constructs a new runtime exception with the specified detail
* message, cause, suppression enabled or disabled, and writable
* stack trace enabled or disabled.
*
* @param message the detail message.
* @param cause the cause. (A {@code null} value is permitted,
* and indicates that the cause is nonexistent or unknown.)
* @param enableSuppression whether or not suppression is enabled
* or disabled
* @param writableStackTrace whether or not the stack trace should
* be writable
* @since 1.7
*/
protected ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

UnauthorizedException

package cn.myesn.exception;

public class UnauthorizedException extends RuntimeException {
/**
* Constructs a new runtime exception with {@code null} as its
* detail message. The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause}.
*/
public UnauthorizedException() {
super();
} /**
* Constructs a new runtime exception with the specified detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public UnauthorizedException(String message) {
super(message);
} /**
* Constructs a new runtime exception with the specified detail message and
* cause. <p>Note that the detail message associated with
* {@code cause} is <i>not</i> automatically incorporated in
* this runtime exception's detail message.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link #getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A <tt>null</tt> value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public UnauthorizedException(String message, Throwable cause) {
super(message, cause);
} /**
* Constructs a new runtime exception with the specified cause and a
* detail message of <tt>(cause==null ? null : cause.toString())</tt>
* (which typically contains the class and detail message of
* <tt>cause</tt>). This constructor is useful for runtime exceptions
* that are little more than wrappers for other throwables.
*
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A <tt>null</tt> value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public UnauthorizedException(Throwable cause) {
super(cause);
} /**
* Constructs a new runtime exception with the specified detail
* message, cause, suppression enabled or disabled, and writable
* stack trace enabled or disabled.
*
* @param message the detail message.
* @param cause the cause. (A {@code null} value is permitted,
* and indicates that the cause is nonexistent or unknown.)
* @param enableSuppression whether or not suppression is enabled
* or disabled
* @param writableStackTrace whether or not the stack trace should
* be writable
* @since 1.7
*/
protected UnauthorizedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

创建异常返回值包装类

package cn.myesn.exception;

import lombok.Data;
import lombok.experimental.Accessors; @Data
@Accessors(chain = true)
public class GlobalExceptionResponseResult {
private String message;
}

创建全局异常处理者

创建 GlobalExceptionHandler 处理类,使用注解 @RestControllerAdvice 修改该类,该注解可以全局处理 spring boot rest controller 中抛出的所有异常,并且不用加 @ResponseBody,因为默认已经加上了

package cn.myesn.handler;

import cn.myesn.exception.GlobalExceptionResponseResult;
import cn.myesn.exception.ServiceException;
import cn.myesn.exception.UnauthorizedException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice
public class GlobalExceptionHandler { // 根本就没有传递参数时的异常
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public GlobalExceptionResponseResult handle(HttpMessageNotReadableException e) {
return new GlobalExceptionResponseResult().setMessage("参数不能为空");
} // 传了参数,但没有通过 validation 时的异常
@ExceptionHandler(BindException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public GlobalExceptionResponseResult handle(BindException e) {
final ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
return new GlobalExceptionResponseResult().setMessage(objectError.getDefaultMessage());
} // 代码中抛出的逻辑异常
@ExceptionHandler(ServiceException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public GlobalExceptionResponseResult handle(ServiceException e) {
return new GlobalExceptionResponseResult().setMessage(e.getMessage());
} // 未登录异常
@ExceptionHandler(UnauthorizedException.class)
@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
public void handle(UnauthorizedException e) {
} // 但以上几种错误都未能匹配到时,catch 一个基础的异常类型,基本上能捕获所有该捕获的异常类型
@ExceptionHandler(RuntimeException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public GlobalExceptionResponseResult handle(RuntimeException e) {
return new GlobalExceptionResponseResult().setMessage(String.format("未处理的异常:%s", e.getMessage()));
}
}

实际使用

新建一个 TestController 文件,在里面添加如下端点:

@GetMapping("check-username")
public ResponseEntity<?> checkUsername(@RequestParam String username) {
if (StringUtils.isBlank(username)) {
throw new ServiceException("用户名不能为空");
} if (userService.existsUserName(username)) {
throw new ServiceException("用户名已存在");
} return ResponseEntity.ok().build();
}

这样,写业务代码时,throw 就行了,代码整体更符合语义,也更加简洁明了

spring boot 统一接口异常返回值的更多相关文章

  1. 只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

    ## 统一返回值 在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生. 比较通用的返回值格式如下: ```jav ...

  2. SpringBoot第十一集:整合Swagger3.0与RESTful接口整合返回值(2020最新最易懂)

    SpringBoot第十一集:整合Swagger3.0与RESTful接口整合返回值(2020最新最易懂) 一,整合Swagger3.0 随着Spring Boot.Spring Cloud等微服务的 ...

  3. spring boot rest 接口集成 spring security(2) - JWT配置

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

  4. spring boot rest 接口集成 spring security(1) - 最简配置

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

  5. Spring Boot 中全局异常处理器

    Spring Boot 中全局异常处理器,就是把错误异常统一处理的方法.等价于Springmvc中的异常处理器. 步骤一:基于前面的springBoot入门小demo修改 步骤二:修改HelloCon ...

  6. postman 上一个接口的返回值作为下一个接口的入参

    在使用postman做接口测试的时候,在多个接口的测试中,如果需要上一个接口的返回值作为下一个接口的入参,其基本思路是: 1.获取上一个接口的返回值 2.将返回值设置成环境变量或者全局变量 3.设置下 ...

  7. 接口需要上一个接口的返回值(unittest)

    import unittest,requests ''' 使用unittest框架的时候,这个接口需要上一个接口的返回值 ''' class Test_case(unittest.TestCase): ...

  8. JMeter-一个接口的返回值作为输入传给其他接口

    背景: 在用JMeter写接口case,遇到一种情况,接口1查看列表接口,接口2查看详情接口,接口2需要传入接口1列表的第一条数据的id 解决方案: 首先放一下总体截图 具体步骤 1-新建一个Thre ...

  9. spring boot:使接口返回统一的RESTful格式数据(spring boot 2.3.1)

    一,为什么要使用REST? 1,什么是REST? REST是软件架构的规范体系,它把资源的状态用URL进行资源定位, 以HTTP动作(GET/POST/DELETE/PUT)描述操作 2,REST的优 ...

随机推荐

  1. poj_3253_priority queue

    描述 农夫约翰想要修篱墙,他需要N块木板,第i块板长Li.然后他买了一块很长的板子,足够他分成N块.忽略每次锯板子带来的损失. 约翰忘记买锯子了,于是像Don借.Don要收费,每次锯一下,就要收一次板 ...

  2. CSS实例:翻转图片、滚动图片栏、打开大门

    CSS 翻转图片主要用到的技术除了3D翻转和定位 ,还用到了一个属性 backface-visibility:visable|hidden;该属性主要是用来设定元素背面是否可见. 效果图如下: 具体的 ...

  3. 基于HTML5的网络拓扑图(1)

    什么是网络拓扑 网络拓扑,指构成网络的成员间特定的排列方式.分为物理的,即真实的.或者逻辑的,即虚拟的两种.如果两个网络的连接结构相同,我们就説它们的网络拓扑相同,尽管它们各自内部的物理接线.节点间距 ...

  4. PhantomJS,隐身浏览器

    PhantomJS PhantomJS是一个无界面的浏览器,实现了传统浏览器的所有功能,除了没有界面,因此,这是一个隐身浏览器. PhantomJS官网 API,特别需要注意的是Web Page Mo ...

  5. Android实现蓝牙远程连接遇到的问题

    主要问到的问题:1.uuid获取不到,一直为空,后来发现android4.2之前使用uuid这种方法,目前尽量不使用uuid方式 2.socket.connect()出错,报read failed, ...

  6. 【Android开发】【布局】 仿微信UI

    Demo地址

  7. msmpeng.exe阻止移动硬盘弹出

    MsMpEng.exe 占用 该进程是微软反恶意软件服务的一个可执行文件,用户无法手动停止该进程. 首先运行   eventvwr.msc打开事件查看器,找到警告信息,查看是什么进程在阻止硬盘弹出. ...

  8. 以&#开头的是什么编码?

    今天遇到了一个网页时繁体的,它的title和meta信息在浏览器中显示正常,但是查看其源码是却是"最新發"这种. 在网上找了半天资料,终于搞明白了. 以在网页中&#开头的是 ...

  9. vux+vue-cli3.0坑

    最近开发了项目使用了vue-cli3.0+vux搭建的项目,现在总结遇到的问题: 环境:github vux有关于vue-cli3.0以及vux已经搭建好的脚手架vux-cli3链接 一:如下报错 解 ...

  10. sequelize模型

    model表示数据库中的表,有时它也会被称为"模型"或"工厂".Model不能通过构造函数创建,只能通过sequlize.define方法来定义或通过sequl ...