【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅

这篇具有很好参考价值的文章主要介绍了【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

🍊缘由

博友的需求就是我最大的动力

博友一说话,本狗笑哈哈。博友要我写啥,我就写啥

【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅

特来一篇关于SpringBoot接口返回结果及异常统一处理,虽说封不封装都能用,但咱后端也得给前端小姐姐留个好印象不是。项目前后端分离,规范的数据传输格式,让REST风格的API具有简单、易读、易用的特点。不仅代码优美,也可以让带刀的前端小姐姐变得更漂亮。以下例子参考多个实际项目,最终总结来跟大家进行分享,大佬勿喷。


🎯主要目标

实现2大重点

1. 统一接口返回结果
2. 配置全局异常处理

正文

🍊一.统一接口返回结果

前端接口请求后台端,后端将返回结果统一封装。提高交互的规范性通用性,也提高了前后端联调效率。前端根据规范格式返回结构体进行统一映射处理,就避免一个接口一个返回格式的问题。

1.统一封装结果包含如下参数

  • 状态码:code
  • 状态信息:status
  • 返回信息:message
  • 数据:data

2.统一封装结果包含如下方法

  • 全参数方法
  • 成功返回(无参)
  • 成功返回(枚举)
  • 成功返回(状态码+返回信息)
  • 成功返回(返回信息 + 数据)
  • 成功返回(状态码+返回信息+数据)
  • 成功返回(数据)
  • 成功返回(返回信息)
  • 失败返回(无参)
  • 失败返回(枚举)
  • 失败返回(状态码+返回信息)
  • 失败返回(返回信息+数据)
  • 失败返回(状态码+返回信息+数据)
  • 失败返回(数据)
  • 失败返回(返回信息)

3.ResponseResult封装返回结果代码

package net.javadog.common.result;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import net.javadog.common.enums.HttpStatusEnum;

