概述
1. 什么是 Webservice?
Webservice 即 web 服务,是一种跨操作系统,跨语言的远程调用技术,例如,服务提供方是使用 Java 开发的服务,客户端使用 Webservice 去调用就无需关心自身是使用何种平台或语言
2. Webservice 三要素
SOAP:简单对象协议,是一种基于 XML 的协议,使得应用程序可以通过 HTTP 交换信息,可以简单理解为 SOAP = HTTP + XML
WSDL:Webservice 描述语言,基于 XML 格式,用户描述 Webservice 及其函数,参数和返回值,可通俗理解为 Webservice 说明书
UDDI:目录服务,企业可以使用它对 Webservice 进行注册和搜索,从而达到资源共享的作用
JAX-WS
1. 服务端开发
Java 在 1.6 版本以后已经支持开发 Webservice,即 JAX-WS。高版本的 JDK 中 JAX-WS 则不再与 JDK 捆绑在一起,需要自行引入。以天气查询服务为例,根据地名返回对应的天气
引入依赖,建议按照这里的版本,高版本存在问题
<dependency>
<groupId>javax.jws</groupId>
<artifactId>javax.jws-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.3.1</version>
</dependency>
开发服务接口
@Webservice
public interface WeatherWebservice {
public String queryWeatherByCity(String cityName);
}
开发服务实现类
@Webservice
public class WeatherWebserviceImpl implements WeatherWebservice {
public String queryWeatherByCity(String cityName) {
}
}
发布服务
public class TestPublished {
public static void main(String[] args) {
Endpoint.publish("http://localhost:8888/ws", new WeatherWebserviceImpl());
}
}
2. 客户端开发
首先查看 Webservice 的服务说明书,访问 http://localhost:8888/ws?wsdl
根据 wsdl 地址生成客户端调用代码
wsimport -s . -p com.yeeq.client [wsdl地址]
我使用的 JDK11 已经移除了 wsimport,可是使用 Maven 插件
<build>
<plugins>
<plugin>
<groupId>com.helger.maven</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.6.2</version>
<configuration>
<packageName>
com.yeeq.web.client
</packageName>
<wsdlUrls>
<wsdlUrl>http://localhost:8888/ws?wsdl</wsdlUrl>
</wsdlUrls>
<keep>true</keep>
<verbose>true</verbose>
<sourceDestDir>src\main\java</sourceDestDir>
<vmArgs>
<vmArg>-Djavax.xml.accessExternalSchema=all</vmArg>
</vmArgs>
</configuration>
</plugin>
</plugins>
</build>
将生成的客户端代码拷贝到项目中,调用方法有两种:
-
基于服务视图对象的调用方式 public class TestClient {
public static void main(String[] args) {
WeatherWebserviceImplService weatherWebserviceImplService = new WeatherWebserviceImplService();
WeatherWebserviceImpl weatherServicePorType = weatherWebserviceImplService.getWeatherWebserviceImplPort();
String weather = weatherServicePorType.queryWeatherByCity("北京");
}
}
-
标准的调用方式 public class TestClient {
public static void main(String[] args) throws Exception {
QName qName = new QName("http://impl.service.web.yeeq.com/", "WeatherWebserviceImplService");
Service service = Service.create(new URL("http://localhost:8888/ws?wsdl"), qName);
WeatherWebserviceImpl weatherServicePorType = service.getPort(WeatherWebserviceImpl.class);
String weather = weatherServicePorType.queryWeatherByCity("北京");
System.out.println(weather);
}
}
相比第一种方式,第二种方式更为复杂,但耦合度更低,当服务端路径发生变化,只需要修改为对应的路径即可,不需要重新生成代码。但无论是第一种还是第二种方式,当服务端的方法声明发生了变化,就必须重新生成代码
CXF 框架
CXF 框架是 Apache 组织开源的 Webservice 框架,最大的特点就是可以与 Spring 框架无缝整合
以 SpringBoot 整合 CXF 为例,需要先引入依赖
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxws</artifactId>
<version>3.5.1</version>
</dependency>
和之前一样,开发服务接口
@WebService
public interface WeatherService {
public String queryWeatherByCity(String cityName);
}
@Component
public class WeatherServiceImpl implements WeatherService {
@Override
public String queryWeatherByCity(String cityName) {
if ("北京".equals(cityName)) {
return "晴转多云";
}
return "多云转晴";
}
}
开发配置类
@Configuration
public class CXFConfig {
@Autowired
private Bus bus;
@Autowired
private WeatherService weatherService;
@Bean
public Endpoint userEndpoint(){
EndpointImpl endpoint = new EndpointImpl(bus,weatherService);
endpoint.publish("/weather");
return endpoint;
}
}
server.port=8080
spring.application.name=cxf-webservice-server
cxf.path=/cxf
运行服务,访问 http://localhost:8080/cxf/weather?wsdl ,查看服务说明书
对于 CXF 开发的服务,也可以用传统的方式调用
|