預告片:裸指關節SOA

我正在研究這個想法,但我不知道它是否對你們有吸引力。 我想就您是否需要進一步探討提出您的意見。

達成協議:我遇到過一些團隊,他們在使用SOA技術時由于其工具的復雜性而陷入泥潭。 我只在Java中看到過這種情況,但是我從一些C#開發人員那里聽說,他們也意識到那里的現象。 我想探索一種替代方法。

與向您的項目中添加WSDL(Web服務定義語言。Hocuspocus)文件并自動生成內容相比,此方法需要更多的工作。 但是,它帶有更多的了解和增強的可測試性。 最后,我體驗到,盡管需要額外的體力勞動,但是這使我能夠更快地完成任務。

這篇博客文章的目的(如果您喜歡它,它是擴展的)旨在探索一種總體上對SOA特別是對Web服務的更簡單的方法。 我通過一個具體的例子來說明這些原理:當用戶的貨幣相對于美元跌至閾值以下時,通知用戶。 為了使服務在技術上變得有趣,我將使用訂戶的IP地址來確定其幣種。

步驟1:通過模擬外部交互來創建活動服務

模擬您自己的服務的活動可以幫助您構建定義與外部服務的交互的接口。

預告片:

public class CurrencyPublisherTest {private SubscriptionRepository subscriptionRepository = mock(SubscriptionRepository.class);private EmailService emailService = mock(EmailService.class);private CurrencyPublisher publisher = new CurrencyPublisher();private CurrencyService currencyService = mock(CurrencyService.class);private GeolocationService geolocationService = mock(GeolocationService.class);@Testpublic void shouldPublishCurrency() throws Exception {Subscription subscription = TestDataFactory.randomSubscription();String location = TestDataFactory.randomCountry();String currency = TestDataFactory.randomCurrency();double exchangeRate = subscription.getLowLimit() * 0.9;when(subscriptionRepository.findPendingSubscriptions()).thenReturn(Arrays.asList(subscription));when(geolocationService.getCountryByIp(subscription.getIpAddress())).thenReturn(location);when(currencyService.getCurrency(location)).thenReturn(currency);when(currencyService.getExchangeRateFromUSD(currency)).thenReturn(exchangeRate);publisher.runPeriodically();verify(emailService).publishCurrencyAlert(subscription, currency, exchangeRate);}@Beforepublic void setupPublisher() {publisher.setSubscriptionRepository(subscriptionRepository);publisher.setGeolocationService(geolocationService);publisher.setCurrencyService(currencyService);publisher.setEmailService(emailService);}
}

Spoiler:最近,我開始將隨機測試數據生成用于我的測試,效果很好。

發布者使用了許多服務。 現在讓我們集中討論一項服務:GeoLocationService。

步驟2:為每個服務創建測試和存根-從geolocationservice開始

頂級測試顯示了我們從每個外部服務中需要的東西。 得知此信息并閱讀(是!)服務的WSDL后,我們可以測試驅動服務的存根。 在此示例中,我們實際上通過啟動嵌入在測試中的Jetty使用HTTP運行測試。

預告片:

public class GeolocationServiceStubHttpTest {@Testpublic void shouldAnswerCountry() throws Exception {GeolocationServiceStub stub = new GeolocationServiceStub();stub.addLocation("80.203.105.247", "Norway");Server server = new Server(0);ServletContextHandler context = new ServletContextHandler();context.addServlet(new ServletHolder(stub), "/GeoService");server.setHandler(context);server.start();String url = "http://localhost:" + server.getConnectors()[0].getLocalPort();GeolocationService wsClient = new GeolocationServiceWsClient(url + "/GeoService");String location = wsClient.getCountryByIp("80.203.105.247");assertThat(location).isEqualTo("Norway");}
}

驗證并創建xml有效負載

這是第一個“裸露的”位。 在這里,我不使用框架就創建了XML有效負載(俗稱的“ $”語法由JOOX庫提供,JOOX庫是內置JAXP類之上的一個薄包裝):

我將用于實際服務的XSD(更多焦點)添加到項目中,并編寫代碼以驗證消息。 然后,通過遵循驗證錯誤開始構建XML有效負載。

預告片:

public class GeolocationServiceWsClient implements GeolocationService {private Validator validator;private UrlSoapEndpoint endpoint;public GeolocationServiceWsClient(String url) throws Exception {this.endpoint = new UrlSoapEndpoint(url);validator = createValidator();}@Overridepublic String getCountryByIp(String ipAddress) throws Exception {Element request = createGeoIpRequest(ipAddress);Document soapRequest = createSoapEnvelope(request);validateXml(soapRequest);Document soapResponse = endpoint.postRequest(getSOAPAction(), soapRequest);validateXml(soapResponse);return parseGeoIpResponse(soapResponse);}private void validateXml(Document soapMessage) throws Exception {validator.validate(toXmlSource(soapMessage));}protected Validator createValidator() throws SAXException {SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);Schema schema = schemaFactory.newSchema(new Source[] {new StreamSource(getClass().getResource("/geoipservice.xsd").toExternalForm()),new StreamSource(getClass().getResource("/soap.xsd").toExternalForm()),});return schema.newValidator();}private Document createSoapEnvelope(Element request) throws Exception {return $("S:Envelope",$("S:Body", request)).document();}private Element createGeoIpRequest(String ipAddress) throws Exception {return $("wsx:GetGeoIP", $("wsx:IPAddress", ipAddress)).get(0);}private String parseGeoIpResponse(Element response) {// TODOreturn null;}private Source toXmlSource(Document document) throws Exception {return new StreamSource(new StringReader($(document).toString()));}
}

在這個示例中,我從JOOX庫中獲得了一些幫助(也有些痛苦),用于Java中的XML操作。 由于Java的XML庫非常瘋狂,因此我也放棄了已檢查的異常。

Spoiler:我對到目前為止發現的所有XML庫中的名稱空間,驗證,XPath和檢查的異常的處理通常感到非常不滿意。 所以我正在考慮創建自己的。

當然,您可以對從XSD自動生成的類使用相同的方法,但是我不相信這確實有很大幫助。

通過http流xml

Java內置的HttpURLConnection是一種笨拙但可維修的將XML傳送到服務器的方法(只要您不執行高級HTTP身份驗證)。

預告片:

public class UrlSoapEndpoint {private final String url;public UrlSoapEndpoint(String url) {this.url = url;}public Document postRequest(String soapAction, Document soapRequest) throws Exception {URL httpUrl = new URL(url);HttpURLConnection connection = (HttpURLConnection) httpUrl.openConnection();connection.setDoInput(true);connection.setDoOutput(true);connection.addRequestProperty("SOAPAction", soapAction);connection.addRequestProperty("Content-Type", "text/xml");$(soapRequest).write(connection.getOutputStream());int responseCode = connection.getResponseCode();if (responseCode != 200) {throw new RuntimeException("Something went terribly wrong: " + connection.getResponseMessage());}return $(connection.getInputStream()).document();}
}

破壞者:此代碼應通過日志記錄和錯誤處理進行擴展,并將驗證移入裝飾器中。 通過控制HTTP處理,我們可以解決人們購買ESB所需解決的大多數問題。

創建存根并解析xml

存根使用xpath在請求中查找位置。 它生成響應的方式與ws客戶端生成請求的方式幾乎相同(未顯示)。