/**
 * 返回结果集
 *
 * @author javadog
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel("统一结果集处理器")
public class ResponseResult<T> {

    /**
     * 状态码
     */
    @ApiModelProperty(value = "状态码")
    private Integer code;

    /**
     * 状态信息
     */
    @ApiModelProperty(value = "状态信息")
    private Boolean status;

    /**
     * 返回信息
     */
    @ApiModelProperty(value = "返回信息")
    private String message;

    /**
     * 数据
     */
    @ApiModelProperty(value = "数据")
    private T data;

    /**
     * 全参数方法
     *
     * @param code    状态码
     * @param status  状态
     * @param message 返回信息
     * @param data    返回数据
     * @param <T>     泛型
     * @return {@link ResponseResult<T>}
     */
    private static <T> ResponseResult<T> response(Integer code, Boolean status, String message, T data) {
        ResponseResult<T> responseResult = new ResponseResult<>();
        responseResult.setCode(code);
        responseResult.setStatus(status);
        responseResult.setMessage(message);
        responseResult.setData(data);
        return responseResult;
    }

    /**
     * 全参数方法
     *
     * @param code    状态码
     * @param status  状态
     * @param message 返回信息
     * @param <T>     泛型
     * @return {@link ResponseResult<T>}
     */
    private static <T> ResponseResult<T> response(Integer code, Boolean status, String message) {
        ResponseResult<T> responseResult = new ResponseResult<>();
        responseResult.setCode(code);
        responseResult.setStatus(status);
        responseResult.setMessage(message);
        return responseResult;
    }

    /**
     * 成功返回(无参)
     *
     * @param <T> 泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> success() {
        return response(HttpStatusEnum.SUCCESS.getCode(), true, HttpStatusEnum.SUCCESS.getMessage(), null);
    }

    /**
     * 成功返回(枚举参数)
     *
     * @param httpResponseEnum 枚举参数
     * @param <T>              泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> success(HttpStatusEnum httpResponseEnum) {
        return response(httpResponseEnum.getCode(), true, httpResponseEnum.getMessage());
    }

    /**
     * 成功返回(状态码+返回信息)
     *
     * @param code    状态码
     * @param message 返回信息
     * @param <T>     泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> success(Integer code, String message) {
        return response(code, true, message);
    }

    /**
     * 成功返回(返回信息 + 数据)
     *
     * @param message 返回信息
     * @param data    数据
     * @param <T>     泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> success(String message, T data) {
        return response(HttpStatusEnum.SUCCESS.getCode(), true, message, data);
    }

    /**
     * 成功返回(状态码+返回信息+数据)
     *
     * @param code    状态码
     * @param message 返回信息
     * @param data    数据
     * @param <T>     泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> success(Integer code, String message, T data) {
        return response(code, true, message, data);
    }

    /**
     * 成功返回(数据)
     *
     * @param data 数据
     * @param <T>  泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> success(T data) {
        return response(HttpStatusEnum.SUCCESS.getCode(), true, HttpStatusEnum.SUCCESS.getMessage(), data);
    }

    /**
     * 成功返回(返回信息)
     *
     * @param message 返回信息
     * @param <T>  泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> success(String message) {
        return response(HttpStatusEnum.SUCCESS.getCode(), true, message, null);
    }

    /**
     * 失败返回(无参)
     *
     * @param <T> 泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> fail() {
        return response(HttpStatusEnum.ERROR.getCode(), false, HttpStatusEnum.ERROR.getMessage(), null);
    }

    /**
     * 失败返回(枚举)
     *
     * @param httpResponseEnum 枚举
     * @param <T>              泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> fail(HttpStatusEnum httpResponseEnum) {
        return response(httpResponseEnum.getCode(), false, httpResponseEnum.getMessage());
    }

    /**
     * 失败返回(状态码+返回信息)
     *
     * @param code    状态码
     * @param message 返回信息
     * @param <T>     泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> fail(Integer code, String message) {
        return response(code, false, message);
    }

    /**
     * 失败返回(返回信息+数据)
     *
     * @param message 返回信息
     * @param data    数据
     * @param <T>     泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> fail(String message, T data) {
        return response(HttpStatusEnum.ERROR.getCode(), false, message, data);
    }

    /**
     * 失败返回(状态码+返回信息+数据)
     *
     * @param code    状态码
     * @param message 返回消息
     * @param data    数据
     * @param <T>     泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> fail(Integer code, String message, T data) {
        return response(code, false, message, data);
    }

    /**
     * 失败返回(数据)
     *
     * @param data 数据
     * @param <T>  泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> fail(T data) {
        return response(HttpStatusEnum.ERROR.getCode(), false, HttpStatusEnum.ERROR.getMessage(), data);
    }

    /**
     * 失败返回(返回信息)
     *
     * @param message 返回信息
     * @param <T>  泛型
     * @return {@link ResponseResult<T>}
     */
    public static <T> ResponseResult<T> fail(String message) {
        return response(HttpStatusEnum.ERROR.getCode(), false, message, null);
    }
}


4.HttpStatusEnum返回结果代码

package net.javadog.common.enums;

import lombok.Getter;

/**
 * Http状态返回枚举
 *
 * @author javadog
 **/
