spring项目自定义全局响应处理器,统一处理响应结果

实现方式

使用@ControllerAdvice注解和实现ResponseBodyAdvice接口自定义全局响应处理器

实现步骤

  • 自定义统一返回类

定义统一返回类,包装返回结果

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)//过滤null,提高性能
@ApiModel(value = "返回类")
public class Wrapper<T> implements Serializable {

	/**
	 * 成功码
	 */
	public static final int SUCCESS_CODE = 200;

	/**
	 * 成功信息
	 */
	public static final String SUCCESS_MESSAGE = "操作成功";

	/**
	 * 错误码
	 */
	public static final int ERROR_CODE = 500;

	/**
	 * 错误信息
	 */
	public static final String ERROR_MESSAGE = "内部异常";

	/**
	 * 编号
	 */
	@ApiModelProperty("编号")
	private int code;

	/**
	 * 信息
	 */
	@ApiModelProperty("信息")
	private String message;

	/**
	 * 结果数据
	 */
	@ApiModelProperty("结果数据")
	private T result;

	/** 为什么使用this替代new类名
	 * 代码简洁:使用 this 可以使得代码更加简洁,因为你不需要每次都重复使用类的名称。
	 * 明确性:通过使用 this,你清楚地表明你正在调用当前类的另一个构造函数或方法,而不是其他类的构造函数或方法。
	 * 减少重复:在多构造函数的类中,如果每个构造函数都需要设置相同的属性,那么使用 this 可以避免重复代码。
	 * 提高可读性:当一个构造函数调用了另一个构造函数时,使用 this 可以让读者更容易理解正在发生的事情,尤其是当构造函数的参数不同,但都包含某些共同参数时。
	 */
	//默认构造函数,它直接调用第二个构造函数,并传递 SUCCESS_CODE 和 SUCCESS_MESSAGE 作为参数。
	Wrapper() {
		this(SUCCESS_CODE, SUCCESS_MESSAGE);
	}
	//不需要返回数据 带有两个参数的构造函数,它调用第三个构造函数,并传递相同的参数。
	Wrapper(int code, String message) {
		this(code, message, null);
	}
	//需要返回数据
	Wrapper(int code, String message, T result) {
		super();
		this.code(code).message(message).result(result);
	}

	private Wrapper<T> code(int code) {
		this.setCode(code);
		return this;
	}

	private Wrapper<T> message(String message) {
		this.setMessage(message);
		return this;
	}

	public Wrapper<T> result(T result) {
		this.setResult(result);
		return this;
	}

	@JsonIgnore
	public boolean success() {
		return Wrapper.SUCCESS_CODE == this.code;
	}

	@JsonIgnore
	public boolean error() {
		return !success();
	}

}

  • 定义 统一返回包装类
public class WrapMapper {
    /**
     * 在 `WrapMapper` 类中,私有构造函数的设计是为了防止外部实例化这个类。这是一个常见的做法,有以下几个原因:
     * 1. **单一职责原则**:`WrapMapper` 类被设计为一个工具类,只提供一系列静态方法,用于创建和处理 `Wrapper` 对象。它不包含任何实例变量,因此它没有必要被实例化。
     * 2. **减少依赖**:如果 `WrapMapper` 类可以被实例化,那么任何使用这个类的代码都需要导入这个类的引用。通过将构造函数设为私有,你可以限制它的使用,只允许通过静态方法来使用这个类。
     * 3. **提高效率**:工具类通常不需要创建多个实例,因为它们不依赖于外部状态,而且它们的操作通常可以通过静态方法完成。因此,设计为不可实例化可以提高效率。
     * 4. **清晰意图**:通过将构造函数设为私有,明确地表明这个类不应该被实例化,这有助于其他开发者理解这个类的用途和设计意图。
     * 总之,将 `WrapMapper` 类的构造函数设为私有是为了遵循单一职责原则,减少依赖,提高效率,并提高代码的可读性和可维护性。这样的设计有助于确保 `WrapMapper` 类只作为工具类被使用,而不被误用或滥用。
     */
    private WrapMapper() {
    }

