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中response对象用法实例分析

    Java中Response对象用法实例分析 在Java的Web开发中,Response对象是常用的一个对象。它用于向客户端发送响应信息,同时还可以设置Cookie、Header等信息。本文将介绍Java中Response对象的用法,包括常见的方法和示例说明。 Response对象常用方法 1. 设置响应头信息 使用Response对象的setHeader()…

    Java 2023年5月26日
    00
  • JSP使用JDBC完成动态验证及采用MVC完成数据查询的方法

    JSP使用JDBC完成动态验证及采用MVC完成数据查询的方法 本文将详细讲解如何通过JSP使用JDBC完成动态验证及采用MVC完成数据查询的方法。步骤分为以下几个部分: I. JDBC动态验证 动态验证可以确保用户提供的输入数据是正确的。如果用户提供的数据无法通过验证,应该向用户显示错误消息。JDBC是Java语言访问关系型数据库的标准API。 以下是通过J…

    Java 2023年5月20日
    00
  • 什么是并发收集器?

    并发收集器是Java虚拟机中的一种垃圾收集器,它能够在停顿时间(GC时应用程序暂停)减少的情况下进行垃圾收集。接下来将详细讲解并发收集器的使用攻略。 并发收集器的使用步骤 并发收集器的使用步骤包括如下几个方面: 1. 开启并发收集器 在启动应用程序的时候,加入如下命令来开启并发收集器: -XX:+UseConcMarkSweepGC 2. 配置停顿时间 停顿…

    Java 2023年5月10日
    00
  • java中String,数组,ArrayList三者之间的转换

    对于Java中的String、数组和ArrayList,它们之间的转换是非常常见和实用的操作。下面我将为您提供一份完整攻略: 1. String转数组 将一个字符串转换成字符数组非常简单,只需要使用 String 类的 toCharArray() 方法即可。例如: String str = "Hello, world!"; char[] …

    Java 2023年5月26日
    00
  • 使用SSM+Layui+Bootstrap实现汽车维保系统的示例代码

    下面就为大家介绍如何使用SSM+Layui+Bootstrap实现汽车维保系统的完整攻略。首先,我们将从环境搭建开始,分别介绍SSM框架、Layui和Bootstrap的使用方法和示例。 环境搭建 JDK 1.8及以上 Maven 3.X及以上 Tomcat 8.X及以上 Eclipse集成开发环境 以上环境安装配置完成后,我们就可以开始使用SSM+Layu…

    Java 2023年5月19日
    00
  • SpringBoot整合SpringSecurity实现权限控制之实现多标签页

    下面是“SpringBoot整合SpringSecurity实现权限控制之实现多标签页”的完整攻略: 环境搭建 首先,您需要在本地环境中安装下列软件和工具: JDK 1.8或更高版本 Maven 3.2或更高版本 IntelliJ IDEA或 Eclipse 其次,在pom.xml中添加Spring Security和Thymeleaf依赖: <dep…

    Java 2023年5月20日
    00
  • Springmvc conver实现原理及用法解析

    以下是关于“SpringMVC Converter实现原理及用法解析”的完整攻略,其中包含两个示例。 SpringMVC Converter实现原理及用法解析 SpringMVC Converter是一种用于将请求参数转换为Java对象的机制。在本文中,我们将讲解SpringMVC Converter的实现原理及用法。 Converter实现原理 Sprin…

    Java 2023年5月17日
    00
  • Mybatis中resultMap标签和sql标签的设置方式

    Mybatis是一款优秀的ORM框架,其中resultMap标签和sql标签的设置方式可以让我们更好地管理SQL语句和查询结果的映射关系。下面就详细讲解一下这两个标签的使用方式。 resultMap标签的设置方式 resultMap标签用于定义查询结果和Java对象的映射关系,我们通常可以用它来解决查询表中字段名和Java属性名不完全匹配的情况。result…

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