@Getter
public enum HttpStatusEnum {
    /**
     * 操作成功
     */
    SUCCESS(200, "操作成功"),
    /**
     * 对象创建成功
     */
    CREATED(201, "对象创建成功"),
    /**
     * 请求已经被接受
     */
    ACCEPTED(202, "请求已经被接受"),
    /**
     * 操作已经执行成功,但是没有返回数据
     */
    NO_CONTENT(204, "操作已经执行成功,但是没有返回数据"),
    /**
     * 资源已被移除
     */
    MOVED_PERM(301, "资源已被移除"),
    /**
     * 重定向
     */
    SEE_OTHER(303, "重定向"),
    /**
     * 资源没有被修改
     */
    NOT_MODIFIED(304, "资源没有被修改"),
    /**
     * 参数列表错误(缺少,格式不匹配)
     */
    BAD_REQUEST(400, "参数列表错误(缺少,格式不匹配)"),
    /**
     * 未授权
     */
    UNAUTHORIZED(401, "未授权"),
    /**
     * 访问受限,授权过期
     */
    FORBIDDEN(403, "访问受限,授权过期"),
    /**
     * 资源,服务未找到
     */
    NOT_FOUND(404, "资源,服务未找!"),
    /**
     * 不允许的http方法
     */
    BAD_METHOD(405, "不允许的http方法"),
    /**
     * 资源冲突,或者资源被锁
     */
    CONFLICT(409, "资源冲突,或者资源被锁"),
    /**
     * 不支持的数据,媒体类型
     */
    UNSUPPORTED_TYPE(415, "不支持的数据,媒体类型"),
    /**
     * 系统内部错误
     */
    ERROR(500, "系统内部错误"),
    /**
     * 接口未实现
     */
    NOT_IMPLEMENTED(501, "接口未实现"),
    /**
     * 系统警告消息
     */
    WARN(601,"系统警告消息");

    private final Integer code;
    private final String message;

    HttpStatusEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}

5.SysLoginController实操调试

/**
 * 登录验证
 *
 * @author javadog
 */
@RestController
public class SysLoginController {

    @Resource
    private SysLoginService loginService;

    /**
     * 登录方法
     *
     * @param loginRequest 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public ResponseResult login(@RequestBody LoginRequest loginRequest) {
        // 生成令牌
        String token = loginService.login(loginRequest.getUsername(), loginRequest.getPassword());
        return ResponseResult.success(token);
    }

}

【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅

【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅


🍋二.配置全局异常处理

在使用上方统一返回结果的加持下,规范的同时也不可避免程序异常情况。因此我们必须提前定义一个统一全局异常来捕获这些异常信息,并将其当作一种结果返回给控制层,友好的处理异常信息。

1.全局异常处理注解

@RestControllerAdvice

@RestControllerAdvice什么是?

  • @RestControllerAdvice注解是Spring MVC和Spring Boot应用程序中用于定义全局异常处理类的注解,它是@ControllerAdvice注解的特殊版本,是一个组合注解,由@ControllerAdvice、@ResponseBody组成

  • @ControllerAdvice继承了@Component,因此@RestControllerAdvice本质上是个组件,用于定义@ExceptionHandler,@InitBinder和@ModelAttribute方法,适用于所有使用@RequestMapping方法

@RestControllerAdvice有什么特点?

  • 注解@RestControllerAdvice的类的方法可以使用@ExceptionHandler、@InitBinder、@ModelAttribute注解到方法上
  • @RestControllerAdvice注解将作用于所有注解了@RequestMapping的控制器的方法上
  • @ExceptionHandler:用于指定异常处理方法,与@RestControllerAdvice配合使用时,用于全局处理控制器里的异常
  • @InitBinder:用来设置WebDataBinder,用于自动绑定前台请求参数到Model中。
  • @ModelAttribute:本来作用是绑定键值对到Model中,当与@ControllerAdvice配合使用时,可以让全局的@RequestMapping都能获得在此处设置的键值对

2.@ExceptionHandler常用异常拦截

  • 权限校验异常:AccessDeniedException(spring-security中异常)
  • 请求方式不支持:HttpRequestMethodNotSupportedException
  • 业务异常:ServiceException(自己业务定义异常)
  • 拦截未知的运行时异常:RuntimeException
  • 系统异常:Exception
  • 自定义验证异常:BindException
  • 自定义验证异常:MethodArgumentNotValidException

3.全局异常处理代码

package net.javadog.common.exception;

import cn.hutool.core.util.ObjectUtil;
import net.javadog.common.enums.HttpStatusEnum;
import net.javadog.common.result.ResponseResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * 异常处理 配置
 *
 * @author javadog
 */
@RestControllerAdvice
public class GlobalException {

