国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

鹽城微網(wǎng)站建設(shè)廣州王牌seo

鹽城微網(wǎng)站建設(shè),廣州王牌seo,一個完美的網(wǎng)站怎么做,江陰做網(wǎng)站前言 在尼恩讀者50交流群中,尼恩經(jīng)常指導(dǎo)小伙伴改簡歷。 改簡歷所涉及的一個要點(diǎn)是: 在 XXX 項(xiàng)目中,完成了 XXX 模塊的代碼優(yōu)化 另外,在面試的過程中,面試官也常常喜歡針對提問,來考察候選人對代碼質(zhì)量的追…

前言

在尼恩讀者50+交流群中,尼恩經(jīng)常指導(dǎo)小伙伴改簡歷。 改簡歷所涉及的一個要點(diǎn)是:

在 XXX 項(xiàng)目中,完成了 XXX 模塊的代碼優(yōu)化

另外,在面試的過程中,面試官也常常喜歡針對提問,來考察候選人對代碼質(zhì)量的追求、對設(shè)計(jì)模式的應(yīng)用能力:

你做過哪些代碼優(yōu)化?

大家一般的套路,都是通過模板模式、策略模式等,完成 XXXXX 模塊的重構(gòu),提升代碼的可擴(kuò)展行,可維護(hù)性。

如果有類似的擴(kuò)展場景還好,頭疼的是,很多小伙伴確實(shí)沒有。然后無奈的說,沒有做過代碼的優(yōu)化。

尼恩告訴大家,如果你作為一個高手,連代碼優(yōu)化都沒有做過,是不可能的。 尼恩本人從2006開始做Java開發(fā),就一直生活在代碼優(yōu)化的路上。

如果這個問題答不好,你就不是高手,不具備拿高薪的條件。

那么,該在哪里找點(diǎn)代碼優(yōu)化的需求呢?

這里尼恩給大家展示一個簡單、又可以稱之為極品、又是人人用得著的案例:

后端接口返回結(jié)果的二次封裝優(yōu)化

此案例,既能展示大家對代碼優(yōu)雅的追求,也能展示大家對spring框架的雄厚內(nèi)功,如果面試的時(shí)候如數(shù)家珍,能讓面試官愛到 “刮目相看”。

同時(shí),尼恩一并把這個題目以及參考答案,收入咱們的 《尼恩Java面試寶典》,供后面的小伙伴參考,提升大家的 3高 架構(gòu)、設(shè)計(jì)、開發(fā)水平。

注:本文以 PDF 持續(xù)更新,最新尼恩 架構(gòu)筆記、面試題 的PDF文件,請從這里獲取:碼云


場景

在移動互聯(lián)網(wǎng),分布式、微服務(wù)盛行的今天,現(xiàn)在項(xiàng)目絕大部分都采用的微服務(wù)框架,前后端分離方式,一般系統(tǒng)的大致整體架構(gòu)圖如下:

Rest API接口

前端和后端進(jìn)行交互,前端按照約定請求URL路徑,并傳入相關(guān)參數(shù),后端服務(wù)器接收請求,進(jìn)行業(yè)務(wù)處理,返回?cái)?shù)據(jù)給前端。

針對URL路徑的restful風(fēng)格,以及傳入?yún)?shù)的公共請求頭的要求(如:app_version,api_version,device等),這里就不介紹了,小伙伴們可以來尼恩的尼恩讀者50+交流群中交流

著重介紹一下后端服務(wù)器如何實(shí)現(xiàn)把數(shù)據(jù)返回給前端?

返回格式

后端返回給前端我們一般用JSON體方式,定義如下:

{#返回狀態(tài)碼code:integer,		#返回信息描述message:string,#返回值data:object
}

CODE狀態(tài)碼

code返回狀態(tài)碼,一般小伙伴們是在開發(fā)的時(shí)候需要什么,就添加什么。

如接口要返回用戶權(quán)限異常,我們加一個狀態(tài)碼為101吧,下一次又要加一個數(shù)據(jù)參數(shù)異常,就加一個102的狀態(tài)碼。這樣雖然能夠照常滿足業(yè)務(wù),但狀態(tài)碼太凌亂了

我們應(yīng)該可以參考HTTP請求返回的狀態(tài)碼

