(7)中在ESB项目中集成了Spring项目,但是在移植到Web项目并不能原样移植过去,需要做一些修改。
1.首先将ESB项目新增的代码文件,配置文件和第三方pom引用更新到Web项目中。
2.修改pom文件中的maven-war-plugin,将conf目录下的applicationContext.xml文件拷贝到WEB-INF/conf目录下:
<resource>
<targetPath>WEB-INF/conf</targetPath>
<directory>src/main/app/conf</directory>
<includes>
<include>*.xml</include>
</includes>
</resource>
再在流程文件中修改导入applicationContext.xml文件的路径
<spring:beans>
<spring:import resource="WEB-INF/conf/applicationContext.xml"/>
</spring:beans>
这样修改好后,部署到tomcat运行时,将会出现以下异常:
java.io.FileNotFoundException:
Cannot create a relative resource for resource WEB-INF/testproject.xml
修改上面的targetPath为WEB-INF, import resources path为"applicationContext.xml",仍然会出现这样的问题,这表示mule在加载applicationContext.xml文件时,无法从流程文件的路径找到applicationContext.xml的相对路径,加载失败,最后我们将targetPath设置为WEB-INF/classes,resources path设置为“classpath*:/applicationContext.xml”,启动时不再出现找不到相对路径的错误,但是又抛出了以下异常:
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Unexp
ected exception parsing XML document from URL [file:/D:/tomcat7/apache-tomcat-7.
0.69/webapps/testproject/WEB-INF/classes/applicationContext.xml]; nested excepti
on is org.springframework.beans.FatalBeanException: Class [org.springframework.c
ontext.config.ContextNamespaceHandler] for namespace [http://www.springframework
.org/schema/context] does not implement the [org.springframework.beans.factory.x
ml.NamespaceHandler] interface
但是查看Spring的源码,ContextNamespaceHandler类明明实现了NamespaceHandler接口的,定位这个问题的原因找了很久。
首先我在google上查到是因为没有导入spring的web和webmvc jar包,可是当我在项目中添加了spring web和spring web mvc两个jar包的引用后,启动仍然会报这个错误。后来我想到了,mule在加载spring配置文件时,是使用它自带的spring 4.1.6的库,而我的项目引入了spring 4.3.0的库,导致mule加载spring配置文件时,类加载出现了库冲突,从而导致了这个问题。
在anystudio中启动ESB项目时,mule ESB运行时优先加载运行时环境下的spring 4.1.6库文件,因此不存在此问题。
找到这个原因后,解决方案就简单了,在web项目的pom文件中,将所有引用到spring库的dependency的scope都设置为provided,不包含到生成的war包中,运行时直接使用mule lib目录下自带的spring 4.1.6库。修改好后重新部署web项目,启动时Web项目正常启动。
但是当我调用Web项目接口时,后台抛出No Suitable Driver for jdbc:mysql........的异常信息,这个问题和ESB项目运行时的问题是一样的,解决方案也相同,将mysql driver jar包拷贝到mule的lib目录下,使得mule加载spring配置文件时,能找到对应的数据库驱动,建立对应的数据源,从而成功初始化Jdbc Template,当然在pom文件中同样要把mysql的jar引用scope改为provided。
复制完成后重新启动项目,调用Web接口,获得的结果和ESB项目完全一致,说明我们对集成了Spring的ESB项目的改造完全成功。
然而这个Web项目的改造还存在问题,如果存在多个ESB项目改造的Web项目,这些Web项目都使用共通的数据源配置,如果还是在每个项目里都设置数据源连接信息,不仅会出现配置信息冗余,而且会给将来的配置更新带来麻烦,因此我们想到了使用Tomcat Data Source,在Tomcat的配置文件中配置数据源,而在Web项目中使用JNDI方式访问这个数据源。
我们先在Tomcat的server.xml文件里添加Tomcat的Data Source配置
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
<Resource name="jdbc/TestDB"
global="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource"
username="root"
password="admin"
url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8"
driverClassName="com.mysql.jdbc.Driver"
initialSize="10"
maxWaitMillis="15000"
maxTotal="75"
maxIdle="20"
maxAge="7200000"
testOnBorrow="true"
validationQuery="select 1"
/>
</GlobalNamingResources>
再修改context.xml文件,添加以下配置
<ResourceLink name="jdbc/MyLocalDB"
global="jdbc/TestDB"
auth="Container"
type="javax.sql.DataSource" />
最后修改applicationContext.xml,添加对JNDI DataSource的引用
<jee:jndi-lookup expected-type="javax.sql.DataSource"
id="dataSource" jndi-name="java:comp/env/jdbc/MyLocalDB"/>
在applicationContext.xml的头部添加jee的prefix定义
xmlns:jee="http://www.springframework.org/schema/jee"
.............
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
最后将mysql connector的jar文件拷贝到tomcat的lib目录下
重新运行Tomcat,调用Web接口,结果和使用spring jdbc template的效果一样。