    private static final Logger log = LoggerFactory.getLogger(GlobalException.class);

    /**
     * 权限校验异常
     */
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage());
        return ResponseResult.fail(HttpStatusEnum.FORBIDDEN.getCode(), HttpStatusEnum.FORBIDDEN.getMessage());
    }

    /**
     * 请求方式不支持
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
                                                          HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
        return ResponseResult.fail(e.getMessage());
    }

    /**
     * 业务异常
     */
    @ExceptionHandler(ServiceException.class)
    public ResponseResult handleServiceException(ServiceException e) {
        log.error(e.getMessage(), e);
        Integer code = e.getCode();
        return ObjectUtil.isNotNull(code) ? ResponseResult.fail(code, e.getMessage()) : ResponseResult.fail(e.getMessage());
    }

    /**
     * 拦截未知的运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public ResponseResult handleRuntimeException(RuntimeException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',发生未知异常.", requestURI, e);
        return ResponseResult.fail(e.getMessage());
    }

    /**
     * 系统异常
     */
    @ExceptionHandler(Exception.class)
    public ResponseResult handleException(Exception e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',发生系统异常.", requestURI, e);
        return ResponseResult.fail(e.getMessage());
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(BindException.class)
    public ResponseResult handleBindException(BindException e) {
        log.error(e.getMessage(), e);
        String message = e.getAllErrors().get(0).getDefaultMessage();
        return ResponseResult.fail(message);
    }

    /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error(e.getMessage(), e);
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        return ResponseResult.fail(message);
    }

}

4.全局异常处理实操调试

【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅

【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅

总结

本文通过多个SpringBoot实际项目进行归纳整理,从统一接口返回结果配置全局异常处理两个方面出发,介绍如何优雅的封装规范后端接口输出,详细刨析@RestControllerAdvice和@ExceptionHandler注解及使用方式,增加后端服务健壮性和与前端对接规范性,希望由此化繁为简,能够帮到博友分毫。


🍈猜你想问

如何与狗哥联系进行探讨

关注公众号【JavaDog程序狗】

公众号回复【入群】或者【加入】,便可成为【程序员学习交流摸鱼群】的一员,问题随便问,牛逼随便吹。

【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅

此群优势:

  1. 技术交流随时沟通
  2. 任何私活资源免费分享
  3. 实时科技动态抢先知晓
  4. CSDN资源免费下载
  5. 本人一切源码均群内开源,可免费使用
2.踩踩狗哥博客

javadog.net

大家可以在里面留言,随意发挥,有问必答

【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅


🍯猜你喜欢

文章推荐

【项目实战】SpringBoot+uniapp+uview2打造H5+小程序+APP入门学习的聊天小项目

【项目实战】SpringBoot+uniapp+uview2打造一个企业黑红名单吐槽小程序

【模块分层】还不会SpringBoot项目模块分层?来这手把手教你!

【ChatGPT】手摸手,带你玩转ChatGPT

【ChatGPT】SpringBoot+uniapp+uview2对接OpenAI,带你开发玩转ChatGPT


【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅文章来源地址https://www.toymoban.com/news/detail-709875.html