下面是常見的HTTP狀態(tài)碼:
200 - 請求成功
301 - 資源(網(wǎng)頁等)被永久轉(zhuǎn)移到其它URL
404 - 請求的資源(網(wǎng)頁等)不存在
500 - 內(nèi)部服務(wù)器錯誤
分類區(qū)間分類描述
1**100~199信息,服務(wù)器收到請求,需要請求者繼續(xù)執(zhí)行操作
2**200~299成功,操作被成功接收并處理
3**300~399重定向,需要進(jìn)一步的操作以完成請求
4**400~499客戶端錯誤,請求包含語法錯誤或無法完成請求
5**500~599服務(wù)器錯誤,服務(wù)器在處理請求的過程中發(fā)生了錯誤

我們可以參考這樣的設(shè)計(jì),這樣的好處就把錯誤類型歸類到某個區(qū)間內(nèi),如果區(qū)間不夠,可以設(shè)計(jì)成4位數(shù)。

#10001999 區(qū)間表示參數(shù)錯誤
#20002999 區(qū)間表示用戶錯誤
#30003999 區(qū)間表示接口異常

這樣前端開發(fā)人員在得到返回值后,根據(jù)狀態(tài)碼就可以知道,大概什么錯誤,再根據(jù)message相關(guān)的信息描述,可以快速定位。

Message

這個字段相對理解比較簡單,就是發(fā)生錯誤時(shí),如何友好的進(jìn)行提示。一般的設(shè)計(jì)是和code狀態(tài)碼一起設(shè)計(jì),如

//狀態(tài)碼枚舉
public enum ResultCode {private Integer code;private String message;ResultCode(Integer code, String message) {this.code = code;this.message = message;}
}

再在枚舉中定義,狀態(tài)碼

返回狀態(tài)碼
public enum ResultCode {privateInteger code;private String message;ResultCode(Integer code,String message) {this.code = code;this.message = message;}public Integer code(){return this.code;}public String message() {return this.message;}/* 成功狀態(tài)碼 */SUCCESS(1"成功"),/* 參數(shù)錯誤: 1001-1999 */PARAM IS INVALID(1001,"參數(shù)無效"),PARAM IS BLANK(1002,"參數(shù)為空"),PARAM TYPE BIND ERROR(1003"參數(shù)類型錯誤"),PARAM NOT_COMPLETE(1004,"參數(shù)缺失"),/* 用戶錯誤: 2001-2999*/USER NOT_LOGGED IN(2001,"用戶未登錄,訪問的路徑需要驗(yàn)證,請登錄"),USER LOGIN ERROR(2002,"賬號不存在或密碼錯誤"),USER ACCOUNT FORBIDDEN(2003,"賬號已被禁用"),USER NOT_EXIST(2004,"用戶不存在"),USER HAS EXISTED(2005"用戶已存在")
}

狀態(tài)碼和信息就會一一對應(yīng),比較好維護(hù)。

Data

返回?cái)?shù)據(jù)體,JSON格式,根據(jù)不同的業(yè)務(wù)又不同的JSON體。

我們要設(shè)計(jì)一個返回體類Result

@aData
public class Result implements Serializable {private Integer code;private String message;private Object data;public Result(ResultCode resultCode, Object data) {this.code = resultCode.code;this.message = resultCode.message();this.data = data;}
}

控制層Controller

我們會在controller層處理業(yè)務(wù)請求,并返回給前端,以order訂單為例

@RestController
@RequestMapping("/orders")
public class OrderController {@Autowiredprivate OrderService orderService;@GetMapping("{id}")public Result getOrder(@PathVariable("id") Integer id) {Order order = orderService.getOrderById(id);Result result = new Result(ResultCode.SUCCESS,order);return result;}
}

我們看到在獲得order對象之后,我們是用的Result構(gòu)造方法進(jìn)行包裝賦值,然后進(jìn)行返回。

小伙伴們有沒有發(fā)現(xiàn),構(gòu)造方法這樣的包裝是不是很麻煩,我們可以優(yōu)化一下。

美觀優(yōu)化

我們可以在Result類中,加入靜態(tài)方法,一看就懂

@Data
public class Result implements Serializable {//省。。//返回成功public static Result success() {Result result = new Result();result.setResultCode(ResultCode.SUCCESS);return result;}//返回成功public static Result success(Object data) {Result result = new Result();result.setResultCode(ResultCode.SUCCESS);result.setData(data);return result;}//返回失敗public static Result failure(ResultCode resultCode) {Result result = new Result();result.setResultCode(resultCode);return result;}//返回失敗public static Result failure(ResultCode resultCode, Obiect data){Result result = new ResultO;result.setResultCode(resultCode);result.setData(data);return result;}
}

那我們來改造一下Controller

@RestController
@RequestMapping("/orders")
public class OrderController [@Autowiredprivate OrderService orderService;GetMapping("{id}")public Result getOrder(@PathVariable("id") Integer id) {if(id == null){return Result.failure(ResultCode.PARAM IS INVALID);}Order order = orderService.getOrderById(id);return Result.success(order);}
}

