日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java生鲜电商平台-SpringCloud微服务架构中网络请求性能优化与源码解析

發(fā)布時間:2023/12/13 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java生鲜电商平台-SpringCloud微服务架构中网络请求性能优化与源码解析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Java生鮮電商平臺-SpringCloud微服務(wù)架構(gòu)中網(wǎng)絡(luò)請求性能優(yōu)化與源碼解析

?

說明:Java生鮮電商平臺中,由于服務(wù)進(jìn)行了拆分,很多的業(yè)務(wù)服務(wù)導(dǎo)致了請求的網(wǎng)絡(luò)延遲與性能消耗,對應(yīng)的這些問題,我們應(yīng)該如何進(jìn)行網(wǎng)絡(luò)請求的優(yōu)化與處理呢?

到底有沒有一些好的建議與方案呢?

?

下面這個文章將揭曉上面的問題,讓你對SpringCloud微服務(wù)網(wǎng)絡(luò)請求性能有一個全新的認(rèn)識.

?

目錄簡介

  • 01.網(wǎng)絡(luò)請求異常分類
  • 02.開發(fā)中注意問題
  • 03.原始的處理方式
  • 04.如何減少代碼耦合性
  • 05.異常統(tǒng)一處理步驟
  • 06.完成版代碼展示

01.網(wǎng)絡(luò)請求異常分類

網(wǎng)絡(luò)請求異常大概有哪些?

  • 第一種:訪問接口異常,比如404,500等異常,出現(xiàn)這類異常,Retrofit會自動拋出異常。
  • 第二種:解析數(shù)據(jù)異常,數(shù)據(jù)體發(fā)生變化可能會導(dǎo)致這個問題。
  • 第三種:其他類型異常,比如服務(wù)器響應(yīng)超時異常,鏈接失敗異常,網(wǎng)絡(luò)未連接異常等等。
  • 第四種:網(wǎng)絡(luò)請求成功,但是服務(wù)器定義了異常狀態(tài),比如token失效,參數(shù)傳遞錯誤,或者統(tǒng)一給提示(這個地方比較拗口,比如購物app,你購買n件商品請求接口成功,code為200,但是服務(wù)器發(fā)現(xiàn)沒有這么多商品,這個時候就會給你一個提示,然后客戶端拿到這個進(jìn)行吐司)

02.開發(fā)中注意問題

在獲取數(shù)據(jù)的流程中,訪問接口和解析數(shù)據(jù)時都有可能會出錯,我們可以通過攔截器在這兩層攔截錯誤。

  • 1.在訪問接口時,我們不用設(shè)置攔截器,因為一旦出現(xiàn)錯誤,Retrofit會自動拋出異常。比如,常見請求異常404,500,503等等。為了方便后期排查問題,這個可以在debug環(huán)境下打印日志就可以。
  • 2.在解析數(shù)據(jù)時,我們設(shè)置一個攔截器,判斷Result里面的code是否為成功,如果不成功,則要根據(jù)與服務(wù)器約定好的錯誤碼來拋出對應(yīng)的異常。比如,token失效后跳轉(zhuǎn)登錄頁面,禁用同賬號登陸多臺設(shè)備,缺少參數(shù),參數(shù)傳遞異常等等。
  • 3.除此以外,為了我們要盡量避免在View層對錯誤進(jìn)行判斷,處理,我們必須還要設(shè)置一個攔截器,攔截onError事件,然后使用ExceptionUtils,讓其根據(jù)錯誤類型來分別處理。

03.原始的處理方式

  • 最簡單的處理方式,直接對返回的throwable進(jìn)行類型判斷處理
