1. 程式人生 > >拯救老舊工程,記橋接SpringMVC與Stripes框架

拯救老舊工程,記橋接SpringMVC與Stripes框架

背景:

  公司基礎設施部門推出了自己的微服務框架(以下簡稱M),要求所有業務應用都要接入進去,但坑爹的是M只提供了SpringMVC工程的support,對於採用Stripes作為MVC框架的應用並不支援,所以就必須重構這個Stripes應用。

  M雖然代替Tomcat自己實現了IO,工作執行緒池,服務註冊發現等等,但還是提供了對Servlet規範的簡單支援(移除了web.xml,filter,listener, 打包方式也改成了tar.gz,保留了ServletContext,request,response等等)。

思路與分析:

  由於現有應用的業務邏輯還是比較複雜(沉澱了3,4年),且涉及到多個APP端和其他第三方的互動,所以如果想對應用做完全的重構是一件非常頭痛的事情,不僅要投入大量的後端,測試等人力成本,而且整個重構週期也會比較長,影響到對其他需求的響應。

  於是在想:既然SpringMVC和Stripes都遵循Servlet規範,而M又能支援SpringMVC,是否可以通過SpringMVC攔截到所有請求後,把之前的老介面的請求轉發給Stripes處理,以後新開發的介面就直接走SpringMVC,這樣既相容了公司的M框架也對原有應用的改動較小,開發週期短,測試人員只需要驗證一些系統邊界和主要流程,不用再挨個挨個驗證已有的業務邏輯,這樣可以節省大量人力成本,縮短開發週期。

  SpringMVC是目前最流行的MVC框架,是Spring龐大家族的一員,而Stripes也是一個非常輕量的MVC框架,但是SpringMVC的Controller跟Stripes的ActionBean有個很明顯的區別就是前者是單例的,跟狀態無關,所有的請求引數都是封裝在ServletRequest中的,而後者是prototype,每次請求都會重新生成一個ActionBean物件。

 

動手實現原型:

       新建橋接工程XXX-bridge,所有新增程式碼均放在新工程,對老工程零侵入,僅新增了pom檔案裡的兩個plugin,可以實現Stripes和SpringMVC兩種框架模式下的並行開發,(原來的老工程持續有需求進來)。

    /**
     * 攔截所有請求,如果能對映到Stripes則直接派發給Stripes並return false;
     * 如果不能對映則回退給SpringMVC
     */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws
Exception { if (handlerMapping.isEmpty()) { return true; } String url = httpServletRequest.getRequestURI(); String contextPath = httpServletRequest.getContextPath(); url = url.replace(contextPath, "").replaceAll("/+", "/"); LOGGER.info("當前請求路徑: {}", url); if (!StripesContextHandlerInterceptor.handlerMapping.containsKey(url)) { LOGGER.info("請求由SpringMVC處理: {}", url); return true; } try { LOGGER.info("請求由Stripes處理: {}", url); StripesContextHolder.doService(httpServletRequest.getServletContext(), getApplicationContext(), httpServletRequest, httpServletResponse); return false; } catch (Exception e) { LOGGER.error("處理請求異常:", e); return false; } }

       關鍵點在於要解析到所有的老介面地址,然後通過攔截器來判斷當前請求是否是老介面,是的話就轉發給Stripes來處理。其他詳細的程式碼託管在github(已排除掉公司相關資訊)

       https://github.com/hiccup234/web-advance/blob/master/bridge.rar

問題與驗證:

       1、因為初始化Stripes需要 ServletContext,但是應用啟動時卻沒辦法獲取到 ServletContext 物件,所以在 StripesContextHolder 裡做了懶載入,只有當第一個請求進來後才初始化Stripes。

  2、Stripes是支援queryString為空的查詢的,類似:http://127.0.0.1/server/test?list 這種,而M會在解析請求引數的時候對這種情況直接拋異常,經過與基礎設施同事協商,他們做出讓步,對這種請求的情況直接放行給應用,從而避免了前端和第三方做改造。

 

今晚上線成功,目前跟Tomcat並行釋出,5%的流量灰度,觀察日誌一切正常。前期的技術驗證加上近一月的開發測試到今天的上線,算是向著架構的方向邁出了小小一步。

 

未完待續...