Springboot项目异常处理及返回结果统一

下面是关于Spring Boot项目异常处理及返回结果统一的完整攻略:

1. 异常处理的重要性

在Web开发中,异常是常见的问题。除开系统自带的异常外,还有业务系统自己抛出的异常。如果不及时有效的处理异常,系统将会毫无提示地将异常信息直接暴露给用户,这对系统的安全性以及可维护性均会产生不利影响。

因此,良好的异常处理机制非常重要。Spring Boot为我们提供了强大的异常处理机制,使用它能够做到全局统一异常处理并返回统一格式的异常信息,这样一来,不仅能够保护系统的安全性,更能给用户提供友好的提示。

2. 统一异常处理

统一异常处理是指将所有可能出现的异常捕获并转化为同一种异常类型,从而使得异常处理方式标准化并分离业务和异常处理逻辑。

在Spring Boot中,您可以使用@ControllerAdvice,@ExceptionHandler和其他有关注解来实现全局异常处理。具体的步骤如下:

2.1 创建一个全局异常处理类

首先,你需要创建一个类并添加@ControllerAdvice注解。这样Spring Boot就知道它应该将这个类用作全局异常处理程序。

@ControllerAdvice
public class GlobalExceptionHandler {
    // 异常处理方法
}

2.2 使用@ExceptionHandler来处理异常

接下来,您需要使用@ExceptionHandler注解来处理各种异常类型。例如:

@ExceptionHandler(Exception.class)
@ResponseBody
public JsonResult handleException(Exception e) {
    // 处理逻辑
}

在上面的代码中,我们使用了@ApiIgnore注解,表示这个方法不会被Swagger API文档显示。@ResponseBody注解是将方法的返回值自动转换为JSON格式。

在异常处理中,我们需要使用自定义异常类,统一处理所有抛出的自定义异常。查看如下的代码:

@ExceptionHandler(CustomException.class)
@ResponseBody
public JsonResult handleCustomException(CustomException e) {
    // 处理逻辑
}

相比较上面的代码,这里处理的是自定义异常。对于常规异常和自定义异常的处理方式需要分别处理。

2.3 自定义异常

定义自定义异常需要继承RuntimeException或其子类,以便在代码中抛出异常:

public class CustomException extends RuntimeException {
    // 自定义异常处理逻辑
}

2.4 返回异常信息

下面是一个返回统一格式的异常处理实例:

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public JsonResult handleException(Exception ex) {
        log.error("[GlobalExceptionHandler] handleException: ", ex);
        return JsonResult.error(ResultCode.INTERNAL_SERVER_ERROR.getCode(),
                ResultCode.INTERNAL_SERVER_ERROR.getMessage());
    }

    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public JsonResult handleCustomException(CustomException ex) {
        log.error("[GlobalExceptionHandler] handleCustomException: ", ex);
        return JsonResult.error(ex.getCode(), ex.getMessage());
    }
}

在上面的代码中,我们使用了@Slf4j注解,用于记录日志,@ResponseBody用于将结果转换为JSON字符串,而JsonResult是自定义的统一数据返回格式。

3. 统一返回结果处理

除了处理异常信息,将所有的返回结果都统一成一个格式,也是很有必要的。这样一来,无论使用什么方式,返回的数据都是统一的格式,这样利于前端数据处理以及进行规范化。

3.1 创建返回结果类

首先,您需要创建一个返回结果类。根据实际情况,您的结果类可以包含不同的属性。一般来说,一个返回结果类需要包含状态码(code)、消息(msg)以及返回的数据(data)等属性。示例如下:

public class JsonResult {

    // 请求结果状态码
    private Integer code;

    // 请求结果消息
    private String msg;

    // 请求结果数据
    private Object data;
}

3.2 封装返回结果

定义好返回结果类之后,您需要在Controller层对所有的返回对象进行封装,并使用@JsonInclude注解转换为JSON格式,并设置每个方法的@ResponseBody注解为统一处理类:

