跳到主要內容

深入淺出Spring MVC_包裝設計


※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面



網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。



摘要


本文旨在詳細分析SpringMVC工作原理以及作為開發者如何基於SpringMVC做擴展。因為SpringMVC分析的文章比較多,所以本文重點講解如何利用SpringMVC的擴展點實現我們的需求。


什麼是Spring MVC


SpringMVC的作用是什麼呢?需要解決什麼問題呢?


下圖是一個客戶端與服務端的交互



在之前的詳解http報文(2)-web容器是如何解析http報文的一文中我也提到過。
這次再更細緻的分析一遍。一個請求如何中客戶端發到服務端,再從服務端返回內容。乾的這件事在web中叫請求動態內容,區別於靜態內容。在java語言中,為了解決這件事定義了一個規範就是servlet。具體的實現由各大廠商自己定義。


大體部分分為兩部分一塊是建立連接、一塊是傳輸內容。所以servlet規範包括兩大部分,,一部分是servlet接口,定義處理請求的規範。一部分是servlet容器的,去管理加載servlet實例。


輕量級的servlet容器有tomcat/jetty/undertow,servlet框架有SpringMVC/Struts/Webx這些,本篇重點講解SpringMVC


SpringMVC工作流程



Spring MVC 顧名思義就是處理Controll-Model-View的。



  1. DispatchServlet 是入口,doDispatch方法開始處理請求

  2. 首先經過controll,controll包含兩部分,一部分是url處理映射,將url與具體的處理bean映射起來。也就是HandleMapping,另一部分是具體的Handle,因為需要不同的handle,所以定義了HandleAdapter.

  3. Model比較簡單,主要就是ModelView對象,

  4. View 包含兩部分,一部分是ViewName的解析,另一部分是ViewName的對應的模板引擎,來渲染出最終的模板引擎。


常見擴展點


基於以上,Spring MVC 提供了不同層面的擴展,方便開發者實現定製化的功能,而不需要底層代碼的修改


一. Filter


Filter其實不算是SpringMVC,是servlet的,這時候請求還沒有到DispatchServlet。Filter允許對請求和響應做一些統一的定製化處理,比如你限流、日誌、trace。


實現javax.servlet.Filter接口即可


二. Controll - HandleMapping,HandlerAdapter


HandleMapping屬於Controll層面,我們可以編寫任意的HandlerMapping實現類,然後定義策略來決定一個web請求到HandlerExecutionChain對象的生成。


繼承RequestMappingHandlerMapping 類即可。
這個具體案例可以看下fredal的博客-使用基於 SpringMVC 的透明 RPC 開發微服務


簡要來說,他的rpc通信協議是基於http的。所以rpc調用就是基於服務端還是原來的restful api。寫法給普通的前端去掉無異,然後包一層rpc client。方便客戶端調用。但是這樣太麻煩了,對於不需要暴露給前端的API,單純是服務間的rpc調用。再走一遍servlet-SpringMVC沒必要。


※產品缺大量曝光嗎?你需要的是一流包裝設計!



窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。




所以他基於RequestMappingHandlerMapping做了一個改造。不再基於SpringMVC,而是自己定義了一套rpc的範式,然後轉換為springmvc。


三. Controll - Interceptor


Interceptor屬於Controll層面,我們可以自定義各種攔截器,在一個請求被真正處理之前、請求被處理但還沒輸出到響應中、請求已經被輸出到響應中之後這三個時間點去做任何我們想要做的事情。廣泛應用於Log,Session,鑒權等場景。


實現HandlerInterceptor接口即可


四. View - HandlerMethodArgumentResolver


解析方法參數的,可以很方便的擴展http請求參數。
實現HandlerMethodArgumentResolver接口即可


比如需要從http header中處理設備信息


@Component
public class DeviceResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(final MethodParameter methodParameter) {
return methodParameter.getParameterType().equals(DeviceInfo.class);
}

@Override
public Object resolveArgument(final MethodParameter methodParameter,
final ModelAndViewContainer modelAndViewContainer,
final NativeWebRequest nativeWebRequest,
final WebDataBinderFactory webDataBinderFactory) throws Exception {
HttpServletRequest request =
(HttpServletRequest) nativeWebRequest.getNativeRequest(HttpServletRequest.class);

// 從head頭中獲取設備信息
String id = request.getHeader("x-device-id");
if (id != null) {
DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.setId("id");
return deviceInfo;
}
return null;
}
}

五. View - Converter


類型轉換器,主要和序列化相關,參數綁定時springmvc會對將前端傳來的參數通過某種規則轉化成方法定義的參數的類型,默認實現的有StringHttpMessageConverter、ByteArrayHttpMessageConverter等等,默認的不能滿足需求時我們可自己定義此接口來實現自己的類型的轉換。