到了这里,关于【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Boot 统一功能处理(拦截器实现用户登录权限的统一校验、统一异常返回、统一数据格式返回)

    目录 1. 用户登录权限校验 1.1 最初用户登录权限效验 1.2 Spring AOP 用户统⼀登录验证 1.3 Spring 拦截器 (1)创建自定义拦截器 (2)将自定义拦截器添加到系统配置中,并设置拦截的规则 1.4 练习:登录拦截器 (1)实现 UserController 实体类 (2)返回的登录页面:login.html (3)实

    2024年02月12日
    浏览(50)
  • 【Spring Boot】拦截器与统一功能处理:统一登录验证、统一异常处理与统一数据返回格式

     Spring AOP是一个基于面向切面编程的框架,用于将横切性关注点(如日志记录、事务管理)与业务逻辑分离,通过代理对象将这些关注点织入到目标对象的方法执行前后、抛出异常或返回结果时等特定位置执行,从而提高程序的可复用性、可维护性和灵活性。但使用原生Sp

    2024年02月16日
    浏览(47)
  • SpringBoot统一收集异常信息并返回给前端

    目录 适用场景 实现方法 结合Servlet对象 @RestControllerAdvice 通常前后端交互时,后端对前端参数进行校验后,对于校验不通过的信息会自定义一个异常抛出,但是后端一旦抛出异常,后台接口服务就会报500的错误 对于有些逻辑错误而言,我们只是想将此信息提示给用户,这时候

    2023年04月08日
    浏览(41)
  • 【Spring Boot统一功能处理】统一异常处理,统一的返回格式,@ControllerAdvice简单分析,即将走进SSM项目的大门! ! !

    前言: 大家好,我是 良辰丫 ,在上一篇文章中我们已经学习了一些统一功能处理的相关知识,今天我们继续深入学习这些知识,主要学习统一异常处理,统一的返回格式,@ControllerAdvice简单分析.💌💌💌 🧑个人主页:良辰针不戳 📖所属专栏:javaEE进阶篇之框架学习 🍎励志语句:生

    2024年02月16日
    浏览(41)
  • springboot统一拦截包装接口返回值

    1、作用 代替手动封装每个接口的返回值,否则每个有返回值的controller接口,都需要手动使用Resonse类包装返回结果 2、实现 方法返回值handler,需要实现接口HandlerMethodReturnValueHandler,并重写supportsReturnType和handleReturnValue方法。只有在supportsReturnType方法返回值为true的情况下才会

    2024年02月13日
    浏览(56)
  • springboot的@RestControllerAdvice作用和捕获自定义异常返回自定义结果案例

    @RestContrllerAdvice是一种组合注解,由@ControllerAdvice,@ResponseBody组成 @ControllerAdvice继承了@Component,反过来,可以理解为@RestContrllerAdvice 本质上就是@Component 本质上是一个类,泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller,@Service等的时候),我们就可以

    2024年02月03日
    浏览(33)
  • springboot全局统一返回处理

    项目中一般都会有规定好的接口返回格式,无论成功与失败,一般格式都是不变的,这样是为了方便前后端统一处理,今天就来说下前后端统一处理的较为优雅的方式; 一般而言都会有一个统一的返回类作为接口的返回数据的封装,例如: 然后我们通过此类作为返回参数的统一封装

    2024年02月13日
    浏览(39)
  • 接口返回响应,统一封装(ResponseBodyAdvice + Result)(SpringBoot)

    接口的返回响应,封装成统一的数据格式,再返回给前端。 对于SpringBoot项目,接口层基于 SpringWeb ,也就是 SpringMVC 。 为了使接口的返回结果数据更加规范化,便于接口测试和前端处理,需要以统一的格式来返回数据; 为了不在每一个接口里面,都写一段返回数据封装的代

    2024年02月08日
    浏览(59)
  • 一文教你处理SpringBoot统一返回格式

    相信大部分后端开发人员在日常开发中都需要和前端对接,当然前后端都是你自己一个人搞的话可以想怎么玩就怎么玩,但是我们还是要做到一定的规范性。在前后端分离的项目中后端返回的格式一定要友好,并且固定,不能经常变来变去,不然会对前端的开发人员带来很多

    2024年02月11日
    浏览(46)
  • SpringBoot 全局异常统一处理:BindException(绑定异常)

    在Spring Boot应用中,数据绑定是一个至关重要的环节,它负责将HTTP请求中的参数映射到控制器方法的入参对象上。在这个过程中如果遇到问题,如参数缺失、类型不匹配或验证失败等,Spring MVC将会抛出一个 org.springframework.validation.BindException 异常。本文将深入解析 BindExceptio

    2024年01月18日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包