@RestControllerAdvice
public class ResponseControllerAdvice {

    @ExceptionHandler({Exception.class, BusinessException.class})
    public JsonResult handleException(Exception ex) {
        return JsonResult.fail(ex.getMessage());
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public JsonResult handleHttpMessageNotReadableException(HttpServletRequest request,
            HttpMessageNotReadableException ex) {
        String message = String.format("URL: %s, %s", request.getRequestURL().toString(),
                "参数解析失败,请检查传参格式是否正确或参数是否缺失");
        return JsonResult.fail(message);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public JsonResult handleMethodArgumentNotValidException(HttpServletRequest request,
            MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder message = new StringBuilder();
        if (bindingResult.hasErrors()) {
            bindingResult.getAllErrors()
                    .forEach(error -> message.append(error.getDefaultMessage()).append(","));
        }
        message.deleteCharAt(message.length() - 1);
        String errMsg = String.format("URL: %s, %s", request.getRequestURL().toString(),
                "参数校验失败: " + message);
        return JsonResult.fail(errMsg);
    }

    @ExceptionHandler(value = HttpException.class)
    public JsonResult httpExceptionHandler(HttpServletRequest request, HttpException e) {
        return JsonResult.fail(e.getCode(), e.getMessage());
    }

    /**
     * 非法参数异常
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public JsonResult illegalArgumentExceptionHandler(HttpServletRequest request,
            IllegalArgumentException e) {
        return JsonResult.fail(e.getMessage());
    }

    /**
     * 参数缺失异常
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public JsonResult missingServletRequestParameterExceptionHandler(HttpServletRequest request,
            MissingServletRequestParameterException e) {
        return JsonResult.fail("缺少请求参数:" + e.getParameterName());
    }

    /**
     * Token校验失败异常
     * @param request
     * @param e
     * @return
     */
    @ExceptionHandler(value = TokenException.class)
    public JsonResult tokenExceptionHandler(HttpServletRequest request, TokenException e) {
        return JsonResult.fail(e.getCode(), e.getMessage());
    }

    /**
     * 权限认证异常
     */
    @ExceptionHandler(value = AuthenticationException.class)
    public JsonResult authenticationExceptionHandler(HttpServletRequest request,
            AuthenticationException e) {
        return JsonResult.fail(e.getCode(), e.getMessage());
    }

    /**
     * 抛出通用异常
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(value = CommonException.class)
    public JsonResult commonExceptionHandler(CommonException e, HttpServletRequest request) {
        return JsonResult.fail(e.getCode(), e.getMessage());
    }

    /**
     * 参数解析异常
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(value = ParseException.class)
    public JsonResult parseExceptionHandler(ParseException e, HttpServletRequest request) {
        return JsonResult.fail(e.getMessage());
    }

    /**
     * 业务异常处理
     * @param e
     * @param request
     * @return
     */
    @ExceptionHandler(value = BizException.class)
    public JsonResult bizExceptionHandler(BizException e, HttpServletRequest request) {
        return JsonResult.fail(e.getCode(), e.getMessage());
    }
}

3.3 封装返回结果示例

/**
 * 新增商品类别信息
 *
 * @param category
 * @return
 */
@PostMapping("save")
public JsonResult save(@RequestBody @Validated Category category) {
    return JsonResult.ok(categoryService.save(category));
}

在上面示例中,我们将返回值简化为了JsonResult.ok(obj)的语法。这样一来,返回的结果就会被 ResponseControllerAdvice进行统一返回。如果只有一个接口需要统一返回结果,那么直接在controller层return JsonResult.ok(obj)就可以,如果有多个接口需要统一返回,每个接口都写一遍就显得复杂冗余。将所有返回统一到一个单独的Controller中,等待SpringMVC拦截响应再进行统一输出。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Springboot项目异常处理及返回结果统一 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • Java Springboot全局异常处理

    Java Spring Boot 是一个快速开发框架,可以帮助我们快速构建稳定高效的应用程序。在开发应用程序时,往往需要处理一些在运行期间可能发生的异常错误。为了使应用程序更加健壮与可靠,我们需要进行全局异常处理。 一、为什么需要全局异常处理 全局异常处理在应用中非常重要,主要有以下几个原因: 增强用户体验:当应用程序出现异常时,我们可以通过全局异常处理机制…

    Java 2023年5月19日
    00
  • eclipse 中的javac命令与java命令

    针对“eclipse 中的javac命令与java命令”的详细解释和完整攻略,下面是我的回答: 1. 什么是javac命令 javac命令是Java编译器,用于将Java代码编译成Java字节码。在eclipse中,可以通过在项目中编写Java代码后,点击“编译”按钮(位于工具栏中),或通过点击菜单栏中的“项目” > “编译”来使用javac命令。 2…

    Java 2023年5月19日
    00
  • Nacos源码之注册中心的实现详解

    Nacos源码之注册中心的实现详解 Nacos 是一个开源的分布式系统服务发现、配置管理和服务管理平台,具有高度可扩展性和强一致性。 在 Nacos 中,注册中心是其核心组件之一,本文将详细讲解 Nacos 的注册中心实现原理及其源码解析。 注册中心的作用 在分布式系统中,服务提供者需要将自己的服务注册到注册中心,以便服务消费者可以通过注册中心获取服务提供者…

    Java 2023年6月15日
    00
  • Spring Security 安全认证的示例代码

    关于 Spring Security 安全认证示例代码的完整攻略,我将按照以下步骤来讲解: 系统需求 Spring Security 简介 Spring Security 安全认证的示例代码 示例代码的详细解释 示例的运行方式 附加示例 1. 系统需求 首先,你需要确保你的系统已经安装了以下环境: Java 1.8+; Maven; Eclipse 或者 I…

    Java 2023年5月20日
    00
  • 关于jsp版ueditor1.2.5的部分问题解决(上传图片失败)

    关于jsp版ueditor1.2.5的部分问题解决(上传图片失败)攻略可以按照以下步骤进行: 1. 修改配置文件 打开ueditor.config.js文件,将serverUrl修改为你后端处理上传请求的路径。例如: window.UEDITOR_CONFIG = { …, serverUrl: ‘uploadImage.jsp’ } 其中,upload…

    Java 2023年5月20日
    00
  • JSP中 Session和作用域的使用

    下面是关于“JSP中 Session和作用域的使用”的完整攻略。 什么是Session和作用域 在JSP中,”作用域(Scope)”是指在某个特定的范围内,程序可以访问到的变量。JSP中的作用域是从大到小,依次为:application、session、request和page。 其中,”Session”就是 Session 作用域,代表一个用户会话过程,当…

    Java 2023年6月15日
    00
  • Java超详细讲解WebMvcConfigurer拦截器

    下面是关于“Java超详细讲解WebMvcConfigurer拦截器”的完整攻略,包含两个示例说明。 Java超详细讲解WebMvcConfigurer拦截器 在Spring MVC中,我们可以使用拦截器来拦截请求并进行一些处理。WebMvcConfigurer是一个接口,它提供了一些方法来配置Spring MVC的行为,其中包括添加拦截器。本文将详细讲解W…

    Java 2023年5月17日
    00
  • java中JDBC实现往MySQL插入百万级数据的实例代码

    我将为你详细介绍Java中JDBC实现往MySQL插入百万级数据的攻略,包括以下内容: JDBC简介 JDBC连接MySQL数据库的步骤 插入百万级数据的实现步骤 两条示例 1. JDBC简介 JDBC(Java Database Connectivity)是Java平台中用于执行SQL语句的一组API。使用JDBC可以连接各种各样的关系型数据库,如MySQ…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部