一、webservice是什么、能干什么?
(1)webservice是一种使用http发送soap协议数据的远程调用技术。
(2)wsdl:webservice description language(web服务描述语言),通过xml的形式说明服务在哪里,如何调用。
(3)soap:simple object access protocol (简单对象访问协议),用http协议传输xml数据。
(4)sei:WebService EndPoint Interface(web服务终端接口),两个重要的类。
(4.1)@WebService:定义Webservice接口。
(4.2)@WebMethod:设置Webservice的方法。
(4.3)@WebParam:设置Webservice的参数。
(4.4)@WebResult:设置Webservice的返回值。
注意:
当使用SOAP12以后,wsimport和Eclipse和WSExplorer都不可以正常使用了,必须使用cxf提供的wsdl2java工具生成本地代码。
webservice性能不高。
二、用jdk提供的类发布webservice服务
1、发布服务方实现
package com.cjh.service.impl;
import javax.jws.WebMethod;
import javax.jws.WebService;
import com.cjh.service.IUserService;
/**
* SEI定义发布服务
* @author 陈嘉豪
*
*/
@WebService
public class UserServiceImpl implements IUserService{
@Override
public String queryUserName() {
return "chen jia hao";
}
@WebMethod(exclude=true)
@Override
public String queryUserPassword() {
return "123456";
}
}
package com.cjh.provider;
import javax.xml.ws.Endpoint;
import com.cjh.service.impl.UserServiceImpl;
/**
* 发布服务
* @author 陈嘉豪
*/
public class UserProvider {
public static void main(String[] args) {
Endpoint.publish("http://127.0.0.1:8080/user", new UserServiceImpl());
System.out.println("userService publihser...");
}
}
更多:Endpoint.publish()将会开启一个新的线程,不会影响主线程的运行。
发布的服务至少需要有一个可发布的方法,其中方法不能是静态或者final方法。
在需要发布的服务类上使用@WebService注解,这样Endpoint发布时才能正确将服务类绑定到一个地址。
2、服务调用方实现
(1)使用jdk自带的工具wsimport.exe(在JAVA_HOME/bin里面)来生成相应的java类。
命令行窗口:输入wximport -s http://127.0.0.1:8080?wsdl。这样就可以生成客户端java代码。
可选参数:
-d<目录> :将生成.class文件。默认参数。
-s<目录> :将生成.java文件。
-p<生成的新包名> -将生成的类,放于指定的包下,自定义包结构。
wsdlurl :http://127.0.0.1:8080?wsdl,必须的参数。
package com.cjh.client;
import com.cjh.service.impl.UserServiceImpl;
import com.cjh.service.impl.UserServiceImplService;
/**
* 客户端远程调用
* @author 陈嘉豪
*
*/
public class WebServiceClient {
public static void main(String[] args) {
UserServiceImplService userServiceImplService = new UserServiceImplService();
UserServiceImpl userServiceImplPort = userServiceImplService.getUserServiceImplPort();
System.out.println(userServiceImplPort.queryUserName());;
}
}
远程调用成功效果:
二、spring集成cxf实现webservice远程调用
1、jar包准备:apache-cxf-2.7.18,下载地址:http://cxf.apache.org/download.html
2、web.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>WebServiceProvider</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/spring-cxf.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- 字符过滤器 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
3、发布服务方spring-cxf.xml配置,在该配置里面配置需要暴露的服务接口和调用地址:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<context:component-scan base-package="com.cjh.*" />
<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" />
<!--第一种 方式: 暴露 Web Service服务 -->
<!-- <jaxws:server
id="userWebService"
serviceClass="com.cjh.service.IUser"
address="/UserWebService">
<jaxws:serviceBean>
<ref bean="userService" />
</jaxws:serviceBean>
</jaxws:server> -->
<!-- 第二种方式:暴露Web Service服务 -->
<jaxws:endpoint
id="userWebService"
address="/UserWebService"
implementor="com.cjh.service.UserServiceImpl">
</jaxws:endpoint>
</beans>
package com.cjh.service;
import javax.jws.WebService;
/**
* 发布方暴露的接口
* @author 陈嘉豪
*/
@WebService
public interface IUserService {
public String queryUserName();
}
package com.cjh.service;
import javax.jws.WebService;
/**
* 发布方需要暴露的服务
* @author 陈嘉豪
*/
@WebService
public class UserServiceImpl implements IUserService{
@Override
public String queryUserName(){
return "chen jia hao...";
}
}
4、服务调用方spring.xml配置,在该配置里面配置需要远程调用的服务和远程服务地址:
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!--web service 远程调用服务 ,这个就相当于 普通 bean了-->
<jaxws:client
id="userService"
serviceClass="com.cjh.service.IUserService"
address="http://localhost:8080/Spring-webservice/UserWebService"/>
</beans>
5、最后调用者做下测试:
package com.cjh.client;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.cjh.service.IUserService;
/**
* 调用方测试
* @author 陈嘉豪
*
*/
public class WebserviceClient {
public static void main(String[] args) {
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath:config/spring.xml");
IUserService userService = (IUserService) classPathXmlApplicationContext.getBean("userService");
System.out.println(userService.queryUserName());
}
}
如果显示,那么恭喜你,远程调用成功了O(∩_∩)O~。
三、通过axis2调用webservice服务
1、引入maven依赖:
<!-- Axis2 -->
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.axiom</groupId>
<artifactId>axiom</artifactId>
<version>1.2.20</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.axiom</groupId>
<artifactId>axiom-api</artifactId>
<version>1.2.20</version>
</dependency>
<dependency>
<groupId>org.apache.ws.commons.axiom</groupId>
<artifactId>axiom-impl</artifactId>
<version>1.2.20</version>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>org.apache.ws.xmlschema</groupId>
<artifactId>xmlschema-core</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.neethi</groupId>
<artifactId>neethi</artifactId>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-transport-local</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-transport-http</artifactId>
<version>1.7.7</version>
</dependency>
<!-- Axis2 End -->
2、关键代码实现(以调用天气webservice为例学习):
package com.cjh.test.webservice;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.rpc.client.RPCServiceClient;
import org.junit.Test;
import javax.xml.namespace.QName;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* @author chen jia hao
*/
public class AxisTest {
/***
* 获取天气,这是完整的webservice调用小例子
* @throws AxisFault
*/
@Test
public void testRPCClient() throws AxisFault {
try {
// 使用RPC方式调用WebService
RPCServiceClient serviceClient = new RPCServiceClient();
// 创建WSDL的URL
// String url = "http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl";
String url = "http://ws.webxml.com.cn/WebServices/WeatherWS.asmx";
// 指定调用WebService的URL
EndpointReference targetEPR = new EndpointReference(url);
Options options = serviceClient.getOptions();
// 确定目标服务地址
options.setTo(targetEPR);
// 确定调用方法(wsdl 命名空间地址 (wsdl文档中的targetNamespace) 和 方法名称 的组合)
options.setAction("http://WebXml.com.cn/getWeather");
// 创建服务名称
// 1.namespaceURI - 命名空间地址 (wsdl文档中的targetNamespace)
// 2.localPart - 服务视图名 (wsdl文档中operation的方法名称,例如<wsdl:operation name="getWeather">)
QName qname = new QName("http://WebXml.com.cn/", "getWeather");
OMFactory omFactory = OMAbstractFactory.getOMFactory();
OMNamespace omNamespace = omFactory.createOMNamespace("http://WebXml.com.cn/", "");
//方法
OMElement method = omFactory.createOMElement("getWeather", omNamespace);
//参数
OMElement theCityCode = omFactory.createOMElement("theCityCode", omNamespace);
//对于参数的值
theCityCode.setText("长沙");
method.addChild(theCityCode);
//method.build(); //可选
OMElement responseOMElement = serviceClient.sendReceive(method);
System.out.println(responseOMElement);
String hr = "-------------------------------------------------------";
System.out.println(hr);
System.out.println(hr);
OMElement firstElement = responseOMElement.getFirstElement();
Iterator childElements = firstElement.getChildElements();
while (childElements.hasNext()) {
OMElement element = (OMElement) childElements.next();
System.out.println(element.getText());
System.out.println(hr);
}
} catch (AxisFault e) {
e.printStackTrace();
}
}
/***
* 测试客户端WebServiceClient
* @throws AxisFault
*/
@Test
public void test() throws AxisFault {
String url = "http://ws.webxml.com.cn/WebServices/WeatherWS.asmx";
String namespace = "http://WebXml.com.cn/";
String method = "getWeather";
Map<String, String> params = new HashMap<>();
params.put("theCityCode","长沙");
OMElement result = WebServiceClient.request(url, namespace, method, params);
System.out.println(result);
String hr = "-------------------------------------------------------";
System.out.println(hr);
System.out.println(hr);
OMElement firstElement = result.getFirstElement();
Iterator childElements = firstElement.getChildElements();
while (childElements.hasNext()) {
OMElement element = (OMElement) childElements.next();
System.out.println(element.getText());
System.out.println(hr);
}
}
}
/***
* webservice 客户端调用服务
* @author chen jia hao
*/
class WebServiceClient {
/***
* 远程调用
* @author chen jia hao
* @param url
* @param namespace
* @param method
* @param params
* @return
* @throws AxisFault
*/
public static OMElement request(String url, String namespace, String method, Map<String, String> params) throws AxisFault {
assert (url!=null && namespace!=null && method!=null):"参数不能为null";
String action = namespace + method;
if (params == null) {
params = new HashMap<>(0);
}
// 使用RPC方式调用WebService
RPCServiceClient serviceClient = new RPCServiceClient();
// 指定调用WebService的URL
EndpointReference targetEPR = new EndpointReference(url);
Options options = serviceClient.getOptions();
// 确定目标服务地址
options.setTo(targetEPR);
// 确定调用方法(wsdl 命名空间地址 (wsdl文档中的targetNamespace) 和 方法名称 的组合)
options.setAction(action);
// 创建服务名称
// 1.namespaceURI - 命名空间地址 (wsdl文档中的targetNamespace)
// 2.localPart - 服务视图名 (wsdl文档中operation的方法名称,例如<wsdl:operation name="getWeather">)
//QName qname = new QName(namespace, method);
OMFactory omFactory = OMAbstractFactory.getOMFactory();
OMNamespace omNamespace = omFactory.createOMNamespace(namespace, "");
//方法
OMElement methodElement = omFactory.createOMElement(method, omNamespace);
for (Map.Entry<String, String> item : params.entrySet()) {
//参数
OMElement paramElement = omFactory.createOMElement(item.getKey(), omNamespace);
//对于参数的值
paramElement.setText(item.getValue());
methodElement.addChild(paramElement);
}
methodElement.build(); //可选
//远程调用
OMElement responseOMElement = serviceClient.sendReceive(methodElement);
return responseOMElement;
}
}
返回结果: