因爲Mule ESB提供的容器自身限制,使它不容易集成第三方庫。爲了解決這個問題,Mule提供了ESB項目與Spring框架的集成。可是這個集成在轉換爲Tomcat項目時會遇到一些問題,下面我會一一加以敘述。java
ESB項目與spring的集成參考了Mule ESB的Spring集成文檔,地址爲mysql
https://docs.mulesoft.com/mule-user-guide/v/3.8/using-spring-beans-as-flow-componentsspring
在前面的例子中請求的json報文是固定的,例如{"name":"張三","id":"197"},這樣僅能處理單個用戶,當咱們想處理多個用戶,每一個用戶有多個屬性信息時就不是很方便。咱們想僅僅提供一批須要處理的用戶Id的json報文,例如sql
{ "students": [ [ { "id":"197" }, { "id":"198" }, { "id":"199" } ] ] }
ESB項目解析這樣的json報文,根據id從數據庫裏讀取這些學生的詳細信息,再經過Data Weaver的轉換爲xml報文,輸出如下的xml響應報文:數據庫
<?xml version="1.0" encoding="UTF-8" ?> <Students> <Student> <name>張三</name> <id>197</id> <class>1年1班<class> </Student> <Student> <name>李四</name> <id>198</id> <class>1年2班</class> </Student> <Student> <name>趙五</name> <id>199</id> <class>1年3班</class> </Student> </Students>
根據id從數據庫裏讀取數據咱們可使用Mule ESB提供的jdbc connector,直接鏈接數據庫執行sql查詢,因爲咱們這裏討論spring集成,咱們使用spring jdbc template進行訪問。express
ESB訪問的數據庫咱們使用MySql 5.5,新建一個test數據庫,編碼集使用utf-8,再在這個數據庫下新建一個students表,建表sql爲json
CREATE TABLE `students` ( `ID` int(10) NOT NULL, `NAME` varchar(255) NOT NULL, `CLASS` varchar(255) NOT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
初始化表數據的sql爲app
INSERT INTO `students` VALUES ('197', '張三', '1年1班'); INSERT INTO `students` VALUES ('198', '李四', '1年2班'); INSERT INTO `students` VALUES ('199', '趙五', '1年3班'); INSERT INTO `students` VALUES ('200', '王六', '1年4班'); INSERT INTO `students` VALUES ('201', '孫七', '2年1班');
這樣就創建了ESB項目須要訪問的數據庫。框架
第二步須要在ESB項目中引入Spring Jdbc訪問,咱們首先恢復ESB項目的Maven支持,而後在pom文件中引入spring的庫包(Mule ESB EE 3.8.0 M1版本自帶Spring Framework版本爲 4.1.6,若是用戶想使用不一樣版本的Spring Framework,能夠自行在pom文件中配置,這裏咱們使用最新的4.3.0 RELEASE版本)ide
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.3.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.0.RELEASE</version> </dependency>
再定義Student類,對應studens表的單行記錄
package com.mule.spring.entity; public class Student { private Integer id; private String name; private String className; ............
定義StudentService接口,定義根據Id列表從studens表讀取student的Service層
package com.mule.spring.service; import java.util.List; import com.mule.spring.entity.Student; public interface StudentService { List<Student> getStudentsByIds(List<String> ids); }
再定義StudentDao接口,定義根據Ids列表從students表讀取student的Dao層,它的實現類使用spring jdbc template執行具體的查詢命令,而且使用了我自定義的Mapper轉換查詢結果爲Student類對象。
package com.mule.spring.service.impl; @Service("studentService") public class StudentServiceImpl implements StudentService { @Override public List<Student> getStudentsByIds(List<String> ids) { // TODO Auto-generated method stub return null; } } package com.mule.spring.dao; public interface StudentDao { List<Student> getStudentsByIds(List<String> ids); } package com.mule.spring.dao.impl; @Component("studentDao") public class StudentDaoImpl implements StudentDao { @Autowired private JdbcTemplate jdbcTemplate; @Override public List<Student> getStudentsByIds(List<String> ids) { String idListStr = Joiner.on(',').join(ids); String sql = "select * from students where id in (" + idListStr + ")"; List<Student> studentList =jdbcTemplate.query( sql, new StudentMapper()); return studentList; } ............
這裏咱們使用guava庫用於從id列表得到id字符串,咱們使用的guava版本是19.0
添加完訪問Students表所需的Service和Dao類後,咱們須要在流程中引入Service接口。
打開ESB項目流程圖,咱們在Http Listener節點和DataWeaver節點間拖入一個Java Transformer,自定義一個Customer類,繼承自AbstractJsonTransformer,爲了引入AbstractJsonTransformer接口,咱們須要修改pom文件,添加mule-module-json jar包
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>19.0</version> </dependency> <dependency> <groupId>org.mule.modules</groupId> <artifactId>mule-module-json</artifactId> <version>${mule.version}</version> <scope>provided</scope> </dependency>
修改後的流程圖和Data Weaver映射關係圖以下所示
咱們在自定義的Transformer中引入Service
public class CustomJsonTransformer extends AbstractJsonTransformer { @Autowired protected StudentService studentService; @Override public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException { String transformJsonStr = null; try { String jsonMessage = message.getPayloadAsString(); //添加信息 JSONObject jsonMap = updateStudentInfos(jsonMessage); transformJsonStr = jsonMap.toJSONString(); } ............. private JSONObject updateStudentInfos(String originalJsonStr) { JSONObject studentsJsonObj = null; try { studentsJsonObj = JSONObject.parseObject(originalJsonStr); JSONArray studentMapArray = studentsJsonObj.getJSONArray("students"); //從請求json報文中讀取student的id列表 List<String> idList = new ArrayList<String>(); int length = studentMapArray.size(); for(int i=0;i<length;i++) { JSONObject studentMap = studentMapArray.getJSONObject(i); String id = studentMap.getString("id"); idList.add(id); } //根據student的id列表從數據庫中讀取student信息 List<Student> studentList = studentService.getStudentsByIds(idList); //將student信息填充到json報文中。 for(int j=0;j<length;j++) { JSONObject studentMap = studentMapArray.getJSONObject(j); Student student = studentList.get(j); String name = student.getName(); String className = student.getClassName(); studentMap.put("name", name); studentMap.put("class", className); } studentsJsonObj.put("students", studentMapArray); } catch(Exception ex) { ex.printStackTrace(); } return studentsJsonObj;
咱們先導入mysql connector庫
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.39</version> </dependency>
再在src/main/app下新建一個conf文件夾,在下面新建applicationContext.xml文件
在src/main/resources下新建jdbc.properties文件
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8 jdbc.username=root jdbc.password=admin
applicationContext.xml的內容爲:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"> <context:annotation-config/> <context:property-placeholder ignore-unresolvable="true" location="classpath*:/jdbc.properties" /> <context:component-scan base-package="com.mule.spring"> <context:include-filter type="regex" expression="org.springframework.stereotype.Service" /> </context:component-scan> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> </beans>
最後在ESB項目流程文件中使用spring:import標籤導入applicationContext.xml文件
<spring:beans> <spring:import resource="classpath:conf/applicationContext.xml"/> </spring:beans>
到此爲止,ESB項目便與Spring Framework集成在一塊兒了,不過要運行這個ESB項目,須要將mysql connector jar文件拷貝到Mule ESB運行時的lib/opt目錄下,不然在調用ESB接口時會出現No Suitable Driver的異常
最後運行ESB項目,經過Advanced Rest Client調用ESB接口
ESB項目啓動時,mule-module-spring-config jar包中的SpringXmlConfigurationBuilder類會加載流程文件中import的applicationContext.xml文件,加載了Spring Context對象
MuleArtifactContext類對象(繼承自AbstractXmlApplicationContext類),再加載流程文件中自身定義的元素,能夠理解爲MuleArtifactContext容器中包含了MuleContext容器,所以在查找Bean定義時,先從MuleContext容器中查找,再到父容器MuleArtifcatContext容器中查找,然而這兩個Context容器的包容關係僅限於經過Mule ESB運行時環境啓動ESB項目時才能構建,若是ESB項目改爲了Web項目,這一關係將不復存在,接下來咱們將看到這一點。