public class GeolocationServiceStub extends HttpServlet {private Map<String,String> locations = new HashMap<String, String>();public void addLocation(String ipAddress, String country) {locations.put(ipAddress, country);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {try {String ipAddress = $(req.getReader()).xpath("/Envelope/Body/GetGeoIP/IPAddress").text();String location = locations.get(ipAddress);createResponse(location).write(resp.getOutputStream());} catch (Exception e) {throw new RuntimeException("Exception at server " + e);}}
}

劇透:可以將存根擴展到一個網頁,使我可以測試系統,而無需實際集成到任何外部服務。

驗證并解析響應

ws客戶端現在可以驗證存根的響應是否符合XSD并解析響應。 同樣,這是使用XPath完成的。 我沒有顯示代碼,只是更多相同。

真實的東西!

現在,該代碼將驗證XML有效負載是否符合XSD。 這意味著ws客戶端現在應該可以用于真實對象。 讓我們編寫一個單獨的測試來檢查它:

public class GeolocationServiceLiveTest {@Testpublic void shouldFindLocation() throws Exception {GeolocationService wsClient = new GeolocationServiceWsClient("http://www.webservicex.net/geoipservice.asmx");assertThat(wsClient.getCountryByIp("80.203.105.247")).isEqualTo("Norway");}}

好極了! 有用! 實際上,它在我第一次嘗試時失敗了,因為我沒有正確的國家名稱作為測試的IP地址。

這種點對點集成測試比我的其他單元測試慢且健壯。 但是,我認為事實并不重要。 我從Infinitest配置中過濾了測試,除此之外我不在乎。

充實所有服務

需要以與GeolocationService相同的方式充實SubscriptionRepository,CurrencyService和EmailService。 但是,由于我們知道我們只需要與這些服務中的每一個進行非常特定的交互,因此我們不必擔心作為SOAP服務的一部分可能發送或接收的所有內容。 只要我們能夠完成業務邏輯(CurrencyPublisher)所需的工作,我們就很好!

示范和價值鏈測試

如果我們為存根創建Web UI,我們現在可以向客戶展示此服務的整個價值鏈。 在我的SOA項目中,我們依賴的某些服務將僅在項目后期才能上線。 在這種情況下,我們可以使用存根顯示我們的服務有效。

劇透:隨著我厭倦了驗證手動價值鏈測試的有效性,我可能最終會創建一個使用WebDriver設置存根并驗證測試可以正常進行的測試,就像在手動測試中一樣。

在Soa競技場中戰斗時脫下手套

在本文中,我展示并暗示了六種以上的技術,這些技術可用于不涉及框架,ESB或代碼生成的測試,http,xml和驗證。 該方法使程序員可以100%控制他們在SOA生態系統中的位置。 每個領域都需要深入探索。 如果您想探索它,請告訴我。

哦,我也想使用更好的Web服務的想法,因為Geolocated貨幣電子郵件非常實用。

參考: 預告片:來自我們JCG合作伙伴 Johannes Brodwall的“千篇一律的SOA”,來自“更大的盒子中的思考”博客。


翻譯自: https://www.javacodegeeks.com/2012/07/teaser-bare-knuckle-soa.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371733.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371733.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371733.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網頁轉圖片 java_java-網頁轉圖片

對比了網上常用的好幾種網頁轉圖片的開源插件&#xff0c;最后效果還不如使用原生的java直接寫來得好&#xff0c;上代碼&#xff0c;很簡單&#xff0c;中間需要考慮網頁加載延遲的問題&#xff0c;所以需要加上thread.sleep&#xff0c;休眠一下等待網頁加載完成了&#xff0…

開一個新坑吧

每天讀讀日志 給自己動力 開個新坑&#xff08;外星殖民&#xff09; 無聊時寫一寫 轉載于:https://www.cnblogs.com/dandansang/p/7143489.html

JMX和Spring –第1部分

這是三篇文章的第一篇&#xff0c;這三篇文章將展示如何通過JMX支持為Spring應用程序賦能。 Maven配置 這是用于設置此示例代碼的Maven pom.xml&#xff1a; <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSche…

maven exclude java_java – Maven:從shade插件中排除依賴項

我在mvn clean install之后看過下一個字符串Including com.sun.jersey.contribs:jersey-multipart:jar:1.5 in theshaded jar問題&#xff1a;即使我已經為maven-shade-plugin添加了exlusion,我也無法使它沒有陰影(參見下面的代碼)我的maven-shade-plugin&#xff1a;org.apach…

JMX和Spring –第3部分

本文是本系列的最后一篇。 看一下第1 部分和第2部分 。 在本系列的最后一篇文章中&#xff0c;我將展示如何在JDK中使用本機JMX支持來實現一種通知機制&#xff0c;該機制可以在HEAP內存超過特定閾值時向偵聽器發出警報。 正如我在上一篇文章中討論的那樣&#xff0c;這種方法…

QScrollArea不能顯示滾動條

轉載請注明出處&#xff1a;http://www.cnblogs.com/dachen408/p/7147141.html 問題&#xff1a;QScrollArea不能顯示滾動條 解決方案&#xff1a;設置QScrollArea->setWidgetResizeable&#xff08;false&#xff09;解決問題。 例子&#xff1a; ui.scrollArea->setWi…

java婚慶網站源碼_基于jsp的婚慶網站-JavaEE實現婚慶網站 - java項目源碼

基于jspservletpojomysql實現一個javaee/javaweb的婚慶網站, 該項目可用各類java課程設計大作業中, 婚慶網站的系統架構分為前后臺兩部分, 最終實現在線上進行婚慶網站各項功能,實現了諸如用戶管理, 登錄注冊, 權限管理等功能, 并實現對各類婚慶網站相關的實體進行管理。該婚慶…

JQuery實現的模塊交換動畫效果

<!doctype html> <html><head><meta http-equiv"content-type" content"text/html;charsetutf-8" /><title>JQuery實現的模塊交換動畫效果</title><meta name"Keywords" content"jquery&#xff0c…

CKD 實現

主要功能&#xff1a;1、新物料&#xff08;部品號&#xff09;的入庫管理 部品號的驗證、描述、品名、重量、單價等 2、部品號-供應商的核對 校驗部品號/供應商的對應情況、入庫、移除等 3、BOM清單的導入 基礎清單的導入 4、訂單 CKD套件管理 物料齊套管理 箱單管理 匯總 5、…

JMX和Spring –第2部分

這篇文章從本教程的第1部分繼續。 嗨&#xff0c;在我的前一篇文章中&#xff0c;我解釋了如何通過Spring設置JMX服務器以及如何通過身份驗證和授權保護對它的訪問。 在本文中&#xff0c;我將展示如何實現一個簡單的MBean&#xff0c;該MBean允許用戶在運行時更改Log4j記錄器…

android p wifi一直在掃描_(一百六十八)Android P wifi 掃描失敗結果上報流程梳理-掃描上報梳理②...

接(一百五十五)Android P wifi 掃描失敗結果上報流程梳理-掃描上報梳理 掃描失敗上報梳理發現梳理的差了很多&#xff0c;特補充1.WificondScannerImplOverridepublic boolean startSingleScan(WifiNative.ScanSettings settings,WifiNative.ScanEventHandler eventHandler) {i…

(五)什么是RDD-JavaPython版Spark

什么是RDD 視頻教程&#xff1a; 1、優酷 2、YouTube RDD是個抽象類&#xff0c;全稱為Resilient Distributed Datasets&#xff0c;是一個容錯的、并行的數據結構&#xff0c;可以讓用戶顯式地將數據存儲到磁盤和內存中&#xff0c;并能控制數據的分區。同時&#xff0c;RDD還…

LazyInitializationException的四種解決方案–第1部分

在今天的帖子中&#xff0c;我們將討論常見的LazyInitializationException錯誤。 我們將看到四種避免該錯誤的方法&#xff0c;以及每種方法的優缺點。在本文的最后&#xff0c;我們將討論EclipseLink如何處理該異常。 為了看到LazyInitializationException錯誤并進行處理&…

linux驅動

jeffies hz xtime 每秒鐘系統時鐘節拍數 prco < 內核內存視窗 include/linux/list.h < 內核的數據結構&#xff0c;鏈表 workques_struct 工作隊列轉載于:https://www.cnblogs.com/asreg/p/7148606.html

java 條碼識別_條碼識別示例代碼

package api.jisuapi.barcode;import api.util.HttpUtil;import net.sf.json.JSONArray;import net.sf.json.JSONObject;public class Read {public static final String APPKEY "your_appkey_here";// 你的appkeypublic static final String URL "https://ap…

終極JPA查詢和技巧列表–第2部分

這一部分是該系列文章的第一部分 。 JPA&#xff1a;NamedQuery&#xff0c;使用日期查詢&#xff0c;有關getSingleResult方法的警告 為了避免重復查詢代碼&#xff0c;提高性能并簡化維護查詢&#xff0c;我們可以使用NamedQueries。 NamedQuery使用JPQL作為語法&#xff0c…

設置UITableView設置contentsize

由于UITableView是繼承自UIScrollView的&#xff0c;所以他是可以設置contentsize的。 但是&#xff0c;我在試驗的過程中&#xff0c;初始化UITableView實例后&#xff0c;直接設置它的contentsize是不起作用&#xff0c;在搜尋相關資料得知&#xff0c;UITableView會自動設置…

java 線程什么時候結束_java線程什么時候讓出cpu?

Thread.sleep();sleep就是正在執行的線程主動讓出cpu&#xff0c;cpu去執行其他線程&#xff0c;在sleep指定的時間過后&#xff0c;cpu才會回到這個線程上繼續往下執行&#xff0c;如果當前線程進入了同步鎖&#xff0c;sleep方法并不會釋放鎖&#xff0c;即使當前線程使用sle…

Hibernate配置方式

Hibernate配置方式 Hibernate給人的感受是靈活的&#xff0c;要達到同一個目的&#xff0c;我們可以使用幾種不同的辦法。就拿Hibernate配置來說&#xff0c;常用的有如下三種方式&#xff0c;任選其一。 在 hibernate.cfg.xml 中加入元素 <property>、<mapping>&a…

js中 javascript:void(0) 用法詳解

javascript:void(0)表示不做任何動作。如&#xff1a; 復制代碼代碼如下:<a href"javascript:void(0);" οnclick"alert(ok);"></a> 這里表示這個鏈接不做跳轉動作&#xff0c;執行onClick事件。 我想使用過ajax的都常見這樣的代碼&#xff1…