在CXF+S2SH服务端集成时,遇到很多问题。
主要是jar不兼容的问题。
CXF 2.6 + Hibernate3+struts2.0+spring3.0
1、首先看Root项目服务端的配置:
Action只是测试调用服务端cxf-springDemo用的
Struts2Filter : 继承FilterDispatcher类,过滤cxfServlet的路径,以免struts2的过滤器将其过滤掉了。
Struts.properties: struts.action.excludePattern=/webservice/.*
配置struts2的过滤机制,不过滤路径为webservice/.*的URL,
这个URL为CXF占用,等下在web.xml会配置的。
SpringService : 对外提供的接口 注意:在接口类名上要使用注解@WebService,
SpringServiceImpl :实现SpringService接口,对于服务端需要实现里面的方法。
注意:对于实现类要使用DAO层对象操作数据库,需要使用注解注入DAO层对象。如下:
//此处要采用注解注入
@Component("SpringService")
@WebService(endpointInterface="com.spring.service.SpringService",targetNamespace=http://service.spring.com/)
public class SpringServiceImpl implements SpringService {
JeNewsDAO JeNewsDAO ;
@Resource(name="JeNewsDAO")
public void setJeNewsDao(JeNewsDAO JeNewsDAO) {
this.JeNewsDAO = JeNewsDAO;
}
2、 新建applicationContext.xml ,专门配置cxf webservice:
<?xml version="1.0" encoding="UTF-8"?>
<!-- START SNIPPET: beans -->
<beans xmlns=http://www.springframework.org/schema/beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws=http://cxf.apache.org/jaxws
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<!—以下三个文件在cxf.jar包中的META-INF下面可以看到 -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<!-- cxf+ssh服务端配置 ,就要写实现类,开启服务端 -->
<jaxws:endpoint id="springService"
implementor="com.spring.service.impl.SpringServiceImpl"
address="/eshop" />
</beans>
3、 web.xml配置:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- 注意:CXFservlet要写在contextLoaderListener后面, struts2 Filter的前面 -->
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 需要注意:cxfServlet与struts2的URL 不能都写/*,需要区分 -->
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/webservice/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>s2</filter-name>
<filter-class>
com.spring.filter.Struts2Filter <!—这个filter是自已写的继承了FilterDispatcher -->
</filter-class>
</filter>
<filter-mapping>
<filter-name>s2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
OK啦,服务端配好了。
CXF+S2SH客户端的配置如下:
1、服务端项目打包
首先将服务端的com.spring下的类进行打包,客户端在调用服务端接口时需要引入这个jar包:
如果接口的实现类中用到了实体类,则把实体类复制到SpringService接口的同级包下
如下:JeChannel,JeClass,JeNews都是实体类
并在这些实体类上加上@XmlType (namespace="http://service.spring.com/")
以区分MODEL中的实体类,避免报以下错误:
Two classes have the same XML type name,请使用 @XmlType.name 和 @XmlType.namespace 为类分配不同的名称
打包的类有:com.spring包下的和MODEL中引用到的实体类,如:JeChannel,JeClass,JeNews
创建一个新项目,配置与上面服务端项目一样,
1、com.spring.action.SpringAction类的代码如下:
package com.spring.action;
import java.util.ArrayList;
import java.util.List;
import com.cxf.service.CXFService;
import com.lxsoft.model.JeChannel.JeChannel;
import com.lxsoft.model.JeClass.JeClass;
import com.lxsoft.model.JeNews.JeNews;
import com.moss.portal.category.Category;
import com.moss.portal.information.Information;
import com.opensymphony.xwork2.ActionSupport;
import com.spring.service.SpringService;
public class SpringServiceAction extends ActionSupport {
private SpringService client;// 服务1
private CXFService client2;// 服务2
private List<Information> newsList; //数据测试
private List<JeNews> newsList2;//
//getter setter .... 省略
/**
* 测试显示服务端1中的信息 注意将服务端的包加载进来,
*/
public String toDemo1() {
try {
this.newsList = this.client.findAll();
} catch (Exception e) {
System.out.println("获取 信息异常......");
e.printStackTrace();
}
return SUCCESS;
}
/**
* 测试显示服务端2 中的所有信息 注意将服务端2的包加载进来
*/
public String toDemo2() {
try {
this.newsList2 = this.client2.findAllNews();
} catch (Exception e) {
System.out.println("获取 信息异常......");
e.printStackTrace();
}
return SUCCESS;
}
/**
* 将服务端1信息转入到服务端2的数据库
*/
public String toConvert() {
try {
// 1、获取所有服务端1数据库信息
this.newsList = this.client.getInformations();
// 2、遍历信息,将信息填充到服务端2数据库
for (Information f : this.newsList) {
JeNews jeNews = new JeNews();
jeNews.setTitle(f.getTitle());
jeNews.setContent(f.getContent());
// 保存到服务端2的数据库中
this.client2.saveNews(jeNews);
}
} catch (Exception e) {
System.out.println("获取 信息异常......");
e.printStackTrace();
return INPUT;
}
return SUCCESS;
}
}
1、修改后的applicationContext.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- START SNIPPET: beans -->
<beans xmlns=http://www.springframework.org/schema/beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws=http://cxf.apache.org/jaxws
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<!—以下三个文件在cxf.jar包中的META-INF下面可以看到 -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<!-- cxf+SSH客户端配置 无需写实现类,开启客户端-->
<bean id="client" class="com.spring.service.SpringService" factory-bean="clientFactory" factory-method="create"/>
<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="com.spring.service.SpringService"/>
<!-- 这里指定服务端地址,在action类中可以调用对应接口类的方法 -->
<property name="address" value=http://localhost:8080/cxf-spring/webservice/SpringServer></property>
</bean>
<!-- 可以同时开启多个客户端-->
<bean id="client2" class="com.spring.service.SpringService" factory-bean="clientFactory2" factory-method="create"/>
<bean id="clientFactory2" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="com.spring.service.SpringService"/>
<!-- 这里指定服务端地址,在action类中可以调用对应接口类的方法-->
<property name="address" value="http://localhost:8080/demo/webservice/testService"/>
</bean>
<bean id="SpringAction" class="com.spring.action.SpringServiceAction" scope="prototype">
<property name="client" ref="client"/>
<property name="client2" ref="client2"/>
</bean>
</beans>
配置struts.xml 的action,(因为会在action类中调用服务端的接口了):
以下这段配置通常会写在strus.xml文件的最末尾,以免与其它配置加载发生冲突。
<constant name="struts.objectFactory" value="spring" />
<constant name="struts.devMode" value="true" />
<package name="cxf-spring" extends="struts-default">
<action name="hello" class="SpringAction" method="toDemo1">
<result>/index.jsp</result>
</action>
<action name="hello2" class="SpringAction" method="toDemo2">
<result>/index2.jsp</result>
</action>
<action name="convert" class="SpringAction" method="toConvert">
<result>/success.jsp</result>
</action>
</package>
布署服务端和客户端项目,运行
访问地址:http://localhost:8080/hello 可以显示服务端1的信息
http://localhost:8080/hello2 可以显示服务端2的信息
http://localhost:8080/convert 可以将服务端1的信息导入到服务端2的数据库中