悠悠楠杉
Java实现WebService服务的开发与调用实战指南
本文详细讲解如何使用Java原生JAX-WS和Apache CXF框架开发WebService服务,包含服务端搭建、WSDL生成、客户端调用全流程,通过实际案例演示SOAP协议通信的完整实现。
一、WebService技术基础
WebService作为跨平台远程调用的标准方案,其核心基于SOAP协议(Simple Object Access Protocol)和WSDL(Web Services Description Language)。在Java生态中,我们主要通过以下两种方式实现:
- JAX-WS:Java原生WebService API
- Apache CXF:功能更丰富的开源框架
java
// 典型SOAP消息示例
<soap:Envelope>
<soap:Header/>
<soap:Body>
<getUserInfo>
<userId>123</userId>
</getUserInfo>
</soap:Body>
</soap:Envelope>
二、JAX-WS服务端开发
1. 创建服务接口
java
import javax.jws.WebService;
import javax.jws.WebMethod;
@WebService
public interface WeatherService {
@WebMethod
String getWeatherByCity(String cityName);
}
2. 实现服务类
java
@WebService(endpointInterface = "com.example.WeatherService")
public class WeatherServiceImpl implements WeatherService {
@Override
public String getWeatherByCity(String cityName) {
// 模拟数据查询
Map<String, String> data = Map.of("北京", "晴", "上海", "多云");
return data.getOrDefault(cityName, "城市不存在");
}
}
3. 发布服务
java
public class ServicePublisher {
public static void main(String[] args) {
String url = "http://localhost:8080/weather";
WeatherServiceImpl implementor = new WeatherServiceImpl();
Endpoint.publish(url, implementor);
System.out.println("服务已启动,WSDL地址:" + url + "?wsdl");
}
}
关键点说明:
- @WebService
注解标记服务端点
- Endpoint.publish()方法内置了轻量级HTTP服务器
- WSDL会自动生成,访问地址需加?wsdl
后缀
三、Apache CXF进阶开发
对于企业级应用,推荐使用CXF框架:
xml
<!-- Maven依赖 -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>3.5.5</version>
</dependency>
服务发布配置:
java
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
factory.setServiceClass(WeatherServiceImpl.class);
factory.setAddress("http://localhost:8080/weather");
factory.create();
四、客户端调用方案
1. 通过wsimport生成客户端
bash
wsimport -keep -p com.client http://localhost:8080/weather?wsdl
2. 动态调用代码
java
public class WeatherClient {
public static void main(String[] args) throws Exception {
URL wsdlUrl = new URL("http://localhost:8080/weather?wsdl");
QName serviceName = new QName("http://example.com/", "WeatherServiceImplService");
Service service = Service.create(wsdlUrl, serviceName);
WeatherService port = service.getPort(WeatherService.class);
System.out.println(port.getWeatherByCity("北京"));
}
}
五、常见问题解决方案
命名空间冲突:在@WebService注解中明确指定targetNamespace
java @WebService(targetNamespace = "http://yourdomain.com/ws")
复杂类型传输:确保自定义类实现Serializable接口
性能优化建议:
- 使用CXF的FastInfoset协议压缩SOAP消息
- 启用HTTP持久化连接
- 对频繁调用的服务添加本地缓存
六、安全控制(BASIC认证示例)
java
// 服务端拦截器配置
Map<String, Object> props = new HashMap<>();
props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
props.put(WSHandlerConstants.PW_CALLBACK_CLASS, ServerPasswordCallback.class.getName());
factory.setProperties(props);