當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
Spring Cloud的全局封装实践
生活随笔
收集整理的這篇文章主要介紹了
Spring Cloud的全局封装实践
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
跨應用的全局封裝通過模仿java的異常拋出實現,通過各個服務使用相同的接口返回格式實現服務消息的傳遞,在規范化的同時快速定位真正出現問題的服務。
全局接口返回格式分為外部接口格式和內部接口格式,這里簡化為內外接口格式一致。
整體流程如下:
全局返回封裝類
整個spring cloud服務的統一接口
public class ResponseResult<T> implements Serializable {/****/private static final long serialVersionUID = 1679552421651455773L;private int status; //狀態碼,根據服務實際需求自定義private String msg;private T data;private String url; //請求的urlprivate Long host; //出現問題的根服務public static ResponseResult ok(Object data, String url) {return new ResponseResult(ResponseStatusCode.OK, data, url, null);}public static ResponseResult ok(String msg, Object data, String url) {return new ResponseResult(ResponseStatusCode.OK, msg, data, url, null);}public static ResponseResult ok(String msg, String url) {return new ResponseResult(ResponseStatusCode.OK, msg, null, url, null);}public static ResponseResult fail(int status, String msg, String url, Long host) {return new ResponseResult(status, msg, url, host);}public ResponseResult() {}public ResponseResult(String msg, T data, String url, Long host) {this.msg = msg;this.data = data;this.url = url;this.host = host;}public ResponseResult(int status, String msg, String url, Long host) {this.status = status;this.msg = msg;this.url = url;this.host = host;}public ResponseResult(int status, T data, String url, Long host) {this.status = status;this.data = data;this.url = url;this.host = host;}public ResponseResult(int status, String msg, T data, String url, Long host) {this.status = status;this.msg = msg;this.data = data;this.url = url;this.host = host;}public ResponseResult(int status, String msg, T data, Long host) {this.status = status;this.msg = msg;this.data = data;this.host = host;}public int getStatus() {return status;}public void setStatus(int status) {this.status = status;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public T getData() {return data;}public void setData(T data) {this.data = data;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public Long getHost() {return host;}public void setHost(Long host) {this.host = host;} }狀態碼常量類
這個類為整體服務定義的狀態碼,可以使用枚舉實現
public class ResponseStatusCode {/*** OK*/public static final int OK = 0;/*** 未知異常*/public static final int UNKNOW_EXCEPTION = 100;/*** 參數異常*/public static final int ARGUMENT_EXCEPTION = 104;/*** 自定義異常*/public static final int ARGUMENT_EXCEPTION = XXX; }自定義異常類
自定義異常類繼承RuntimeException
public class CustomException extends RuntimeException{public static final long serialVersionUID = 1L;private int status;private Long host;public CustomException(int status) {this.status = status;}/*** 拋出異常使用自定義的異常碼* @param status 自定義異常碼* @param message 異常信息*/public CustomException(int status, String message) {super(message);this.status = status;}public CustomException(String message, Throwable cause, int status) {super(message, cause);this.status = status;}public CustomException(Throwable cause, int status) {super(cause);this.status = status;}public CustomException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, int status) {super(message, cause, enableSuppression, writableStackTrace);this.status = status;}public CustomException(int status, Long host) {this.status = status;this.host = host;}/*** 拋出異常使用自定義的異常碼* @param status 自定義異常碼* @param message 異常信息* @param host 主機*/public CustomException(int status, String message, Long host) {super(message);this.status = status;this.host = host;}public CustomException(String message, Throwable cause, int status, Long host) {super(message, cause);this.status = status;this.host = host;}public CustomException(Throwable cause, int status, Long host) {super(cause);this.status = status;this.host = host;}public CustomException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, int status, Long host) {super(message, cause, enableSuppression, writableStackTrace);this.status = status;this.host = host;}public int getStatus() {return status;}public void setStatus(int status) {this.status = status;}public Long getHost() {return host;}public void setHost(Long host) {this.host = host;} }接口全局響應處理類
使用spring自帶controller響應處理類,使用全局封裝類封裝返回
@ControllerAdvice public class CustomResponseAdivce implements ResponseBodyAdvice<Object> {// 這個方法表示對于哪些請求要執行beforeBodyWrite,返回true執行,返回false不執行@Overridepublic boolean supports(MethodParameter methodParameter, Class aClass) {return true;}// 對于返回的對象如果不是最終對象ResponseResult,則選包裝一下@Overridepublic Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass,ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {ServletServerHttpRequest servletServerHttpRequest = (ServletServerHttpRequest) serverHttpRequest;String url = servletServerHttpRequest.getServletRequest().getRequestURL().toString();if (!(o instanceof ResponseResult)) {ResponseResult responseResult = null;// 因為handler處理類的返回類型是String,為了保證一致性,這里需要將ResponseResult轉回去if (o instanceof String) {responseResult = ResponseResult.ok(o, url);ObjectMapper mapper = new ObjectMapper();String responseString = "";try {responseString = mapper.writeValueAsString(responseResult);} catch (JsonProcessingException e) {e.printStackTrace();}return responseString;}else {responseResult = ResponseResult.ok(o, url);return responseResult;}}return o;}}異常處理類
業務中通過拋出異常的方式來處理錯誤,在此處可以全局處理
@RestControllerAdvice public class ExceptionAdvice {private Logger logger = LoggerFactory.getLogger(this.getClass());/*** 出錯服務端口*/@Value("${server.port}")private int servicePort;/*** 封裝異常** @param req 請求* @param e 異常類* @return 返回封裝類*/@ExceptionHandler(value = Exception.class)public ResponseResult jsonErrorHandler(HttpServletRequest req, Exception e) {logger.error(req.getRequestURL().toString(), e);Long host = null;//分配異常碼與hostint status = ResponseStatusCode.UNKNOW_EXCEPTION;String msg = e.getMessage();if (e instanceof IOException || e instanceof CustomIOException) {status = ResponseStatusCode.IO_EXCEPTION;if (e instanceof CustomIOException){host = ((CustomIOException) e).getHost();}} else if (e instanceof NullPointerException || e instanceof CustomNullPointerException) {status = ResponseStatusCode.NULL_EXCEPTION;if (e instanceof CustomNullPointerException){host = ((CustomNullPointerException) e).getHost();}} else if (e instanceof SQLException || e instanceof CustomSQLException) {status = ResponseStatusCode.SQL_EXCEPTION;if (e instanceof CustomSQLException){host = ((CustomSQLException) e).getHost();}} else if (e instanceof ArgumentException) {status = ResponseStatusCode.ARGUMENT_EXCEPTION;if (((ArgumentException) e).getHost() != null && !((ArgumentException) e).getHost().equals(0)){host = ((ArgumentException) e).getHost();}} else if (e instanceof CustomException) {status = ((CustomException) e).getStatus();if (((CustomException) e).getHost() != null && !((CustomException) e).getHost().equals(0)){host = ((CustomException) e).getHost();}} else if (e instanceof UndeclaredThrowableException) {Throwable targetEx = ((UndeclaredThrowableException) e).getUndeclaredThrowable();if (targetEx != null) {msg = targetEx.getMessage();}}//獲取出錯服務ipint ip = 0;try {ip = Integer.valueOf(Arrays.stream(InetAddress.getLocalHost().getHostAddress().split("\\.")).collect(Collectors.joining()));} catch (Exception e1) {}return ResponseResult.fail(status, msg, req.getRequestURL().toString(),host == null? Long.valueOf(String.valueOf(ip) + servicePort): host);}}接口響應處理類
上游服務獲得下游服務的響應的處理類
public class ResponseHandler<T> {/*** 處理調用遠程接口的返回* @param responseResult* @return*/public T handler(ResponseResult<?> responseResult) {int statusToken = responseResult.getStatus();String msg = responseResult.getMsg();Long host = responseResult.getHost();if (ResponseStatusCode.OK != statusToken){exceptionHandler(statusToken,msg, host);}return (T) responseResult.getData();}/*** 處理異常* @param statusToken 狀態碼* @param msg 錯誤消息* @param host 主機*/private static void exceptionHandler(int statusToken, String msg, Long host) {if (ResponseStatusCode.IO_EXCEPTION == statusToken) {throw new CustomIOException(msg, host);} else if (ResponseStatusCode.NULL_EXCEPTION== statusToken) {throw new CustomNullPointerException(msg, host);} else if (ResponseStatusCode.SQL_EXCEPTION== statusToken) {throw new CustomSQLException(msg, host);} else if (ResponseStatusCode.ARGUMENT_EXCEPTION== statusToken) {throw new ArgumentException(msg, host);} else if (ResponseStatusCode.UNKNOW_EXCEPTION== statusToken) {throw new UnknowException(msg, host);} else {throw new CustomException(statusToken, msg, host);}} }接口例子
上面是所有服務都需要擁有的類,然后是幾個調用的小例子
首先是幾個接口
@RestController @RefreshScope public class DcController {finalClientService clientService;@Autowiredpublic DcController(ClientService clientService) {this.clientService = clientService;}@GetMapping("exception1")public String exception1() {throw new ArgumentException("錯誤");}@GetMapping("exception2")public int exception2() {throw new CustomException(250, "業務異常,自定義異常碼");}@GetMapping("exception3")public int exception3(){return new ResponseHandler<List<MetaVO>>().handler(clientService.generateList()).get(0).getDbid();}@GetMapping("list")public List<MetaVO> generateList() {List<MetaVO> list = new ArrayList<>();for (int i = 0; i < 2; i++) {MetaVO metaVO = new MetaVO();metaVO.setDbid(i);list.add(metaVO);}return list;}}然后是結果
總結
以上就是spring cloud的全局封裝實踐,開發人員編寫業務邏輯不需要考慮返回的封裝,只需要考慮業務和自定義的狀態碼而已
總結
以上是生活随笔為你收集整理的Spring Cloud的全局封装实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C#oop
- 下一篇: 01-将自己的Ubuntu电脑设置为一台