cxf发布webservice

注解和spring配置相结合

使用cxf与spring集成发布webservice的是非常方便的,下面简单写下基本的步骤以备忘.

1.首先当然是引用cxf相关的jar包.这里使用的是2.7.5的版本.

2.在web.xml文件中配置CXFServlet

	<servlet>
		<servlet-name>CXFServlet</servlet-name>
		<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
		<load-on-startup>0</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>CXFServlet</servlet-name>
		<url-pattern>/ws/*</url-pattern><!--CXFServlet拦截RootPath/ws/*的请求-->
	</servlet-mapping>


3.在spring配置文件中配置基本的cxf组件

	<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"/>


4.编写需要发布的POJO类

接口

@WebService(targetNamespace=Constants.TARGETNAMESPACE) 
public interface TestWebService {
	@WebMethod(operationName="SendMessage",action="http://xxx.xxx.Webservice/SendMessage")
	@WebResult(name="SendMessageResult",targetNamespace="http://yyy.yyy.Webservice/")
	public String receiveMsg(@WebParam(name="msg",targetNamespace=Constants.TARGETNAMESPACE) String msg);
}

@WebMethod的属性operationName的值对应wsdl中的operationName,也即ws客户端所谓的方法名称。action的值对应soapAction的值。

@WebResult的属性name,ws会参数转换成xml的格式进行传递,而属性name指定该xml的根节点的名称;targetNameSpace则指定该名称所属的命名空间

@WebParam的属性name指定参数的名称,java虚拟机编译源文件时,通常情况下参数名称不会记录,而会用arg1,arg2之类的替换,转换成xml后对应的节点名称则为<arg0></arg0>,设置name属性可以指定该xml节点的名称为<msg></msg>.

实现

@WebService(serviceName="TestWebService", targetNamespace=Constants.TARGETNAMESPACE, endpointInterface="ws.TestWebService")
public class TestWebServiceImpl implements TestWebService {
	@Override
	public String receiveMsg(String msg) {
              return "接收成功";
	}	
}

serviceName对应wsdl中的<wsdl:service name="TestWebService">中的name.

endpointInterface为该实现类的接口的全限定名称.

5.在spring配置文件中发布该pojo为webservice

 <jaxws:endpoint address="SendMessage" 
	 implementor="ws.impl.TestWebServiceImpl">  
 </jaxws:endpoint>  

address指定了该webservice对应的URI,结合web.xml文件中的CXFServlet配置,访问该webservice的Url为

http://hostip:port/WebRoot/ws/SendMessage

wsdl链接为

http://hostip:port/WebRoot/ws/SendMessage?wsdl

6.部署并通过wsdl链接来验证webservice是否发布成功.

以上发布webservice的方法会把接口中所有的方法发布成webservice接口

 

零配置发布pojo为webservice

第1,2,3步与上面一致.

4.编写需要发布的pojo类

接口

public interface TestWebService {
     public String receiveMsg(String msg);
     public String sendMessage(String msg);
}

实现

public class TestWebServiceImpl implements TestWebService {
	@Override
	public String receiveMsg(String msg) {
              return "接收成功";
	}
         @Override
         public String sendMessage(String msg) 
         { 
              return "接收成功";
         }	
}

5.发布pojo类为webservice

                  ReflectionServiceFactoryBean rsfb = new ReflectionServiceFactoryBean();
		List<Method> list = new ArrayList<Method>();
		Class clazz = Thread.currentThread().getContextClassLoader().loadClass("ws.impl.TestWebService");
		Method [] methods = clazz.getDeclaredMethods();
		for(int i=0;i<methods.length;i++){
			if(methods[i].getName().equals("sendMessage")){
				list.add(methods[i]);
			}
		}
                  //设置需要过滤到的方法,既这些方法不需要被发布成webservice接口
		rsfb.setIgnoredMethods(list);
                  //指定endpointName
		rsfb.setEndpointName(new QName("TestEndpointName"));
		//指定serviceName
		rsfb.setServiceName(new QName("http://lqin.szse.cn/test","ServiceName1",XMLConstants.DEFAULT_NS_PREFIX));
		List<AbstractServiceConfiguration>  listAsc = rsfb.getServiceConfigurations();
		if(listAsc == null){
			listAsc = new ArrayList<AbstractServiceConfiguration>();
		}
		
		listAsc.add(new AbstractServiceConfiguration(){
                            //设置soapAction为"http://lqin.com/sa",可以根据不同的方法返回不同的soapAction
			@Override
			public String getAction(OperationInfo op, Method method) {
				return "http://lqin.com/sa";
			}
                            //设置发布的webservice方法名称,此处可以根据不同的方法返回不同的方法名称
			@Override
			public QName getOperationName(InterfaceInfo service, Method method) {
				return new QName("CustomOperationName");
			}
			
		});
		
		ServerFactoryBean sfb = new ServerFactoryBean(rsfb);
		Object o = SpringUtils.getBean(serviceBeanId);
		sfb.setServiceClass(clazz);
		sfb.setServiceBean(new TestServiceImpl());
		sfb.setAddress("/test");
		sfb.create();

在前一节中,是通过注解和spring配置的方式配置webservice的,那么在零配置的情况下webservice所需的参数从哪里来呢?答案在于

List<AbstractServiceConfiguration> listAsc = rsfb.getServiceConfigurations();

在获取某一个属性的值时,比如operationName,会遍历listAsc中的AbstractServiceConfiguration#getOperationName方法并返回第一个不为null的值,否则返回空字符串.

ReflectionServiceFactoryBean默认注册了一个DefaultServiceConfiguration,该ServiceConfiguration会返回系统默认生成的属性值,比如operationName默认是方法的名称,soapAction默认为空.如此,如果想要自定义opertaionName的值,那么必须先删除DefaultServiceConfiguration再实现一个AbstractServiceConfiguration返回operationName,或者把返回自定义的operationName放到DefaultServiceConfiguration的前面(建议自定义的放前面).

在上面的代码中,我们提供了一个AbstractServiceConfiguration的实现并重写了getAction方法和getOperationName方法,并且把它加到了DefaultServiceConfiguration的后面,根据上面的分析,soapAction自定义有效,而operationName则无效.

将上面的代理在servlet容器启动之后执行,访问

http://hostip:port/WebRoot/ws/test?wsdl路径可以看到webservice发布成功.

附上ServerFactoryBean#create()方法应用AbstractServiceConfiguration的执行路径:

ServerFactoryBean#create

AbstractWSDLBasedEndPointFactory#createEndPoint

ReflectionServerFactoryBean#create

ReflectionServerFactoryBean#initializeServiceModel

ReflectionServerFactoryBean#buildServiceFromClass//这里还有一个方法叫做buildServiceFromWSDL

ReflectionServerFactoryBean#createInterface

ReflectionServerFactoryBean#createOperation

ReflectionServerFactoryBean#getOperationName

 

 



 




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值