基於AnypointStudio IDE開發MuleESB實例
本文部分內容引用https://www.cnblogs.com/enjoyingsoft/p/10132360.html,在此,對原著作者表示感謝。
一、AnypointStudio IDE環境的安裝
1.安裝jdk1.8以上
2.MuleESB分為社區版和企業版,兩者的區別如下:
3.mule esb的開發,主要是在AnypointStudio IDE環境下開發的,所以首先需要下載一個AnypointStudio IDE,本文下載的是6.6.4版本。安裝過程和eclipse一樣。
由於Anypoint Studio默認只內嵌了Mule ESB企業版運行環境,如果你想使用社區版的話,我們還需要安裝Mule ESB社區版運行環境。
安裝社區版運行環境,可以使用下列步驟。
點擊Help/Install New Software...菜單
在Work with下拉框中選擇Mule Runtimes for Anypoint Studio
選中Mule ESB Server Runtime 3.9.0 CE,CE就是Community Edition,社區版的意思。然后點擊Next一直到完成。
本例是實現一個cxf的webservice服務封裝為http服務。
首先,需要自行開發一個webservice的服務端程序。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--WerbService CXF依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> <version>2.2.5.RELEASE</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.3.5</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> </dependencies>
@WebService(name = "helloService",targetNamespace="http://service.cxf.cbi.com/") public interface HelloService { @WebMethod String sayHello(@WebParam(name="param") Person person); } @Service @WebService(targetNamespace="http://service.cxf.cbi.com/", serviceName = "helloService", endpointInterface = "com.cbi.cxf.server.service.HelloService") public class HelloServiceImpl implements HelloService { @Override public String sayHello(@WebParam(name="param") Person person) { System.out.println("receive:"+person.getName()+","+person.getAge()); return "hello,"+person.getName()+","+person.getAge(); } }
@Configuration public class WebServiceConfig { @Autowired private HelloService helloService; @Autowired private SpringBus springBus; @Bean(name = "helloServiceEndPoint") public Endpoint endpoint() { EndpointImpl endpoint=new EndpointImpl(springBus, helloService);//綁定要發布的服務 endpoint.publish("/helloWs"); //顯示要發布的名稱 return endpoint; }
public class Person implements Serializable { private static final long serialVersionUID = 1L; private String name; private String age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String string) { this.age = string; } }
服務端程序開發完成之后啟動,訪問http://localhost:8080/cxf/webServices/helloWs?wsdl,即可得到如下wsdl:
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://service.cxf.cbi.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="helloService" targetNamespace="http://service.cxf.cbi.com/"> <wsdl:types> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://service.cxf.cbi.com/" elementFormDefault="unqualified" targetNamespace="http://service.cxf.cbi.com/" version="1.0"> <xs:element name="sayHello" type="tns:sayHello"/> <xs:element name="sayHelloResponse" type="tns:sayHelloResponse"/> <xs:complexType name="sayHello"> <xs:sequence> <xs:element minOccurs="0" name="param" type="tns:person"/> </xs:sequence> </xs:complexType> <xs:complexType name="person"> <xs:sequence> <xs:element minOccurs="0" name="age" type="xs:string"/> <xs:element minOccurs="0" name="name" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:complexType name="sayHelloResponse"> <xs:sequence> <xs:element minOccurs="0" name="return" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:schema> </wsdl:types> <wsdl:message name="sayHelloResponse"> <wsdl:part element="tns:sayHelloResponse" name="parameters"> </wsdl:part> </wsdl:message> <wsdl:message name="sayHello"> <wsdl:part element="tns:sayHello" name="parameters"> </wsdl:part> </wsdl:message> <wsdl:portType name="helloService"> <wsdl:operation name="sayHello"> <wsdl:input message="tns:sayHello" name="sayHello"> </wsdl:input> <wsdl:output message="tns:sayHelloResponse" name="sayHelloResponse"> </wsdl:output> </wsdl:operation> </wsdl:portType> <wsdl:binding name="helloServiceSoapBinding" type="tns:helloService"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="sayHello"> <soap:operation soapAction="" style="document"/> <wsdl:input name="sayHello"> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="sayHelloResponse"> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="helloService"> <wsdl:port binding="tns:helloServiceSoapBinding" name="HelloServiceImplPort"> <soap:address location="http://localhost:8080/cxf/webServices/helloWs"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
6.使用AnypointStudio開發mule ESB的服務。
根據實際選擇運行環境,一直next下去,完成即可。
工程依賴包:
工程http2webservice創建好之后,按照區域1拖拽出流程,按照區域3編寫java代碼,區域2是在拖拽流程的過程中,可以搜索需要的組件。
public class Person implements Serializable { private static final long serialVersionUID = 1L; private String name; private String age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String string) { this.age = string; } }
public class Trans extends AbstractMessageTransformer{ @Override public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException { String xml=""; try { xml=message.getPayloadAsString(); Document doc=DocumentHelper.parseText(xml); Element root=doc.getRootElement(); Person person=new Person(); person.setName(root.element("name").getText()); person.setAge(root.element("age").getText()); JSONObject node = new JSONObject(); node.put("param", person); System.out.println("node==================="+node); Map<String, Object> newMap=TransUtil.parseJSONToMap(node.toString()); System.out.println("newMap==================="+newMap); xml=TransUtil.parseMapToXML(newMap, "sayHello", "http://service.cxf.cbi.com/"); } catch (Exception e) { e.printStackTrace(); } System.out.println("xml==================="+xml); return xml; } }
public class ReturnTrans extends AbstractMessageTransformer{ @Override public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException { Object payload=message.getPayload(); DepthXMLStreamReader xmlreader=(DepthXMLStreamReader) payload; XMLStreamReader reader=xmlreader.getReader(); String returnxml=""; try { while(reader.hasNext()) { int point =reader.next(); if(point==XMLStreamReader.START_ELEMENT) { String eleName=reader.getName().toString(); if("return".equals(eleName)) { returnxml=reader.getElementText(); break; } } } } catch (XMLStreamException e) { e.printStackTrace(); } returnxml="<result>"+returnxml+"</result>"; System.out.println("xml==================="+returnxml); return returnxml; }
public class TransUtil { public static Map<String,Object> parseJSONToMap(String jsonStr){ Map<String, Object> map = new HashMap<>(); JSONObject json = JSONObject.fromObject(jsonStr); for (Object k : json.keySet()) { Object v = json.get(k); if (v instanceof JSONArray) { List<Map<String, Object>> list = new ArrayList<>(); Iterator<JSONObject> it = ((JSONArray) v).iterator(); while (it.hasNext()) { JSONObject json2 = it.next(); list.add(parseJSONToMap(json.toString())); } map.put(k.toString(), list); } else { map.put(k.toString(), v); } } return map; } public static String parseMapToXML(Map<String,Object> map,String method,String nameSpace) { if (map == null) return null; JSONObject json = JSONObject.fromObject(map); XMLSerializer ser = new XMLSerializer(); ser.setRootName("tem:" + method); ser.write(json); ser.setNamespace("tem", nameSpace); ser.setTypeHintsEnabled(false); String result = ser.write(json, "UTF-8"); return result; } public static Map<String, Object> multilayerXmlToMap(String xml) { Document doc = null; try { doc = DocumentHelper.parseText(xml); } catch (DocumentException e) { e.printStackTrace(); } Map<String, Object> map = new HashMap<>(); if (null == doc) { return map; } // 獲取根元素 Element rootElement = doc.getRootElement(); recursionXmlToMap(rootElement,map); return map; } /** * multilayerXmlToMap核心方法,遞歸調用 * * @param element 節點元素 * @param outmap 用於存儲xml數據的map */ private static void recursionXmlToMap(Element element, Map<String, Object> outmap) { // 得到根元素下的子元素列表 List<Element> list = element.elements(); int size = list.size(); if (size == 0) { // 如果沒有子元素,則將其存儲進map中 outmap.put(element.getName(), element.getTextTrim()); } else { // innermap用於存儲子元素的屬性名和屬性值 Map<String, Object> innermap = new HashMap<>(); // 遍歷子元素 list.forEach(childElement -> recursionXmlToMap(childElement, innermap)); outmap.put(element.getName(), innermap); } } }
按照如上圖的配置完成之后,可以啟動工程。在工程上右鍵run as mule application即可。
7.測試
cxf服務客戶端測試:
方式一:動態調用
public class TestClient { public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException, InstantiationException { // 創建動態客戶端 JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); Client client = dcf.createClient("http://localhost:8080/cxf/webServices/helloWs?wsdl"); // 需要密碼的情況需要加上用戶名和密碼 // client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD)); Object[] result = null; //loadClass路徑是命名空間+po類名,不是Po的包路徑+po類名 Object po = Thread.currentThread().getContextClassLoader().loadClass("com.cbi.cxf.service.Person").newInstance();//加載類為服務端自定義對象命名空間 Method method = po.getClass().getMethod("setName", String.class);//調用set方法設置參數 method.invoke(po, "卓寶貝"); method = po.getClass().getMethod("setAge", String.class);//調用set方法設置參數 method.invoke(po, "6"); Object[] parameters = new Object[]{po}; try { result = client.invoke("sayHello", parameters);//uploadcs為接口方法 System.out.println(result[0].toString()); } catch (Exception e) { e.printStackTrace(); } }
方式二:靜態調用
public class TestClient2 { public static void main(String[] args) { JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setAddress("http://localhost:8080/cxf/webServices/helloWs?wsdl"); factory.setServiceClass(HelloService.class);//服務端接口類 Person person = new Person();//自定義對象參數 person.setName("卓寶貝"); person.setAge("6"); HelloService service = (HelloService) factory.create(); String results = service.sayHello(person);//sayHello為接口方法 System.out.println(results); } }
兩種方式測試原始的webservice接口的結果相同,如下:
hello,卓寶貝,6
使用postman測試封裝的http接口:post方式 http://127.0.0.1:8081/http2webservice/hello
返回結果說明:
如果返回結果要和原始的webservice接口保持一致,流程圖中的最后一個節點需要去掉。
如果返回結果需要用json表示,則需要在ReturnTrans類中或者在webservice接口返回時,先拼接成xml格式,然后xml to json節點才會正確轉換,否則會報錯,如下:
最終獲得的結果json格式如下:
{ "result": "hello,卓寶貝,6" }