	public static <E> Wrapper<E> wrap(int code) {
		return wrap(code, null);
	}

	public static <E> Wrapper<E> wrap(int code, String message) {
		return wrap(code, message, null);
	}

    public static <E> Wrapper<E> wrap(int code, String message, E o) {
        return new Wrapper<>(code, message, o);
    }

    public static <E> Wrapper<E> wrap(Exception e) {
        return new Wrapper<>(Wrapper.ERROR_CODE, e.getMessage());
    }

    public static <E> E unWrap(Wrapper<E> wrapper) {
        return wrapper.getResult();
    }

    public static <E> Wrapper<E> error() {
        return wrap(Wrapper.ERROR_CODE, Wrapper.ERROR_MESSAGE);
    }

    public static <E> Wrapper<E> error(int code,String message) {
        return wrap(code, message);
    }

    public static <E> Wrapper<E> error(String message) {
        return wrap(Wrapper.ERROR_CODE, StringUtils.isBlank(message) ? Wrapper.ERROR_MESSAGE : message);
    }

    public static <E> Wrapper<E> ok() {
        return new Wrapper<>();
    }

    public static <E> Wrapper<E> ok(E o) {
        return new Wrapper<>(Wrapper.SUCCESS_CODE, Wrapper.SUCCESS_MESSAGE, o);
    }
}
  • 定义启用全局响应注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EnableResponseHandler {

}

  • 定义忽略全局响应注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreResponseHandler {

}

  • 定义全局响应处理器