代碼比較簡潔了,也美觀了。

尼恩的SpringCloud開發(fā)腳手架,是這么做的。 尼恩公司的那些億級RMP大項(xiàng)目,也是這么做的。

那么,有沒有優(yōu)化的空間呢? 當(dāng)然有。

切面式思想優(yōu)化

上面我們看到在Result類中增加了靜態(tài)方法,使得業(yè)務(wù)處理代碼簡潔了。但小伙伴們有沒有發(fā)現(xiàn)這樣有幾個問題:

1、每個方法的返回都是Result封裝對象,沒有業(yè)務(wù)含義

2、在業(yè)務(wù)代碼中,成功的時(shí)候我們調(diào)用Result.success,異常錯誤調(diào)用Result.failure。是不是很多余

3、上面的代碼,判斷id是否為null,其實(shí)我們可以使用hibernate validate做校驗(yàn),沒有必要在方法體中做判斷。

具體怎么解決呢?宏觀的思路如下:

可以應(yīng)用切面式的思想,把Rest外層包裝抽取到切面中,而不是放在業(yè)務(wù)代碼中,從而讓業(yè)務(wù)代碼回歸業(yè)務(wù)本身,更為邏輯清晰、結(jié)構(gòu)簡單。

優(yōu)化之后的效果是,業(yè)務(wù)Controller直接返回真實(shí)業(yè)務(wù)對象,最好不要改變之前的業(yè)務(wù)方式,如下圖

@RestController
@RequestMapping("/orders")
public class OrderController {@Autowiredprivate OrderService orderService;@GetMapping("{id}")public Order getOrder(aPathVariable("id") Integer id) {Order order = orderService.getOrderById(id);return roder;}
}

業(yè)務(wù)代碼我們平時(shí)的代碼是一樣的,非常直觀,直接返回order對象,這樣是不是很完美。

切面式的思想的實(shí)現(xiàn)方案是什么呢?

切面式的實(shí)現(xiàn)方案

小伙伴們怎么去實(shí)現(xiàn)是不是有點(diǎn)思路,在這個過程中,我們需要做幾個事情

1、定義一個注解@ResponseResult,表示這個接口返回的值需要包裝一下

2、攔截請求,判斷此請求是否需要被@ResponseResult注解

3、核心步驟就是實(shí)現(xiàn)接口ResponseBodyAdvice和@ControllerAdvice,判斷是否需要包裝返回值,如果需要,就把Controller接口的返回值進(jìn)行重寫。

注解類

定義一個注解類,用來標(biāo)記方法的返回值是否需要包裝

@Retention(RUNTIME)
@Target({ TYPEMETHOD })
@Documented
public @interface ResponseResult {
}

攔截器

攔截請求,是否此請求返回的值需要包裝,

其實(shí)就是運(yùn)行的時(shí)候,解析@ResponseResult注解

//請求攔截器
@slf4j
@Component
public class ResponseResultInterceptor implements HandlerInterceptor{//標(biāo)記名稱public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";@Overridepublic boolean preHandle(HttpServletRequest reguest, HttpServletResponse response, Object handler)throws Exception {//請求的方法if(handler instanceof HandlerMethod){final HandlerMethod handlerMethod = (HandlerMethod)handler;final Class<?> clazz = handlerMethod.getBeanType();final Method method = handlerMethod.getMethod();//判斷是否在類對象上面加了注解if (clazz.isAnnotationPresent(ResponseResult.class)) {//設(shè)置此請求返回體,需要包裝,往下傳遞,在ResponseBodyAdvice接口進(jìn)行判斷request.setAttribute(RESPONSE_RESULTANN,clazz.getAnnotation(ResponseResult.class));}else if (method.isAnnotationPresent(ResponseResult,class)) { //方法體上是否有注解//設(shè)置此請求返回體,需要包裝,往下傳遞,在ResponseBodyAdvice接口進(jìn)行判斷request.setAttribute(RESPONSE_RESULT_ANN,method.getAnnotation(ResponseResult.class));}}return true;}
}

此代碼核心思想,就是獲取此請求,根據(jù)注解判斷是否需要返回值包裝,并且在request上設(shè)置一個屬性標(biāo)記。

重寫返回體

