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日

相关文章

  • table中点击表头实现排序的功能示例介绍

    实现table中点击表头实现排序的功能是一个常见的需求,通过JavaScript和jQuery实现非常方便。下面是具体的步骤和代码示例。 1. HTML结构 首先需要在HTML中定义一个table,并将需要进行排序的数据展示在其中。其中,包括表头和表身两个部分。示例代码如下: <table id="myTable"> <…

    Java 2023年6月15日
    00
  • Spring Boot启动流程分析

    我来为您讲解关于“SpringBoot启动流程分析”的完整攻略。 SpringBoot启动流程分析 SpringBoot是基于Spring的一个快速开发新一代Java框架,其简化了Spring应用的开发流程,同时也隐藏了Spring框架配置的复杂性,在不需要过多配置的情况下,实现快速搭建Spring应用。 SpringBoot应用的启动过程可以分为以下几个步…

    Java 2023年5月15日
    00
  • 如何使用Spring integration在Springboot中集成Mqtt详解

    如何使用Spring Integration在Spring Boot中集成MQTT? Spring Integration的Mqtt模块提供了使用Java Mqtt客户端连接到MQTT代理的模板类、消息驱动通道适配器,在Spring Boot应用程序中非常容易集成。下面是使用Spring Integration在Spring Boot中集成MQTT的完整攻略…

    Java 2023年5月20日
    00
  • 详解SpringMVC在IDEA中的第一个程序

    详解SpringMVC在IDEA中的第一个程序 SpringMVC是一种基于Java的Web框架,它可以帮助我们快速地开发Web应用程序。本文将详细介绍如何在IDEA中创建第一个SpringMVC程序,并提供两个示例说明。 步骤1:创建Maven项目 首先,我们需要在IDEA中创建一个Maven项目。在创建项目时,我们需要选择Web应用程序类型,并勾选Spr…

    Java 2023年5月17日
    00
  • spring Data jpa简介_动力节点Java学院整理

    Spring Data JPA简介 什么是Spring Data JPA Spring Data JPA是Spring基于ORM框架JPA的基础上封装的一套JPA应用框架。它简化了基于JPA的数据访问层开发工作,使得我们可以更加专注于业务逻辑的实现。Spring Data JPA提供了一套自动生成JPA API实现代码的机制,这样我们就不用手动编写大量的JP…

    Java 2023年5月20日
    00
  • 分享java打印简单图形的实现代码

    下面是分享Java打印简单图形的实现代码的完整攻略: 准备工作 在开始之前,我们需要进行一些准备工作。首先,我们需要具备一定的Java基础知识,如循环、条件语句、方法的定义和调用等。其次,我们需要了解一些控制台输出相关的知识,如System.out.print()和System.out.println()的使用方法等。 实现代码 下面是Java打印简单图形的…

    Java 2023年5月23日
    00
  • 使用JDBC连接ORACLE的三种URL格式

    使用JDBC连接ORACLE的三种URL格式: 在使用JDBC连接ORACLE时,需要使用相应的JDBC驱动程序,同时也需要正确的连接URL。以下是三种连接ORACLE数据库的URL格式: THIN模式 jdbc:oracle:thin:@[host][:port]:SID 其中,[host]为ORACLE数据库所在的IP地址或主机名;[:port]为数据库…

    Java 2023年6月16日
    00
  • 如何用java计算两个时间相差多少小时

    下面是如何用Java计算两个时间相差多少小时的完整攻略。 步骤 1.获取两个时间对象 Date beginTime = new Date(); // 开始时间 Date endTime = new Date(); // 结束时间 2.将时间对象转换成时间戳 long beginTimestamp = beginTime.getTime(); // 开始时间戳…

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