//@Component标记的类,Spring 容器会自动扫描这个类,并将它作为一个 bean 创建和注册到 Spring 容器中。
//可以被其他类通过 @Autowired 注解自动装配,你不需要显式地定义 bean 的依赖关系,Spring 容器会自动处理。
@Component
@ControllerAdvice//全局控制器增强
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> {
	
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        if (methodParameter.getMethod().isAnnotationPresent(IgnoreResponseHandler.class)) {
            return false;
        }
        //只有EnableResponseHandler注解标识的类才会去调用beforeBodyWrite方法
        if (methodParameter.getMethod().isAnnotationPresent(EnableResponseHandler.class)) {
            return true;
        }
        if (methodParameter.getDeclaringClass().isAnnotationPresent(EnableResponseHandler.class)) {
            return true;
        }
        return false;
    }
	/**
	*beforeBodyWrite方法在 Spring MVC 将返回的对象写入 HTTP 响应之前被调用,它提供了一个机会来增强或修改响应体。
	*	作用
	*	1.增强响应:在返回对象被写入响应之前,允许你对响应进行增强或修改。
	*	自定义格式化:如果你需要对返回的对象进行特殊的格式化,比如添加额外的头信息,或者修改对象的属性,beforeBodyWrite 提供了这种能力。
	*	全局应用:你可以定义多个 ResponseBodyAdvice 实现类,并将它们应用于整个应用程序,或者针对特定的 Controller 或请求类型进行过滤。
	*/
    @Nullable
    @Override
    public Object beforeBodyWrite(@Nullable Object o,
                                  MethodParameter methodParameter,
                                  MediaType mediaType,
                                  Class<? extends HttpMessageConverter<?>> aClass,
                                  ServerHttpRequest serverHttpRequest,
                                  ServerHttpResponse serverHttpResponse) {

        //如果返回的不是自己定义的包装类
        if (o instanceof Wrapper) {
            return o;
        }
        //使用WrapMapper包装后返回
        return WrapMapper.ok(o);
    }

}

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在Spring Cloud中,我们可以通过自定义全局异常处理器处理应用程序中的所有异常。以下是实现全局异常处理器的步骤: 1. 创建一个全局异常处理器类,该类应该实现Spring的ErrorController接口。 2. 在处理器类中,使用@RequestMapping注解来定义处理所有错误请求的路由。 3. 在路由方法中,获取请求中的异常信息,并根据异常类型返回相应的错误响应。 4. 在应用程序的配置文件中,将Spring的默认错误处理器禁用,并将全局异常处理器类注册为错误处理器。 以下是一个简单的全局异常处理器示例: ``` @RestController @ControllerAdvice public class GlobalExceptionHandler implements ErrorController { @RequestMapping("/error") public ResponseEntity<ErrorResponse> handleAllExceptions(HttpServletRequest request) { ErrorResponse errorResponse = new ErrorResponse(); errorResponse.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); errorResponse.setErrorMessage("An error occurred during the request."); errorResponse.setRequestedURI(request.getRequestURI()); return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); } @Override public String getErrorPath() { return "/error"; } } ``` 在上面的代码中,我们实现Spring的ErrorController接口,并使用@ControllerAdvice注解来指定该类为全局异常处理器。在handleAllExceptions方法中,我们获取请求中的异常信息,并根据异常类型返回相应的错误响应。最后,我们将该类注册为错误处理器,并将Spring的默认错误处理器禁用。 ### 回答2: Spring Cloud是一个用于构建微服务架构的框架,它提供了许多功能和组件来简化微服务的开发和管理。其中之一就是全局异常处理器全局异常处理器是一个用于捕获和处理应用程序中发生的异常的组件。在微服务架构中,由于各个服务之间的调用和交互,很可能会出现许多不同种类的异常,例如网络异常、数据库异常、业务异常等。而全局异常处理器的作用就是捕获这些异常,并根据具体情况进行统一处理。 使用Spring Cloud的全局异常处理器,可以帮助我们实现以下功能: 1. 统一异常处理:无论是哪个服务发生了异常,全局异常处理器都能捕获并进行处理,避免异常导致系统崩溃或无响应。 2. 异常信息返回:全局异常处理器可以将捕获到的异常信息封装成特定的响应格式,方便客户端或其他服务进行处理。 3. 异常分类处理:根据异常的类型和来源,全局异常处理器可以将异常分类处理,例如数据库异常可以跳转到指定的错误页面,业务异常可以返回特定的错误码等。 4. 日志记录:全局异常处理器可以将捕获到的异常信息进行日志记录,方便开发人员进行问题排查和分析。 总之,Spring Cloud的全局异常处理器是一个非常实用的组件,能够帮助我们捕获和处理微服务架构中的异常,并保证系统的稳定性和可靠性。通过合理配置和使用全局异常处理器,我们可以更好地管理和维护我们的微服务应用程序。 ### 回答3: Spring Cloud全局异常处理器是用来统一处理系统中出现的异常情况。在微服务架构中,由于系统由多个服务组成,每个服务都可能出现异常,如果每个服务都单独处理异常,会造成代码冗余和维护困难。因此,引入全局异常处理器可以统一处理所有服务的异常,提高代码的可维护性和可读性。 Spring Cloud全局异常处理器的工作原理如下:首先,在服务启动时,通过配置文件或代码,将异常处理器注册到Spring容器中。当服务中发生异常时,Spring容器会捕获到异常,并根据异常类型和处理器的配置,将异常交给对应的处理器进行处理处理器可以通过捕获异常的类型来判断异常的种类,并根据不同的异常类型进行不同的处理,例如返回给前端用户友好的错误信息、记录异常日志等。 使用全局异常处理器的好处如下:首先,可以减少代码的冗余,不需要在每个服务中都编写相同的异常处理代码;其次,可以提高代码的可读性,将异常处理的逻辑集中在一个地方,便于理解和维护;还可以提高系统的容错性和稳定性,可以捕获并处理各种异常情况,避免系统因为异常导致崩溃或无法正常运行。 总结而言,Spring Cloud全局异常处理器是一个集中处理系统中异常情况的机制,能够统一处理微服务架构中各个服务的异常,提高代码的可维护性和系统的容错性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值