最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Spring實(shí)現(xiàn)自定義錯誤信息返回詳解

 更新時(shí)間:2025年03月20日 14:45:28   作者:夢想歌  
這篇文章主要為大家詳細(xì)介紹了如何基于Spring實(shí)現(xiàn)自定義錯誤信息返回效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

背景

Spring 提供了 @RestControllerAdvice 用來實(shí)現(xiàn) HTTP 協(xié)議的全局異常處理。在異常信息的處理上通常只返回特定的 Response 對象,如下。

@Slf4j
@RestControllerAdvice
public class RestExceptionResolver {

	@ExceptionHandler(Exception.class)
	public ResponseEntity<?> processException(Exception ex) {
		BodyBuilder builder;
		Response response;
		ResponseStatus responseStatus =
			AnnotationUtils.findAnnotation(ex.getClass(), ResponseStatus.class);
		if (responseStatus != null) {
			builder = ResponseEntity.status(responseStatus.value());
			response = Response.buildFailure("500", responseStatus.reason());
		} else {
			builder = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
			response = Response.buildFailure("500", ex.getMessage());
		}
		this.process(ex, response);
		return builder.body(response);
	}
}

作為基礎(chǔ)框架,筆者就遇到項(xiàng)目A 要求返回 Response1 對象,項(xiàng)目B 要求返回 Response2 對象,這個時(shí)候,適配起來就很痛苦,例如下方的代碼。

@Slf4j
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper = true)
@Data
public class Response extends DTO {

	private static final long serialVersionUID = 1L;

	private boolean success;

	private String errCode; // 項(xiàng)目A 要求錯誤碼是字符型

	private String errMessage; // 項(xiàng)目A 要求用這個名字

	private int code; // 項(xiàng)目B 要求錯誤碼是整型

	private String message; // 項(xiàng)目B 要求用這個名字
}

另外,@RestControllerAdvice 只適用于 Web 異常捕獲,我們還要考慮其他組件的情況,例如 Dubbo 捕獲 RPC 異常、Sentinel 組件觸發(fā)限流、Spring Security 安全框架拋出認(rèn)證異常。

目標(biāo)

不需要修改基礎(chǔ)框架,允許業(yè)務(wù)方自行擴(kuò)展異常返回對象。

實(shí)現(xiàn)

Response 提煉為 Builder 模式,改為 ResponseBuilder.builder() 構(gòu)建返回對象。

@Slf4j
@RestControllerAdvice
public class RestExceptionHandler {

	@ExceptionHandler(Exception.class)
	public ResponseEntity<?> resolveException(Exception ex) {
		BodyBuilder builder;
		Object response;
		ResponseStatus status = AnnotationUtils.findAnnotation(ex.getClass(), ResponseStatus.class);
		if (status != null) {
			builder = ResponseEntity.status(status.value());
			response = ResponseBuilder.builder().buildFailure("500", status.reason());
		} else {
			builder = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
			response = ResponseBuilder.builder().buildFailure("500", ex.getMessage());
		}
		this.postProcess(ex);
		return builder.body(response);
	}
}

public interface ResponseBuilder<T> {

	static ResponseBuilder<?> builder() {
		// 嘗試從業(yè)務(wù)項(xiàng)目獲取自定義的 Spring Bean
		ResponseBuilder<?> builder = ApplicationContextHelper.getBean(ResponseBuilder.class);
		if (builder != null) {
			return builder;
		}
		// 如果業(yè)務(wù)項(xiàng)目沒有自定義 Bean,返回默認(rèn)的 Builder
		return DefalutResponseBuilder.getInstance();
	}

	T buildSuccess();

	<Body> T buildSuccess(Body data);

	T buildFailure(String errCode, String errMessage, Object... params);
}

public class DefalutResponseBuilder implements ResponseBuilder<Response> {

    private static final DefaultResponseBuilder INSTANCE = new DefaultResponseBuilder();

    private DefaultResponseBuilder() {}

    public static DefaultResponseBuilder getInstance() {
        return INSTANCE;
    }

	@Override
	public Response buildSuccess() {
		Response response = new Response();
		response.setSuccess(true);
		return response;
	}

	@Override
	public <Body> Response buildSuccess(Body data) {
		SingleResponse<Body> response = new SingleResponse<>();
		response.setSuccess(true);
		response.setData(data);
		return response;
	}

	@Override
	public Response buildFailure(String errCode, String errMessage, Object... params) {
		Response response = new Response();
		response.setSuccess(false);
		response.setErrCode(errCode);
		response.setErrMessage(MessageFormatter.arrayFormat(message, placeholders).getMessage());
		return response;
	}
}

@Slf4j
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper = true)
@Data
public class Response extends DTO {

	private static final long serialVersionUID = 1L;

	private boolean success;

	private String errCode;

	private String errMessage;
}

業(yè)務(wù)方覺得 Response 不能滿足需求,重新定義了新對象,如下。

@Slf4j
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper = true)
@Data
public class CustomResponse {

	private static final long serialVersionUID = 1L;

	private boolean success;

	private int code; // 要求錯誤碼是整型

	private String message; // 前端要求用這個名字
}

創(chuàng)建 CustomResponseBuilder 包裝 CustomResponse 對象,并標(biāo)記 @Component 注解,放入 Spring Bean 管理。

@Component
public class CustomResponseBuilder implements ResponseBuilder<CustomResponse> {

	@Override
	public CustomResponse buildSuccess() {
		CustomResponse response = new CustomResponse();
		response.setSuccess(true);
		return response;
	}

	@Override
	public <Body> CustomResponse buildSuccess(Body data) {
		// 略
	}

	@Override
	public CustomResponse buildFailure(int code, String message, Object... params) {
		CustomResponse response = new CustomResponse();
		response.setSuccess(false);
		response.setCode(code);
		response.setMessage(MessageFormatter.arrayFormat(message, placeholders).getMessage());
		return response;
	}
}

上述已提到 ResponseBuilder.builder() 優(yōu)先查找 Spring Bean,所以 CustomResponseBuilder 覆蓋了框架內(nèi)置的 DefaultResponseBuilder 類,全局異常捕獲器返回結(jié)果時(shí),就能返回業(yè)務(wù)方自定義的 CustomResponse 對象,這樣,不需要改動框架,就能滿足業(yè)務(wù)需求。

產(chǎn)出

根據(jù)這個思路,我們分別實(shí)現(xiàn)了 Web 異常、Dubbo 異常、Sentinel 限流、Security 認(rèn)證等各種場景的異常處理機(jī)制,業(yè)務(wù)方只需要自行創(chuàng)建 ResponseBuilder 擴(kuò)展自己的返回對象即可,不需要修改框架。

到此這篇關(guān)于基于Spring實(shí)現(xiàn)自定義錯誤信息返回詳解的文章就介紹到這了,更多相關(guān)Spring自定義錯誤信息內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

微博| 徐水县| 巴塘县| 定结县| 武清区| 鸡东县| 广丰县| 深圳市| 瑞金市| 卢氏县| 邹城市| 永州市| 屏南县| 榆树市| 淮南市| 琼结县| 永嘉县| 定结县| 姜堰市| 贵德县| 包头市| 正蓝旗| 丘北县| 军事| 沙湾县| 繁峙县| 安泽县| 平阴县| 镇康县| 广河县| 大方县| 汉沽区| 红桥区| 满城县| 子洲县| 集安市| 濉溪县| 满洲里市| 金川县| 右玉县| 克拉玛依市|