繼承AbstractHttpMessageConverter 即可。


六. View- HandlerExceptionResolver


異常處理,通常需要定義的全局異常。


@ControllerAdvice 註解即可
在一次和前端的相互甩鍋的問題記錄中有總結過這種


七. 修改requestbody 內容


當我們需要對RequestBody的內容進行統一處理時,因為HandlerMethodArgumentResolver只能處理特定類型的,做不到這點要求。


實現RequestBodyAdvice 接口即可。比如我需要處理requestbody中的內容,將emoji輸入轉換掉


@RestControllerAdvice
public class EmojiReplaceAdvice implements RequestBodyAdvice {
@Override
public boolean supports(final MethodParameter methodParameter, final Type targetType,
final Class<? extends HttpMessageConverter<?>> converterType) {
return methodParameter.hasParameterAnnotation(EmojiReplace.class);
}

@Override
public Object handleEmptyBody(final Object body, final HttpInputMessage inputMessage,
final MethodParameter parameter, final Type targetType,
final Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}

@Override
public HttpInputMessage beforeBodyRead(final HttpInputMessage inputMessage,
final MethodParameter parameter,
final Type targetType, final Class<? extends HttpMessageConverter<?>> converterType)
throws IOException {
return new HttpInputMessage() {
@Override
public InputStream getBody() throws IOException {
final String content = IOUtils.toString(inputMessage.getBody());
final String emojiUnicodeToAlias = StringUtil.parseEmojiUnicodeToAlias(content);
return new ByteArrayInputStream(
emojiUnicodeToAlias.getBytes(StandardCharsets.UTF_8));
}

@Override
public HttpHeaders getHeaders() {
return inputMessage.getHeaders();
}
};
}

@Override
public Object afterBodyRead(final Object body, final HttpInputMessage inputMessage,
final MethodParameter parameter, final Type targetType,
final Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}
}

總結


這篇文章主要是系統的概括了SpringMVC的工作原理和各種擴展機制,屬於高度概括,細節不足。具體的每個擴展點的實現、坑、應用場景需要在之後的文章繼續闡述。


參考


https://fredal.xin/develop-with-transparent-rpc

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※南投搬家公司費用需注意的眉眉角角,別等搬了再說!



上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務





Orignal From: 深入淺出Spring MVC_包裝設計

留言

這個網誌中的熱門文章

TOYOTA將與FirstElement合作建立加氣站

據AUTONET報導,TOYOTA將與能源公司FirstElement攜手合作加氫站網絡的架設,預計2015-2016年能夠建成20多處的加氣站,並能在2024年實現擴建至100座的計畫。 TOYOTA於2013年底東京車展發表準量產版的FCV Concept,此後又藉由年初的2014 CES消費電子展預告2015年將率先投入北美市場販售,因此對於加氫站等後勤網絡的建設排上日程。 其實在過去的20年來,TOYOTA就已持續針對氫燃料電池進行研發,自2002年以來便投入一系列的測試車輛於北美進行實測,隨著技術的突破,使得氫燃料電池技術成本大幅下修,終於達到原廠量產的預期。 儘管FCV(氫燃料電池車)最終量產版本的相關數據原廠尚未公開,但參考FCV Concept所呈現的數據就相當令人滿意。 動力來源為分別藏在車身底下的氫燃料儲存槽及電池,具備等同於136hp馬力的100kW輸出功率,需花費10秒才能完成100km/h的加速衝刺,滿電的情況下續航力約可達到482km,而且僅需3-5分鐘的時間便能將儲存槽加滿,省去了傳統電池充電耗時的問題。 重點是氫燃料電池是以氫或含氫物質結合氧所形成的一種燃料電池,在化學反應之後僅會產生電流及水且完全沒有污染。 動力來源為分別藏在車身底下的氫燃料儲存槽及電池(圖片來源:AUTONET) 本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理 【其他文章推薦】 ※ 新北清潔 公司,居家、辦公、裝潢細清專業服務 ※別再煩惱 如何寫文案 ,掌握八大原則! ※ 網頁設計 一頭霧水該從何著手呢? 台北網頁設計 公司幫您輕鬆架站! ※超省錢 租車 方案 ※教你寫出一流的 銷售文案 ? Orignal From: TOYOTA將與FirstElement合作建立加氣站

有了四步解題法模板,再也不害怕動態規劃!(看不懂算我輸)

