创建业务 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. Volcano:在离线作业混部管理平台,实现智能资源管理和作业调度

    摘要:本文结合华为CCE团队在混合部署方面的研究和实战,介绍了混合部署的背景.概念.混部技术的设计方案和实际落地情况,以及对未来的计划和展望. 现代互联网数据中心的规模随着应用服务需求的快速增长而不断 ...

  2. 自动驾驶运动规划-Dubins曲线

    1.Simple Car模型 如下图所示,Simple Car模型是一个表达车辆运动的简易模型.Simple Car模型将车辆看做平面上的刚体运动,刚体的原点位于车辆后轮的中心:x轴沿着车辆主轴方向, ...

  3. DOS、DOS攻击、DDOS攻击、DRDOS攻击

    https://baike.baidu.com/item/dos%E6%94%BB%E5%87%BB/3792374?fr=aladdin DOS:中文名称是拒绝服务,一切能引起DOS行为的攻击都被称 ...

  4. java的内存泄露是如何发生的,如何避免和发现

    java的垃圾回收与内存泄露的关系:[新手可忽略不影响继续学习] 马克-to-win:上一节讲了,(i)对象被置成null.(ii)局部对象(无需置成null)当程序运行到右大括号.(iii)匿名对象 ...

  5. git生成和添加SSH公钥

    一 .前言: 大家换电脑.换公司的时候,经常要关联本地git和git线上仓库, 在这里我就顺便记一下,好记性不如烂笔头, 以后找起来来方便 二 .查看自己是否生成过公钥,有的话可以直接拿过来用, 也可 ...

  6. uniapp打包成H5部署到服务器教程

    当前端uniapp写的项目开发完成的时候,需要将页面打包出来,生成H5的静态文件,部署在服务器上,通过服务器链接地址,就可以直接在手机上点开访问 了. 在网上看了一圈,好像没有找到十分详细的教程,这里 ...

  7. javascript回调地狱真的只能Promise来解决吗?js回调地狱,Promise。

    javascript的灵活在于函数可以当作函数的参数来传递,以及它的异步回调思想.但是这就带了一个很严重的问题,那就是回调次数过多,会影响代码结构,多层嵌套影响代码的可阅读性,也不便于书写. 举个例子 ...

  8. Jedis的基本操作

    jedis jedis 是 redis推荐的java客户端.通过Jedis我们可以很方便地使用java代码的方式,对redis进行操作.jedis使用起来比较简单,它的操作方法与redis命令相类似. ...

  9. Element instanceof Node

    今天看到一个问题,问 Element instance Node 为什么是 false. 首先,我们知道 Element 是 Node 的子类,那么为什么 Element instanceof Nod ...

  10. 项目-MyBlog

    项目 地址:https://gitee.com/zwtgit/my-blog 由Docker + SpringBoot2.0 + Mybatis + thymeleaf 等技术实现, 功能齐全.部署简 ...