springboot/spring项目中整合cxf需要经过以下几个步骤:
- 添加cxf依赖。
- 新建webservice接口。
- 注册和发布webservice服务。
1. 添加cxf依赖:
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.1.12</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.1.12</version>
</dependency>
2. 新增webservice接口
2.1 新增接口:
package com.test.webservices.inter;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService
public interface UserService {
@WebMethod
public String hello(@WebParam(name = "name") String name);
}
新增的服务接口必须加上@WebService注解,方法必须有@WebMethod。否则在注册时将无法注册该方法。
2.2 新增服务实现:
package com.test.webservices.impl;
import javax.jws.WebService;
import org.springframework.stereotype.Service;
import com.test.webservices.inter.UserService;
@WebService(targetNamespace="http://impl.webservices.test.com/",endpointInterface = "com.test.webservices.inter.UserService")
@Service
public class UserServiceImpl implements UserService {
@Override
public String hello(String name) {
return "hello:"+name;
}
}
实现的类一定要有@WebService注解,并且指明targetNamespace和endpointInterface,targetNamespace通常是你实现类所在包的倒序,endpointInterface为该实现类实现的接口。
添加@Service注解可以让spring管理,可以依赖注入其他service或者dao。
3. 注册和发布webservice服务。
package com.test.webservices;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.test.webservices.inter.UserService;
@Configuration
public class WebServiceConfig {
@Bean
public ServletRegistrationBean<CXFServlet> cxfServlet() {
return new ServletRegistrationBean<CXFServlet>(new CXFServlet(), "/service/*");// 发布服务名称
}
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
@Bean
public EndpointImpl publishUser(Bus bus, UserService userService) {
EndpointImpl end = new EndpointImpl(bus, userService);
end.publish("/UserService");
return end;
}
}
cxfServlet方法配制了webservice发布的路径。
springBus方法配制的实例供publishUser方法和其他发布的方法使用。
publishUser方法为服务发布方法,发布后就可以把服务暴露出来,并且指定了服务发布的地址。
4. 运行测试。
上述配置和动作完成之后,启动项目完成之后访问:
http://localhost:8080/service/UserService?wsdl
可以看到如下内容:
<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://impl.webservices.test.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns2="http://schemas.xmlsoap.org/soap/http" xmlns:ns1="http://inter.webservices.test.com/" name="UserServiceImplService" targetNamespace="http://impl.webservices.test.com/">
<wsdl:import location="http://localhost:8080/service/UserService?wsdl=UserService.wsdl" namespace="http://inter.webservices.test.com/">
</wsdl:import>
<wsdl:binding name="UserServiceImplServiceSoapBinding" type="ns1:UserService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="hello">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="hello">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="helloResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="UserServiceImplService">
<wsdl:port binding="tns:UserServiceImplServiceSoapBinding" name="UserServiceImplPort">
<soap:address location="http://localhost:8080/service/UserService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
说明项目webservice服务发布是成功的。
4. webservice接口测试
把上面的内容保存之后到项目的/src/main/resources下,命名为UserService.wsdl。
点击文件:Web Services->Generate Client
点击完成后生成测试代码。生成测试代码后一半会报错,需要引用如下依赖:
<dependency>
<groupId>org.apache.axis</groupId>
<artifactId>axis-jaxrpc</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>com.barchart.wrap</groupId>
<artifactId>barchart-wrap-axis</artifactId>
<version>1.4-build003</version>
</dependency>
<dependency>
<groupId>commons-discovery</groupId>
<artifactId>commons-discovery</artifactId>
<version>20040218.194635</version>
</dependency>
编写测试代码:
package com.test.webservices;
import java.rmi.RemoteException;
import com.test.webservices.inter.UserService;
import com.test.webservices.inter.UserServiceProxy;
public class UserServiceTest {
public static void main(String[] args) {
UserServiceProxy proxy = new UserServiceProxy();
UserService service = proxy.getUserService();
try {
System.out.println(service.hello("test"));
} catch (RemoteException e) {
e.printStackTrace();
};
}
}
测试运行后执行结果为:
如果看到如上结果,说明测试是正确的。
5.自动注册webservice接口
本文讲解如何在spring中集成webservice,以及发布后如何测试,文章最后给上自动注册发布含有@WebService注解的service代码:
package com.test.webservices;
import javax.jws.WebService;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
public class WebServiceConfig2 implements BeanFactoryPostProcessor {
@Bean
public ServletRegistrationBean<CXFServlet> cxfServlet() {
return new ServletRegistrationBean<CXFServlet>(new CXFServlet(), "/service/*");// 发布服务名称
}
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] names = beanFactory.getBeanNamesForAnnotation(WebService.class);
for (String name : names) {
BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) beanFactory;
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(EndpointImpl.class);
beanDefinitionBuilder.addConstructorArgReference(Bus.DEFAULT_BUS_ID);
beanDefinitionBuilder.addConstructorArgReference(name);
String beanName = name.replace("Impl", "") + "Endpoint";
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
EndpointImpl b = (EndpointImpl) beanFactory.getBean(beanName);
b.publish("/" + name.replace("Impl", ""));
}
}
}
有兴趣的小伙伴可以研究改进下。
最后附上本文的项目源码下载地址: