具体实现
1 定义结果状态信息
项目中我们会将接口返回的数据封装成Json数据格式,一般我们会将所有接口的数据格式统一, 使前端(iOS Android, Web)对数据的操作更一致、轻松。一般情况下,统一返回数据格式没有固定的格式,只要能描述清楚返回的数据状态以及要返回的具体数据就可以。但是一般会包含状态码、返回消息、数据这几部分内容。
所以我们需要创建统一返回结果状态信息的枚举类
当然,这个是每个项目不同的,需要实际情况实际分析!!!!
package com.atguigu.ssyx.common.result;
import lombok.Data;
import lombok.Getter;
/**
* 统一返回结果状态信息类
*
*/
@Getter
public enum ResultCodeEnum {
SUCCESS(200,"成功"),
FAIL(201, "失败"),
SERVICE_ERROR(2012, "服务异常"),
DATA_ERROR(204, "数据异常"),
ILLEGAL_REQUEST(205, "非法请求"),
REPEAT_SUBMIT(206, "重复提交"),
LOGIN_AUTH(208, "未登陆"),
PERMISSION(209, "没有权限"),
ORDER_PRICE_ERROR(210, "订单商品价格变化"),
ORDER_STOCK_FALL(204, "订单库存锁定失败"),
CREATE_ORDER_FAIL(210, "创建订单失败"),
COUPON_GET(220, "优惠券已经领取"),
COUPON_LIMIT_GET(221, "优惠券已发放完毕"),
URL_ENCODE_ERROR( 216, "URL编码失败"),
ILLEGAL_CALLBACK_REQUEST_ERROR( 217, "非法回调请求"),
FETCH_ACCESSTOKEN_FAILD( 218, "获取accessToken失败"),
FETCH_USERINFO_ERROR( 219, "获取用户信息失败"),
SKU_LIMIT_ERROR(230, "购买个数不能大于限购个数"),
REGION_OPEN(240, "该区域已开通"),
REGION_NO_OPEN(240, "该区域未开通"),
;
private Integer code;
private String message;
private ResultCodeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}
2 创建统一返回结果类
这里我们封装了要返回结果都所有信息,包括状态值code,状态信息message,以及数据data
package com.atguigu.ssyx.common.result;
import lombok.Data;
@Data
public class Result<T> {
//状态码
private Integer code;
//信息
private String message;
//数据
private T data;
//构造私有化
private Result() { }
//设置数据,返回对象的方法
public static<T> Result<T> build(T data,ResultCodeEnum resultCodeEnum) {
//创建Resullt对象,设置值,返回对象
Result<T> result = new Result<>();
//判断返回结果中是否需要数据
if(data != null) {
//设置数据到result对象
result.setData(data);
}
//设置其他值
result.setCode(resultCodeEnum.getCode());
result.setMessage(resultCodeEnum.getMessage());
//返回设置值之后的对象
return result;
}
//成功的方法
public static<T> Result<T> ok(T data) {
Result<T> result = build(data, ResultCodeEnum.SUCCESS);
return result;
}
//失败的方法
public static<T> Result<T> fail(T data) {
return build(data,ResultCodeEnum.FAIL);
}
}
3 编写统一异常处理类
系统在运行过程中如果出现了异常,默认会直接返回异常信息,比如500错误提示。但是我们想让异常结果也显示为统一的返回结果对象,并且统一处理系统的异常信息,那么需要进行统一异常处理。
3.1 代码
package com.atguigu.ssyx.common.exception;
import com.atguigu.ssyx.common.result.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public Result error(Exception e){
e.printStackTrace();
return Result.fail(null);
}
/**
* 自定义异常处理方法
* @param e
* @return
*/
@ExceptionHandler(SsyxException.class)
@ResponseBody
public Result error(SsyxException e){
return Result.fail(null);
}
}
3.2 具体分析
@ControllerAdvice
@ControllerAdvice
在 Spring 框架中发挥了中心化异常处理的作用。它允许你定义一个或多个全局异常处理器,这些处理器可以捕获和处理应用程序中所有控制器(@Controller
或 @RestController
注解的类)抛出的异常。以下是 @ControllerAdvice
发挥的一些关键作用:
-
集中管理异常处理逻辑:通过在一个地方定义异常处理逻辑,你可以避免在每个控制器中重复相同的代码,这有助于保持代码的整洁和可维护性。
-
统一异常响应格式:你可以定义一个统一的响应格式来处理所有的异常,这有助于客户端更容易地解析和处理错误。
-
减少代码冗余:不需要在每个控制器方法中添加异常处理代码,减少了代码的冗余。
-
提高代码的可重用性:定义的异常处理逻辑可以在多个控制器之间共享,提高了代码的可重用性。
-
增强错误处理的灵活性:你可以根据不同的异常类型定义不同的处理逻辑,甚至可以根据异常的属性(如错误代码或错误消息)来定制响应。
-
支持注解驱动的异常处理:通过使用
@ExceptionHandler
注解,你可以轻松地将特定的异常处理方法与特定的异常类型关联起来。 -
支持条件化配置:你可以使用
basePackages
或basePackageClasses
属性来指定@ControllerAdvice
应该应用于哪些控制器,或者使用@Profile
注解来根据环境条件启用或禁用特定的异常处理器。 -
支持响应体的定制:通过
@ResponseBody
注解,你可以将异常处理方法的返回值直接作为 HTTP 响应体返回,这对于构建 RESTful 服务非常有用。 -
支持异常的转换:你可以将捕获的异常转换为自定义的异常类型,然后由全局异常处理器统一处理,这样可以隐藏内部实现细节,只向客户端暴露必要的错误信息。
-
支持异步处理:在某些情况下,异常处理可能需要执行一些异步操作,
@ControllerAdvice
支持这种场景,使得异常处理更加灵活。
总的来说,@ControllerAdvice
提供了一个强大而灵活的机制,用于集中处理 Spring 应用程序中的异常,从而简化了错误处理逻辑的编写和维护。
@ExceptionHandler
@ExceptionHandler
注解在 Spring 框架中用于指定某个方法用于处理特定的异常类型。当你在 @ControllerAdvice
或 @RestControllerAdvice
注解的类中使用 @ExceptionHandler
注解时,你可以定义一个方法来专门处理被注解指定的异常。
对于 @ExceptionHandler(SsyxException.class)
,这个注解的作用是:
-
指定异常类型:
SsyxException
是一个自定义异常类(假设它已经在你的应用程序中定义)。@ExceptionHandler
注解告诉 Spring,当SsyxException
被抛出时,应该调用标记了这个注解的方法来处理这个异常。 -
异常处理方法:被
@ExceptionHandler(SsyxException.class)
注解的方法将作为处理SsyxException
的处理器。这个方法可以返回一个ResponseEntity
对象,这样就可以自定义响应的状态码、头部信息和响应体。 -
集中处理:通过在
@ControllerAdvice
注解的类中定义@ExceptionHandler
方法,你可以集中处理特定类型的异常,而不是在每个控制器中单独处理。 -
定制响应:你可以在
@ExceptionHandler
方法中定制异常的响应,例如返回错误信息、错误代码或者其他对客户端有用的信息。
4 自定义异常处理
@Data
public class SsyxException extends RuntimeException{
//异常状态码
private Integer code;
/**
* 通过状态码和错误消息创建异常对象
* @param message
* @param code
*/
public SsyxException(String message, Integer code) {
super(message);
this.code = code;
}
/**
* 接收枚举类型对象
* @param resultCodeEnum
*/
public SsyxException(ResultCodeEnum resultCodeEnum) {
super(resultCodeEnum.getMessage());
this.code = resultCodeEnum.getCode();
}
@Override
public String toString() {
return "GuliException{" +
"code=" + code +
", message=" + this.getMessage() +
'}';
}
}