ESB提供比傳統中間件產品更爲廉價的解決方案,同時它還能夠消除不一樣應用之間的技術差別,讓不一樣的應用服務器協調運做,實現了不一樣服務之間的通訊與整合。從功能上看,ESB提供了事件驅動和文檔導向的處理模式,以及分佈式的運行管理機制,它支持基於內容的路由和過濾,具有了複雜數據的傳輸能力,並能夠提供一系列的標準接口,可是ESB並無http請求效率高。 廢話就很少說了,先看看怎麼實現的吧。 首先肯定請求報文的格式,以我在項目中的報文爲例:
<MbfService xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <input1> <MbfHeader> <ServiceCode>CMercPerformanceMgmt</ServiceCode> <Operation>queryStoreScores</Operation> <AppCode>SFS</AppCode> <UId>5136fa413f96493391d6075f654d4d83bcfbbc57bd8e47e5</UId> </MbfHeader> <MbfBody> <cmfUserId>0224136722</cmfUserId> <currentPage>1</currentPage> <pageSize>5</pageSize> <supportCStore>0</supportCStore> </MbfBody> </input1></MbfService>java
這就是一個接口的請求報文,通常報文格式是固定的,須要改動的只是報文的節點,被調用方接口也是根據節點篩選出所須要的請求參數,另外,報文是用POST方式提交,參數是封裝在body中的。ajax
下面是被請求接口:爲了各位看的明白些,我狠添註釋,這樣代碼和註釋一塊兒看比較方便
//RequestMapping,這個是spring中截獲請求的url做用 @RequestMapping("/my_product_review") public String getPendingOrderItems(HttpServletRequest request, HttpServletResponse response) throws IOException { //這裏是從request中取到報文,getMbfRequestInput方法會在下面貼出代碼 MbfRequestInput mbfRequestInput = getMbfRequestInput(request); //根據報文中參數建立請求對象,這裏只要PendingOrderItemDTO 中的屬性跟請求報文的節點一致便可(也就是報文中 <MbfBody>中的節點名稱) PendingOrderItemDTO requestDTO = (PendingOrderItemDTO) mbfRequestInput .getMbfBody(PendingOrderItemDTO.class); //封裝返回對像的報文 MbfResponseWrapper mbfResponseWrapper = new MbfResponseWrapper( mbfRequestInput.getMbfHeader());spring
// 處理請求參數,orderVo爲最終返回報文的類 MobilePhonePendingOrderVO orderVO = null; try { //這句代碼能夠忽略,就是根據請求參數作處理,封裝類,做爲返回報文數據 orderVO = mobilePhoneService.getPendingOrderItems(requestDTO.getCmfUserId(), requestDTO.getCurrentPage(), requestDTO.getPageSize(), requestDTO.getSupportCStore()); //將返回類按報文格式處理,就是跟請求報文同樣,好比orderVo有一個屬性name,返回報文<MbfBody>中就會有<name>XXX</name> mbfResponseWrapper.setMbfBody(orderVO); //返回這次請求成功標識 mbfResponseWrapper.setStatus(Constants.COMPLETE); } catch (Exception e) { mbfResponseWrapper.setMbfBody(new DummyResponseDTO()); //返回這次請求失敗標識 mbfResponseWrapper.setStatus(Constants.FAIL); mbfResponseWrapper.setCode(""); mbfResponseWrapper.setDesc(e.getMessage()); //下面是異常處理 EventMessage eventMessage = new EventMessage(); eventMessage.setFunctionName(ExceptionUtil.getCurrentMethodName()); logger.logException(eventMessage, e); } //按報文格式返回數據 return ajaxXmlCache(response, mbfResponseWrapper.getMbfResponse().toString(), ReviewProperties.getMaxAge()); }
上面這些代碼對使用esb處理請求,返回報文等就夠了,由於解析報文是有專門的封裝類的,只須要引入,就可使用裏面的方法。爲了各位方便學習,我多寫點吧服務器
/** * 從HttpServletRequest中獲取ESB請求報文 */ public MbfRequestInput getMbfRequestInput(HttpServletRequest request) throws IOException { InputStream inputStream = request.getInputStream(); BufferedReader in = new BufferedReader(new InputStreamReader(inputStream)); StringBuffer buffer = new StringBuffer(); String line = ""; while ((line = in.readLine()) != null) { buffer.append(line); } return MbfRequest.getMbfRequest(buffer.toString()).getInput(); } 其中MbfRequest.getMbfRequest()方法app
/** * 功能描述:resquestXml轉換成MbfResquest對象 */ public static MbfRequest getMbfRequest(String xml){ MbfRequest mbfRequest = (MbfRequest) XStreamUtil.xmlToObject(xml, MbfRequest.class); mbfRequest.getInput().setMbfBodyXml(getMbfBodyXml(xml)); return mbfRequest; }分佈式
至於好比getInput()等方法就是本身封裝的很基礎的java類了,貼出來也無妨 /** *ide
<MbfService xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">學習
<input1>
<MbfHeader>
<!--ServiceCode: 服務代碼-->
<ServiceCode>OrderManage</ServiceCode>
<!--Operation: 操做編碼-->
<Operation>CreateOrder</Operation>
<!--AppCode: 請求方系統代碼-->
<AppCode>b2c</AppCode>
<!--UId: 服務流水號-->
<UId>414d5120514d5f6c6f63616c202020203baa474c20012802</UId>
<!--AuthId: 認證ID -->
<AuthId/>
</MbfHeader>
<MbfBody>
<!--請求服務系統BODY -->
</MbfBody>
</input1>
</MbfService>this
*/ @XStreamAlias("MbfService") public class MbfRequest {編碼
private static final String rootStart = "<MbfService xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"; private static final String rootEnd = "</MbfService>"; private static final String bodyStart = "<MbfBody>"; private static final String bodyEnd = "</MbfBody>"; @XStreamAlias("input1") private MbfRequestInput input; public MbfRequestInput getInput() { return input; } public void setInput(MbfRequestInput input) { this.input = input; } /** * 功能描述:resquestXml轉換成MbfResquest對象 */ public static MbfRequest getMbfRequest(String xml){ MbfRequest mbfRequest = (MbfRequest) XStreamUtil.xmlToObject(xml, MbfRequest.class); mbfRequest.getInput().setMbfBodyXml(getMbfBodyXml(xml)); return mbfRequest; } private static String getMbfBodyXml(String xml){ int beginIndex = xml.indexOf(bodyStart); int endIndex = xml.indexOf(bodyEnd); String bodyXml = ""; if(beginIndex != -1 && endIndex != -1){ bodyXml = xml.substring(beginIndex + bodyStart.length(), endIndex); } return bodyXml; } @Override public String toString() { return toString(false); } public String toString(boolean replaceBlank) { String inputStr = null; if(replaceBlank){ inputStr = input.toString(true); } else { inputStr = input.toString(false); } String result = rootStart + inputStr + rootEnd; return result; }
} 雖然上面主要貼了的是解析請求報文,可是相信你們看到這裏也應該知道是怎麼回事了,若是你用現有的解析報文的jar包,很方便用,可是若是你就想本身寫jar包玩,根據上面的慢慢琢磨是能夠的,可是仍是有些底層jar須要引用,好比:com.thoughtworks.xstream.annotations.XStreamAlias,不過就是一層一層的解析xml文件,封裝成請求對象,而後在把返回對象解析成xml文件發送給調用方罷了。
最後,我以爲有必要說下主方法中的return後面的內容:ajaxXmlCache(response, mbfResponseWrapper.getMbfResponse().toString(), ReviewProperties.getMaxAge());
這個地方是比較容易出現問題的,很少說 了,直接貼代碼吧:
/** * 根據字符串輸出xml,返回null * * @param xml * @return */ public String ajaxXmlCache(HttpServletResponse response, String xmlString, String cacheTime) { return ajaxCache(response, xmlString, "text/xml", cacheTime); }
//下面就是最原始的寫內容了 /** * AJAX輸出,返回null * * @param content * @param type * @return */ public String ajaxCache(HttpServletResponse response, String content, String type, String cacheTime) { try { response.setContentType(type + ";charset=UTF-8"); setCache(response, cacheTime); response.getWriter().write(content); response.getWriter().flush(); } catch (IOException e) { EventMessage eventMessage = new EventMessage(); eventMessage.setFunctionName(ExceptionUtil.getCurrentMethodName()); logger.logException(eventMessage, e); } return null; }
其中針對解析報文,封裝報文,以及對內容的封裝代碼也是有不少的,以爲沒有必要所有貼出來,就寫這些吧,剛開始寫博客,算做是記錄一下本身的成長經歷吧