導言 動態規劃問題一直是算法面試當中的重點和難點,並且動態規劃這種通過空間換取時間的算法思想在實際的工作中也會被頻繁用到,這篇文章的目的主要是解釋清楚 什麼是動態規劃 ,還有就是面對一道動態規劃問題,一般的 思考步驟 以及其中的注意事項等等,最後通過幾道題目將理論和實踐結合。 什麼是動態規劃 如果你還沒有聽說過動態規劃,或者僅僅只有耳聞,或許你可以看看 Quora 上面的這個 回答 。 How to explain dynamic 用一句話解釋動態規劃就是 " 記住你之前做過的事 ",如果更準確些,其實是 " 記住你之前得到的答案 "。 我舉個大家工作中經常遇到的例子。 在軟件開發中,大家經常會遇到一些系統配置的問題,配置不對,系統就會報錯,這個時候一般都會去 Google 或者是查閱相關的文檔,花了一定的時間將配置修改好。 過了一段時間,去到另一個系統,遇到類似的問題,這個時候已經記不清之前修改過的配置文件長什麼樣,這個時候有兩種方案,一種方案還是去 Google 或者查閱文檔,另一種方案是借鑒之前修改過的配置,第一種做法其實是萬金油,因為你遇到的任何問題其實都可以去 Google,去查閱相關文件找答案,但是這會花費一定的時間,相比之下,第二種方案肯定會更加地節約時間,但是這個方案是有條件的,條件如下: 之前的問題和當前的問題有着關聯性,換句話說,之前問題得到的答案可以幫助解決當前問題 需要記錄之前問題的答案 當然在這個例子中,可以看到的是,上面這兩個條件均滿足,大可去到之前配置過的文件中,將配置拷貝過來,然後做些細微的調整即可解決當前問題,節約了大量的時間。 不知道你是否從這些描述中發現,對於一個動態規劃問題,我們只需要從兩個方面考慮,那就是 找出問題之間的聯繫 ,以及 記錄答案 ,這裏的難點其實是找出問題之間的聯繫,記錄答案只是順帶的事情,利用一些簡單的數據結構就可以做到。 概念 上面的解釋如果大家可以理解的話,接    動態規劃 算法是通過拆分問題,定義問題狀態和狀態之間的關係,使得問題能夠以遞推(或者說分治)的方式去解決。它的幾個重要概念如下所述。    階段: 對於一個完整的問題過程,適當的切分為若干個相互聯繫的子問題,每次在求解一個子問題...

數據資產的玄學、顯學

數據就是資產,這個道理在商業領域並不難懂。 比如國外有聚焦金融數據的彭博,國內也有萬德,早期靠着人工錄入、整理數據的方式,聚集了龐大的數據庫,成為投資公司的必備;而聚焦學術文獻等知識數據的知網,不僅舒舒服服賺差價,還能涉嫌壟斷被處罰。 但數據資產這個理念,在全社會得到認可,也非一蹴而就,而是一波一波的普及、深化。 2011年,麥肯錫發布報告,認為"大數據Big Data已成為當今競爭、創新、生產效率提升的關鍵基礎"。一時間,大數據,成為業內熱點。數據,大家都懂;大,有什麼區別? 聚焦大數據的創業公司紛紛成立,時任美國總統的奧巴馬也在2012年3月宣布了"大數據研究與發展先導計劃",雖然投資額僅2億美元,但有評論認為這和上世紀90年代的信息公路計劃相媲美。 而不管大的是什麼,至少一個確定的趨勢是,數據資產,越來越值錢。 這股科技新風也來到中國。本着"懂不懂先不說,有新趨勢就先干"的大A,也漸漸熱鬧起來。比如擁有消費者購買記錄的百貨公司,雖然還處於電商取代線下的衰退趨勢中,但投資者還是興奮地給了"估值重構"的機會,2013年7月份,也曾有過股價快速漲一倍的戰績。 而最"得勢"的當屬銀之傑,公司通過收購億美軟通,為企業向用戶發送短信,每年發送量超過100億條。每一條短信,在投資人眼裡,都是金燦燦的"數據資產"。再疊加科技牛市buff,銀之傑受到投資者的狂熱追捧。從2012年底起,兩年半漲幅近100倍。一個字,絕。兩個字,瘋狂。 2015年4月,我國首家大數據交易所——貴陽大數據交易所成立,對數據資產的探索,又邁出了關鍵一步。成立當天就完成了第一筆數據交易,交易所管理層也雄心勃勃,提出在3~5年內將日交易額推到100億元的規模。 蜂擁而至的故事,結局似乎都差不多。2016年,Gartner在報告中警告:許多公司正打算削減大數據項目投入。 百貨行業沒有避開電商的衝擊,業績也沒有被數據資產改善;而短信等數據,也讓投資人清醒,有的數據是資產,有的只是01代碼,或者只是投資人情緒的載體。而在大數據領域創業的公司,也有一些融了FGH輪之後,不得不賣服務器來改善現金流。而貴陽大數據中心也在2022年8月,才實現了數據交易規模...