@slf4j
@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object>{//標(biāo)記名稱public static final String RESPONSE_RESULTANN = "RESPONSE-RESULT-ANN";//是否請求 包含了 包裝注解 標(biāo)記,沒有就直接返回,不需要重寫返回體@Overridepublic boolean supports (MethodParameter returntype, Class<? extends HttpMessagelonverter<?>> convertertype){ServletRequestAttributes ra = ((ServletRequestAttributes) RequestContextHolder getRequestAttributes());HttpServletRequest request = sra.getRequest();//判斷請求 是否有包裝標(biāo)記ResponseResult responseResultAnn = (ResponseResult) request,getAttribute(RESPONSE RESULT_ANN);return responseResultAnn == null ? false : true;}@Overridepublic Object beforeBodyWrite(0bject body, MethodParameter returnType, MediaType selectedContentTypeClass<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {log.info("進(jìn)入 返回體 重寫格式 處理中。。。。。");return Result.success(body);}
}

上面supports 代碼就是判斷是否需要返回值包裝,如果需要(support返回true)就直接進(jìn)入 beforeBodyWrite包裝。

這里我們只處理了正常成功的包裝,如果方法體報(bào)異常怎么辦?

處理異常也比較簡單,只要判斷body是否為異常類。

@Override
public Object beforeBodywrite(0bject body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {log.info("進(jìn)入 返回體 重寫格式 處理中。。。。");if (body instanceof ErrorResult) {log.info("返回值 異常 作包裝 處理中。。。");ErrorResult errorResult = (ErrorResult) body;return Result.failure(errorResult.getCode(),errorResult, getMessage ),errorResult, getErrors());}return Result.success(body);
}

怎么做全局的異常處理,實(shí)現(xiàn)方式有兩種

  • 第一種:使用@ControllerAdvice和@ExceptionHandler注解
  • 第二種: 使用ErrorController類來實(shí)現(xiàn)。

參考ResponseBodyAdvice,對返回結(jié)果,進(jìn)行二次包裝就可以了。

篇幅原因,這里就不做介紹了,只要思路理清楚了,自行改造就行。

重寫Controller

@RestController
@RequestMapping("/orders")
@ResponseResult
public class OrderController {@Autowiredprivate OrderService orderService;@GetMapping("{id}")public Order getOrder(aPathVariable("id") Integer id) {Order order = orderService.getOrderById(id);return roder;}
}

在控制器類上或者方法體上加上@ResponseResult注解,這樣就ok了,簡單吧。

到此,返回結(jié)果的代碼優(yōu)化完成,經(jīng)過代碼優(yōu)化之后,咱們的代碼是不是又簡潔,又優(yōu)雅。

那么,這個方案還有沒有別的優(yōu)化空間,當(dāng)然是有的。

如:每次請求都要反射一下,獲取請求的方法是否需要包裝,其實(shí)可以做個緩存,不需要每次都需要解析。

當(dāng)然整體思路了解,小伙伴們就可以在此基礎(chǔ)上面自行擴(kuò)展。具體的進(jìn)一步優(yōu)化方案,也可以來尼恩讀者50+交流群中交流

總結(jié)

代碼優(yōu)化,是一個高手的必須課,基本功。這里尼恩給大家展示一個簡單、又可以稱之為極品、又是人人用得著的案例。

此案例,既能展示大家對代碼優(yōu)雅的追求,也能展示大家對spring框架的雄厚內(nèi)功,如果面試的時(shí)候如數(shù)家珍,能讓面試官愛到 “刮目相看”。

推薦閱讀:

《響應(yīng)式圣經(jīng):10W字,實(shí)現(xiàn)Spring響應(yīng)式編程自由》

《全鏈路異步,讓你的 SpringCloud 性能優(yōu)化10倍+》

《Linux命令大全:2W多字,一次實(shí)現(xiàn)Linux自由》

《網(wǎng)易二面:CPU狂飆900%,該怎么處理?》

《阿里二面:千萬級、億級數(shù)據(jù),如何性能優(yōu)化? 教科書級 答案來了》

《峰值21WQps、億級DAU,小游戲《羊了個羊》是怎么架構(gòu)的?》

《場景題:假設(shè)10W人突訪,你的系統(tǒng)如何做到不 雪崩?》

《2個大廠 100億級 超大流量 紅包 架構(gòu)方案》

《Nginx面試題(史上最全 + 持續(xù)更新)》

《K8S面試題(史上最全 + 持續(xù)更新)》

《操作系統(tǒng)面試題(史上最全、持續(xù)更新)》

《Docker面試題(史上最全 + 持續(xù)更新)》

《Springcloud gateway 底層原理、核心實(shí)戰(zhàn) (史上最全)》

《Flux、Mono、Reactor 實(shí)戰(zhàn)(史上最全)》