//請求,對throwable進(jìn)行判斷 ServiceHelper.getInstance().getModelResult(param1, param2).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<Model>() {@Overridepublic void onCompleted() { } @Override public void onError(Throwable e) { if(e instanceof HttpException){ //獲取對應(yīng)statusCode和Message HttpException exception = (HttpException)e; String message = exception.response().message(); int code = exception.response().code(); }else if(e instanceof SSLHandshakeException){ //接下來就是各種異常類型判斷... }else if(e instanceof ...){ }... } @Override public void onNext(Model model) { if(model.getCode != CODE_SUCCESS){ int code = model.getCode(); switch (code){ case CODE_TOKEN_INVALID: ex.setDisplayMessage("重新登陸"); break; case CODE_NO_OTHER: ex.setDisplayMessage("其他情況"); break; case CODE_SHOW_TOAST: ex.setDisplayMessage("吐司服務(wù)器返回的提示"); break; case CODE_NO_MISSING_PARAMETER: ex.setDisplayMessage("缺少參數(shù),用log記錄服務(wù)器提示"); break; default: ex.setDisplayMessage(message); break; } }else{ //正常處理邏輯 } } });

04.如何減少代碼耦合性

  • 為了不改變以前的代碼結(jié)構(gòu),那么如何做才能夠徹底解耦呢?一般情況下使用Retrofit網(wǎng)絡(luò)請求框架,會有回調(diào)方法,如下所示:
package retrofit2;public interface Callback<T> { void onResponse(Call<T> var1, Response<T> var2); void onFailure(Call<T> var1, Throwable var2); }
  • 不管以前代碼封裝與否,都希望一句代碼即可實現(xiàn)網(wǎng)絡(luò)請求攔截處理邏輯。那么這個時候,我是怎么處理的呢?
public class ResponseData<T> { private int code; private String message; private T t; public int getCode() { return code; } public String getMessage() { return message; } public T getT() { return t; } } new Callback<ResponseData<HomeBlogEntity>>(){ @Override public void onResponse(Call<ResponseData<HomeBlogEntity>> call, Response<ResponseData<HomeBlogEntity>> response) { int code = response.body().getCode(); String message = response.body().getMessage(); HomeBlogEntity t = response.body().getT(); if (code!= CODE_SUCCESS){ //網(wǎng)絡(luò)請求成功200,不過業(yè)務(wù)層執(zhí)行服務(wù)端制定的異常邏輯 ExceptionUtils.serviceException(code,message); } else { //網(wǎng)絡(luò)請求成功,業(yè)務(wù)邏輯正常處理 } } @Override public void onFailure(Call call, Throwable throwable) { ExceptionUtils.handleException(throwable); } };

05.異常統(tǒng)一處理步驟

  • 第一步:定義請求接口網(wǎng)絡(luò)層失敗的狀態(tài)碼
/*** 對應(yīng)HTTP的狀態(tài)碼*/ private static final int BAD_REQUEST = 400; private static final int UNAUTHORIZED = 401; private static final int FORBIDDEN = 403; private static final int NOT_FOUND = 404; private static final int METHOD_NOT_ALLOWED = 405; private static final int REQUEST_TIMEOUT = 408; private static final int CONFLICT = 409; private static final int PRECONDITION_FAILED = 412; private static final int INTERNAL_SERVER_ERROR = 500; private static final int BAD_GATEWAY = 502; private static final int SERVICE_UNAVAILABLE = 503; private static final int GATEWAY_TIMEOUT = 504;
  • 第二步,接口請求成功,業(yè)務(wù)層失敗,服務(wù)端定義異常狀態(tài)碼

比如,登錄過期,提醒用戶重新登錄;
比如,添加商品,但是服務(wù)端發(fā)現(xiàn)庫存不足,這個時候接口請求成功,服務(wù)端定義業(yè)務(wù)層失敗,服務(wù)端給出提示語,客戶端進(jìn)行吐司
比如,請求接口,參數(shù)異常或者類型錯誤,請求code為200成功狀態(tài),不過給出提示,這個時候客戶端用log打印服務(wù)端給出的提示語,方便快遞查找問題
比如,其他情況,接口請求成功,但是服務(wù)端定義業(yè)務(wù)層需要吐司服務(wù)端返回的對應(yīng)提示語

/*** 服務(wù)器定義的狀態(tài)嗎* 比如:登錄過期,提醒用戶重新登錄;* 添加商品,但是服務(wù)端發(fā)現(xiàn)庫存不足,這個時候接口請求成功,服務(wù)端定義業(yè)務(wù)層失敗,服務(wù)端給出提示語,客戶端進(jìn)行吐司* 請求接口,參數(shù)異常或者類型錯誤,請求code為200成功狀態(tài),不過給出提示,這個時候客戶端用log打印服務(wù)端給出的提示語,方便快遞查找問題* 其他情況,接口請求成功,但是服務(wù)端定義業(yè)務(wù)層需要吐司服務(wù)端返回的對應(yīng)提示語*/ /*** 完全成功*/ private static final int CODE_SUCCESS = 0; /** * Token 失效 */ public static final int CODE_TOKEN_INVALID = 401; /** * 缺少參數(shù) */ public static final int CODE_NO_MISSING_PARAMETER = 400400; /** * 其他情況 */ public static final int CODE_NO_OTHER = 403; /** * 統(tǒng)一提示 */ public static final int CODE_SHOW_TOAST = 400000; 第三步,自定義Http層的異常和服務(wù)器定義的異常類 public class HttpException extends Exception { private int code; private String displayMessage; public HttpException(Throwable throwable, int code) { super(throwable); this.code = code; } public void setDisplayMessage(String displayMessage) { this.displayMessage = displayMessage; } public String getDisplayMessage() { return displayMessage; } public int getCode() { return code; } } public class ServerException extends RuntimeException { public int code; public String message; public int getCode() { return code; } public void setCode(int code) { this.code = code; } @Override public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
  • 第四步,統(tǒng)一處理異常邏輯如下所示
/*** 這個可以處理服務(wù)器請求成功,但是業(yè)務(wù)邏輯失敗,比如token失效需要重新登陸* @param code 自定義的code碼*/ public static void serviceException(int code , String content){ if (code != CODE_SUCCESS){ ServerException serverException = new ServerException(); serverException.setCode(code); serverException.setMessage(content); handleException(serverException); } } /** * 這個是處理網(wǎng)絡(luò)異常,也可以處理業(yè)務(wù)中的異常 * @param e e異常 */ public static void handleException(Throwable e){ HttpException ex; //HTTP錯誤 網(wǎng)絡(luò)請求異常 比如常見404 500之類的等 if (e instanceof retrofit2.HttpException){ retrofit2.HttpException httpException = (retrofit2.HttpException) e; ex = new HttpException(e, ErrorCode.HTTP_ERROR); switch(httpException.code()){ case BAD_REQUEST: case UNAUTHORIZED: case FORBIDDEN: case NOT_FOUND: case METHOD_NOT_ALLOWED: case REQUEST_TIMEOUT: case CONFLICT: case PRECONDITION_FAILED: case GATEWAY_TIMEOUT: case INTERNAL_SERVER_ERROR: case BAD_GATEWAY: case SERVICE_UNAVAILABLE: //均視為網(wǎng)絡(luò)錯誤 default: ex.setDisplayMessage("網(wǎng)絡(luò)錯誤"+httpException.code()); break; } } else if (e instanceof ServerException){ //服務(wù)器返回的錯誤 ServerException resultException = (ServerException) e; int code = resultException.getCode(); String message = resultException.getMessage(); ex = new HttpException(resultException, ErrorCode.SERVER_ERROR); switch (code){ case CODE_TOKEN_INVALID: ex.setDisplayMessage("token失效"); //下面這里可以統(tǒng)一處理跳轉(zhuǎn)登錄頁面的操作邏輯 break; case CODE_NO_OTHER: ex.setDisplayMessage("其他情況"); break; case CODE_SHOW_TOAST: ex.setDisplayMessage("吐司"); break; case CODE_NO_MISSING_PARAMETER: ex.setDisplayMessage("缺少參數(shù)"); break; default: ex.setDisplayMessage(message); break; } } else if (e instanceof JsonParseException || e instanceof JSONException || e instanceof ParseException){ ex = new HttpException(e, ErrorCode.PARSE_ERROR); //均視為解析錯誤 ex.setDisplayMessage("解析錯誤"); }else if(e instanceof ConnectException){ ex = new HttpException(e, ErrorCode.NETWORK_ERROR); //均視為網(wǎng)絡(luò)錯誤 ex.setDisplayMessage("連接失敗"); } else if(e instanceof java.net.UnknownHostException){ ex = new HttpException(e, ErrorCode.NETWORK_ERROR); //網(wǎng)絡(luò)未連接 ex.setDisplayMessage("網(wǎng)絡(luò)未連接"); } else if (e instanceof SocketTimeoutException) { ex = new HttpException(e, ErrorCode.NETWORK_ERROR); //網(wǎng)絡(luò)未連接 ex.setDisplayMessage("服務(wù)器響應(yīng)超時"); } else { ex = new HttpException(e, ErrorCode.UNKNOWN); //未知錯誤 ex.setDisplayMessage("未知錯誤"); } String displayMessage = ex.getDisplayMessage(); //這里直接吐司日志異常內(nèi)容,注意正式項目中一定要注意吐司合適的內(nèi)容 ToastUtils.showRoundRectToast(displayMessage); }
  • 第五步,如何調(diào)用
@Override public void onError(Throwable e) { //直接調(diào)用即可 ExceptionUtils.handleException(e); }

06.完成版代碼展示

  • 如下所示
public class ExceptionUtils { /* * 在使用Retrofit+RxJava時,我們訪問接口,獲取數(shù)據(jù)的流程一般是這樣的:訂閱->訪問接口->解析數(shù)據(jù)->展示。 * 如上所說,異常和錯誤本質(zhì)是一樣的,因此我們要盡量避免在View層對錯誤進(jìn)行判斷,處理。 * * 在獲取數(shù)據(jù)的流程中,訪問接口和解析數(shù)據(jù)時都有可能會出錯,我們可以通過攔截器在這兩層攔截錯誤。 * 1.在訪問接口時,我們不用設(shè)置攔截器,因為一旦出現(xiàn)錯誤,Retrofit會自動拋出異常。 * 2.在解析數(shù)據(jù)時,我們設(shè)置一個攔截器,判斷Result里面的code是否為成功,如果不成功,則要根據(jù)與服務(wù)器約定好的錯誤碼來拋出對應(yīng)的異常。 * 3.除此以外,為了我們要盡量避免在View層對錯誤進(jìn)行判斷,處理,我們必須還要設(shè)置一個攔截器,攔截onError事件,然后使用ExceptionHandler,讓其根據(jù)錯誤類型來分別處理。 */ /** * 對應(yīng)HTTP的狀態(tài)碼 */ private static final int BAD_REQUEST = 400; private static final int UNAUTHORIZED = 401; private static final int FORBIDDEN = 403; private static final int NOT_FOUND = 404; private static final int METHOD_NOT_ALLOWED = 405; private static final int REQUEST_TIMEOUT = 408; private static final int CONFLICT = 409; private static final int PRECONDITION_FAILED = 412; private static final int INTERNAL_SERVER_ERROR = 500; private static final int BAD_GATEWAY = 502; private static final int SERVICE_UNAVAILABLE = 503; private static final int GATEWAY_TIMEOUT = 504; /** * 服務(wù)器定義的狀態(tài)嗎 * 比如:登錄過期,提醒用戶重新登錄; * 添加商品,但是服務(wù)端發(fā)現(xiàn)庫存不足,這個時候接口請求成功,服務(wù)端定義業(yè)務(wù)層失敗,服務(wù)端給出提示語,客戶端進(jìn)行吐司 * 請求接口,參數(shù)異常或者類型錯誤,請求code為200成功狀態(tài),不過給出提示,這個時候客戶端用log打印服務(wù)端給出的提示語,方便快遞查找問題 * 其他情況,接口請求成功,但是服務(wù)端定義業(yè)務(wù)層需要吐司服務(wù)端返回的對應(yīng)提示語 */ /** * 完全成功 */ private static final int CODE_SUCCESS = 0; /** * Token 失效 */ public static final int CODE_TOKEN_INVALID = 401; /** * 缺少參數(shù) */ public static final int CODE_NO_MISSING_PARAMETER = 400400; /** * 其他情況 */ public static final int CODE_NO_OTHER = 403; /** * 統(tǒng)一提示 */ public static final int CODE_SHOW_TOAST = 400000; /** * 這個可以處理服務(wù)器請求成功,但是業(yè)務(wù)邏輯失敗,比如token失效需要重新登陸 * @param code 自定義的code碼 */ public static void serviceException(int code , String content){ if (code != CODE_SUCCESS){ ServerException serverException = new ServerException(); serverException.setCode(code); serverException.setMessage(content); handleException(serverException); } } /** * 這個是處理網(wǎng)絡(luò)異常,也可以處理業(yè)務(wù)中的異常 * @param e e異常 */ public static void handleException(Throwable e){ HttpException ex; //HTTP錯誤 網(wǎng)絡(luò)請求異常 比如常見404 500之類的等 if (e instanceof retrofit2.HttpException){ retrofit2.HttpException httpException = (retrofit2.HttpException) e; ex = new HttpException(e, ErrorCode.HTTP_ERROR); switch(httpException.code()){ case BAD_REQUEST: case UNAUTHORIZED: case FORBIDDEN: case NOT_FOUND: case METHOD_NOT_ALLOWED: case REQUEST_TIMEOUT: case CONFLICT: case PRECONDITION_FAILED: case GATEWAY_TIMEOUT: case INTERNAL_SERVER_ERROR: case BAD_GATEWAY: case SERVICE_UNAVAILABLE: //均視為網(wǎng)絡(luò)錯誤 default: ex.setDisplayMessage("網(wǎng)絡(luò)錯誤"+httpException.code()); break; } } else if (e instanceof ServerException){ //服務(wù)器返回的錯誤 ServerException resultException = (ServerException) e; int code = resultException.getCode(); String message = resultException.getMessage(); ex = new HttpException(resultException, ErrorCode.SERVER_ERROR); switch (code){ case CODE_TOKEN_INVALID: ex.setDisplayMessage("重新登陸"); break; case CODE_NO_OTHER: ex.setDisplayMessage("其他情況"); break; case CODE_SHOW_TOAST: ex.setDisplayMessage("吐司"); break; case CODE_NO_MISSING_PARAMETER: ex.setDisplayMessage("缺少參數(shù)"); break; default: ex.setDisplayMessage(message); break; } } else if (e instanceof JsonParseException || e instanceof JSONException || e instanceof ParseException){ ex = new HttpException(e, ErrorCode.PARSE_ERROR); //均視為解析錯誤 ex.setDisplayMessage("解析錯誤"); }else if(e instanceof ConnectException){ ex = new HttpException(e, ErrorCode.NETWORK_ERROR); //均視為網(wǎng)絡(luò)錯誤 ex.setDisplayMessage("連接失敗"); } else if(e instanceof java.net.UnknownHostException){ ex = new HttpException(e, ErrorCode.NETWORK_ERROR); //網(wǎng)絡(luò)未連接 ex.setDisplayMessage("網(wǎng)絡(luò)未連接"); } else if (e instanceof SocketTimeoutException) { ex = new HttpException(e, ErrorCode.NETWORK_ERROR); //網(wǎng)絡(luò)未連接 ex.setDisplayMessage("服務(wù)器響應(yīng)超時"); } else { ex = new HttpException(e, ErrorCode.UNKNOWN); //未知錯誤 ex.setDisplayMessage("未知錯誤"); } String displayMessage = ex.getDisplayMessage(); //這里直接吐司日志異常內(nèi)容,注意正式項目中一定要注意吐司合適的內(nèi)容 ToastUtils.showRoundRectToast(displayMessage); } }

感謝你能讀到最后,希望能對你有所幫助。

?如果需要源代碼或者架構(gòu)文檔的,請加QQ群:793305035

轉(zhuǎn)載于:https://www.cnblogs.com/jurendage/p/11357234.html

總結(jié)

以上是生活随笔為你收集整理的Java生鲜电商平台-SpringCloud微服务架构中网络请求性能优化与源码解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。