尽管aar环境非常象WEB-INF/class, 但aar不提供classpath的环境
服务代码:
package com.machome.test;
import com.machome.model.Student2;
public class TestHibernate {
public static void main(String[] args) {
System.out.println(findById(3));
}
public static String findById(int id) {
Configuration cfg = new Configuration();
SessionFactory sf =null;
Session session = null;
Transaction tran = null;
try {
sf =cfg.configure().buildSessionFactory();
session = sf.openSession();
tran = session.beginTransaction();
Student2 stu = (Student2)session.get(Student2.class, id);
return stu.getName();
} catch (HibernateException e) {
e.printStackTrace();
return null;
}finally{
tran.commit();
session.close();
sf.close();
}
}
}
我们执行的ant target如下: 生成aar文件,形成类似WEB-INF/classes的目录结构
<target name="generate.service" depends="compile.service">
<!--copy services.xml -->
<copy toDir="${service.target}/classes" fail>
<fileset dir="${basedir}/resources">
<include name="**Test.class" dir="${service.target}/classes"/>
</jar>
</target>
形成的TestHibernate.aar包结构如下:
TestHibernate.aar
|----com
|--machome
|--model
|-- Student2.class
|-- Student2.hbm.xml
|--test
|-- TestHibernate.class
|---META-INF
|--MANIFEST.MF
|--services.xml
|---hibernate.cfg.xml
而实际部署到axis2项目的后果:
- hibernate.cfg.xml放在aar内,axis2项目报错找不到
- service 类 调用其他实体类(Student2),但实体类放在aar中没用,axis2项目报错找不到
- hibernate如果采用hbm mapping文件(Student2.hbm.xml),则hbm mapping放在aar中没用,axis2项目报错找不到
解决法1:按普通项目部署,将需要的配置文件,类文件,库部署到axis2项目的buildpath(比如:WEB-INF/classes和lib
--src----
|--com.machome.model
|--Student2.java
|--Student2.hbm.xml
|--hibernate.cfg.xml
--webroot--
|--WEB-INF
|-classes
|--com.machome.model
|-- Student2.class
|-- Student2.hbm.xml
|--hibernate.cfg.xml
|-lib
|-- jar file
|-conf
|-modules
|-services
|-TestHibernate.aar
这是最常见的解决办法, 目前google和百度上能搜索到的都是这个解决办法.
其实这个解决办法也是最合理的,多数人甚至并没有通过网上搜索解决,完全自己就能想出来,毕竟支持文件和库找不到,肯定是build path和classpath出问题,而众所周知的build path其实就两种:1.classpath环境变量指定 2.webcontainer 的WEB-INF/classes和lib
问题的原因和原理:
AXIS2 没对每个service 设置专门的classloader, 而是实现一个统一的classloader,由这个classloader管理所有的service
这个统一的classloader实现了一些特殊的功能,比如service间的隔离,避免部署多个service时有可能出现的同名类和库的冲突
知道了原理,就可以推导出解决办法:为每个service设置单独的classloader,(实际是为每个service的每个线程设置单独的classloader--Thread Context ClassLoader(TCCL))
解决法2:很简单,在services.xml加下面一句
<parameter name="ServiceTCCL">composite</parameter>
例子:
<service name="TestHibernate" scope="application" targetNamespace="http://quickstart.samples/">
<description>
TestHibernate Service
</description>
<messageReceivers>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only"
class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
<schema schemaNamespace="http://quickstart.samples/xsd"/>
<parameter name="ServiceClass">com.machome.test.TestHibernate</parameter>
<parameter name="ServiceTCCL">composite</parameter>
</service>
部署:
--src----
--webroot--
|--WEB-INF
|-classes
|-lib
|-conf
|-modules
|-services
|-TestHibernate.aar
|-TestHibernateAnon.aar
|-Student.aar
同时部署多个相互之间没有关系的服务
测试:
http://localhost:8080/axis2/services/TestHibernate/findById?id=2
结果:
<ns:findByIdResponse>
<ns:return>mac</ns:return>
</ns:findByIdResponse>