《sentinel (史上最全)》

《Nacos (史上最全)》

《TCP協(xié)議詳解 (史上最全)》

《分庫分表 Sharding-JDBC 底層原理、核心實(shí)戰(zhàn)(史上最全)》

《clickhouse 超底層原理 + 高可用實(shí)操 (史上最全)》

《nacos高可用(圖解+秒懂+史上最全)》

《隊(duì)列之王: Disruptor 原理、架構(gòu)、源碼 一文穿透》

《環(huán)形隊(duì)列、 條帶環(huán)形隊(duì)列 Striped-RingBuffer (史上最全)》

《一文搞定:SpringBoot、SLF4j、Log4j、Logback、Netty之間混亂關(guān)系(史上最全)》

《單例模式(史上最全)》

《紅黑樹( 圖解 + 秒懂 + 史上最全)》

《分布式事務(wù) (秒懂)》

《緩存之王:Caffeine 源碼、架構(gòu)、原理(史上最全,10W字 超級長文)》

《緩存之王:Caffeine 的使用(史上最全)》

《Java Agent 探針、字節(jié)碼增強(qiáng) ByteBuddy(史上最全)》

《Docker原理(圖解+秒懂+史上最全)》

《Redis分布式鎖(圖解 - 秒懂 - 史上最全)》

《Zookeeper 分布式鎖 - 圖解 - 秒懂》

《Zookeeper Curator 事件監(jiān)聽 - 10分鐘看懂》

《Netty 粘包 拆包 | 史上最全解讀》

《Netty 100萬級高并發(fā)服務(wù)器配置》

《Springcloud 高并發(fā) 配置 (一文全懂)》

http://aloenet.com.cn/news/39026.html

相關(guān)文章:

  • 開發(fā)一個網(wǎng)站的步驟推廣軟件賺錢的app
  • 廣州移動 網(wǎng)站設(shè)計(jì)如何在各大平臺推廣
  • 天津建設(shè)工程信息網(wǎng)如何注冊網(wǎng)站優(yōu)化推廣招聘
  • 網(wǎng)站搭建搜外友鏈
  • 如何開網(wǎng)店無貨源不需要投資河北seo技術(shù)
  • 在設(shè)計(jì)賺錢的網(wǎng)站有哪些做網(wǎng)站需要多少錢
  • 廣東省農(nóng)業(yè)農(nóng)村廳官方網(wǎng)站成都網(wǎng)站快速開發(fā)
  • 建站源碼程序惠州seo外包服務(wù)
  • 自己的網(wǎng)站怎么開培訓(xùn)心得體會范文大全2000字
  • 外貿(mào)必看網(wǎng)站湖南百度seo
  • 做3d效果的網(wǎng)站亞馬遜關(guān)鍵詞排名提升
  • 松江品劃做網(wǎng)站云浮新增確診病例30例
  • 易企網(wǎng)站建設(shè)滁州網(wǎng)站seo
  • 系統(tǒng)優(yōu)化的方法知識點(diǎn)外貿(mào)建站優(yōu)化
  • 深圳網(wǎng)站建設(shè)加q479185700外貿(mào)網(wǎng)絡(luò)營銷推廣
  • 保障性租賃住房管理平臺優(yōu)化大師班級優(yōu)化大師
  • 網(wǎng)站建設(shè)與開發(fā)論文谷歌seo是什么意思
  • php外貿(mào)網(wǎng)站制作最快新聞資訊在哪看
  • 購物網(wǎng)站開發(fā)需求文檔百度云登錄入口
  • 石獅網(wǎng)站定制北京seo專業(yè)團(tuán)隊(duì)
  • #NAME?站長工具seo優(yōu)化系統(tǒng)
  • 網(wǎng)站描述是什么濟(jì)南網(wǎng)站seo優(yōu)化
  • 換接入商網(wǎng)站備案百度指數(shù)搜索
  • 安徽網(wǎng)站建站系統(tǒng)哪家好谷歌網(wǎng)站優(yōu)化推廣
  • 可以兼職做設(shè)計(jì)的網(wǎng)站百度收錄入口
  • 如何做網(wǎng)站價(jià)格策略seo職業(yè)培訓(xùn)班
  • 專業(yè)做俄語網(wǎng)站建設(shè)司排名第一的手機(jī)清理軟件
  • 婚紗攝影網(wǎng)站seo方案友情鏈接怎么做
  • 企業(yè)網(wǎng)站建設(shè)服務(wù)熱線搜狗搜索引擎網(wǎng)頁
  • 虛擬主機(jī)網(wǎng)站后臺友情鏈接購買