什么是Webservice
WebService是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Internet进行基于Http协议的网络应用间的交互。 其实WebService并不是什么神秘的东西,它就是一个可以远程调用的类,或者说是组件,把你本地的功能开放出去共别人调用。
## HttpClient和WebService的区别二者都是调用对方服务接口,区别在于:
- HttpClient用来调用服务,它是模拟一个浏览器,发送Http的请求,服务器会返回请求的一个响应结果,Httpclient然后把响应的结果取出来。HttpClinet相当于一个客户端,使用Http协议调用系统中的方法或者接口。
- webService是使用soap协议而不是Http协议。
什么是soap协议
SOAP 是基于 XML 的简易协议,可使应用程序在 HTTP 之上进行信息交换。或者更简单地说:SOAP 是用于访问网络服务的协议。
SOAP 消息实列:
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Header>
...
...
</soap:Header>
<soap:Body>
...
...
<soap:Fault>
...
...
</soap:Fault>
</soap:Body>
</soap:Envelope>
SpringBoot使用CXF集成WebService
添加依赖
<!--cxf-->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.1.6</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>3.1.6</version>
</dependency>
<!--axis-->
<dependency>
<groupId>org.apache.axis</groupId>
<artifactId>axis</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.apache.axis</groupId>
<artifactId>axis-jaxrpc</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-discovery</groupId>
<artifactId>commons-discovery</artifactId>
<version>0.2</version>
</dependency>
创建服务端接口
@WebService(name = "DemoWebService", // 暴露服务名称
targetNamespace = "http://service.webservicedemo.example.com"// 命名空间,一般是接口的包名倒序
)
public interface DemoWebService {
String sayHello(String message);
}
服务端接口实现
@WebService(
serviceName = "DemoService", // 与接口中指定的name一致
targetNamespace = "http://service.webservicedemo.example.com", // 与接口中的命名空间一致,一般是接口的包名倒
endpointInterface = "com.example.webservicedemo.service.DemoWebService" // 接口地址
)
public class DemoWebServiceImpl implements DemoWebService {
@Override
public String sayHello(String message) {
return message+",现在时间:"+"("+new Date()+")";
}
}
CXF配置
@Configuration
public class CxfConfig {
@Bean
public ServletRegistrationBean createServletRegistrationBean() {
return new ServletRegistrationBean(new CXFServlet(),"/demo/*");
}
@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
return new SpringBus();
}
@Bean
public DemoWebService demoService() {
return new DemoWebServiceImpl();
}
@Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(springBus(), demoService());
endpoint.publish("/api");
return endpoint;
}
}
启动SpringBoot服务,输入http://localhost:8090/demo/api?wsdl即可。
使用单元测试模拟客户端
使用cxf模拟请求
@SpringBootTest
class WebServiceDemoApplicationTests {
@Test
void contextLoads1() {
//创建动态客户端
JaxWsDynamicClientFactory factory = JaxWsDynamicClientFactory.newInstance();
Client client = factory.createClient("http://localhost:8090/demo/api?wsdl");
// 需要密码的情况需要加上用户名和密码
//client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME,PASS_WORD));
HTTPConduit conduit = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(2000); //连接超时
httpClientPolicy.setAllowChunking(false); //取消块编码
httpClientPolicy.setReceiveTimeout(120000); //响应超时
conduit.setClient(httpClientPolicy);
//client.getOutInterceptors().addAll(interceptors);//设置拦截器
try{
Object[] objects = new Object[0];
// invoke("方法名",参数1,参数2,参数3....);
objects = client.invoke("sayHello", "xxx");
System.out.println("返回数据:" + objects[0]);
}catch (Exception e){
e.printStackTrace();
}
}
}
运行结果
使用axis模拟请求
@SpringBootTest
class WebServiceDemoApplicationTests {
@Test
void contextLoads2() throws ServiceException, RemoteException, MalformedURLException {
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(new URL("http://localhost:8090/demo/api?wsdl"));
call.setOperationName(new QName("http://service.webservicedemo.example.com","sayHello"));
// call.setUseSOAPAction(true);
// call.setSOAPActionURI("http://service.webservicedemo.example.com"+"sayHello");
call.addParameter(new QName("http://service.webservicedemo.example.com", "message"), XMLType.XSD_STRING, ParameterMode.IN);
call.setReturnType(XMLType.XSD_STRING);
call.setTimeout(10000);
call.setEncodingStyle("utf-8");
//设置命名空间和需要调用的方法名
Object invoke = call.invoke(new Object[]{"xxx"});
System.out.println(invoke.toString());
}
}
运行时,会报一个元素错误。
需要暴露服务端的接口以及参数。
@WebService(name = "DemoWebService", // 暴露服务名称
targetNamespace = "http://service.webservicedemo.example.com"// 命名空间,一般是接口的包名倒序
)
public interface DemoWebService {
//暴露接口 参数
@WebMethod
String sayHello(@WebParam(name = "message",targetNamespace = "http://service.webservicedemo.example.com") String message);
}
运行结果