Springboot-WebService 服务端发布与客户端调用
第一章、WebService服务端代码实现:
1.1 pom.xml
<!-- CXF WebService框架依赖 --><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-spring-boot-starter-jaxws</artifactId><version>3.4.5</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http</artifactId><version>3.4.5</version></dependency><!-- Lombok简化代码 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
1.2 yml配置
cxf:path: /webservice/server # WebService服务访问路径前缀: 向外暴露的接口服务;filter过滤器需放行servlet:init:service-list-path: /list # 服务列表页面路径
1.3 config配置
import com.gitee.ht.service.UserService;
import com.gitee.ht.service.impl.UserServiceImpl;
import org.apache.cxf.Bus;
import javax.xml.ws.Endpoint;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;/*** CXF WebService配置类* 负责配置和发布WebService端点*/
@Configuration
public class CxfConfig {@Bean(name = Bus.DEFAULT_BUS_ID)public SpringBus springBus() {return new SpringBus();}@Bean(name = "wsBean")public ServletRegistrationBean dispatcherServlet() {ServletRegistrationBean wbsServlet = new ServletRegistrationBean(new CXFServlet(), "/webservice/server/*");return wbsServlet;}@Beanpublic UserService userService() {return new UserServiceImpl();}@Beanpublic Endpoint userServiceEndpoint(UserService userService, SpringBus bus) {EndpointImpl endpoint = new EndpointImpl(bus, userService);endpoint.publish("/userService");System.out.println("服务发布成功:地址为:http://localhost:8082/webservice/server/userService?wsdl");return endpoint;}
}
1.4 webService服务器接口代码
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;/*** WebService服务接口定义* @WebService 注解用于标识这是一个WebService接口* name: 服务名称* targetNamespace: 命名空间,用于区分不同的服务*/
@WebService(name = "UserService", targetNamespace = "http://localhost:8082/")
public interface UserService {/*** 打招呼方法* @WebMethod 标识这是一个WebService方法* @param name 用户名* @return 问候语*/@WebMethodString sayHello(@WebParam(name = "name") String name);/*** 获取用户信息方法* @param userId 用户ID* @return 用户信息对象*/@WebMethodUserInfo getUserInfo(@WebParam(name = "userId") String userId);/*** 更新用户信息方法* @param userInfo 用户信息对象* @return 更新结果*/@WebMethodboolean updateUserInfo(@WebParam(name = "userInfo") UserInfo userInfo);
}
1.5 webService接口的实现类
import com.gitee.ht.service.UserInfo;
import com.gitee.ht.service.UserService;
import org.springframework.stereotype.Component;import javax.jws.WebService;
import java.util.HashMap;
import java.util.Map;/*** WebService服务接口实现类* @WebService 注解配置:* serviceName: 服务名称* targetNamespace: 命名空间,必须与接口一致* endpointInterface: 指定服务接口类* @Component 标识这是一个Spring组件,会被自动扫描和管理*/
@WebService(serviceName = "UserService",
// targetNamespace = "http://service.webserver.example.com/",targetNamespace = "http://localhost:8082/",endpointInterface = "com.gitee.ht.service.UserService"
)
@Component
public class UserServiceImpl implements UserService {// 模拟用户数据存储private Map<String, UserInfo> userMap = new HashMap<>();/*** 构造函数,初始化测试数据*/public UserServiceImpl() {// 创建测试用户UserInfo user1 = new UserInfo();user1.setUserId("001");user1.setUserName("张三");user1.setEmail("zhangsan@example.com");user1.setPhone("13800138000");user1.setAge(28);userMap.put("001", user1);}/*** 打招呼方法实现* @param name 用户名* @return 个性化问候语*/@Overridepublic String sayHello(String name) {return "Hello, " + name + "! Welcome to User WebService.";}/*** 获取用户信息方法实现* @param userId 用户ID* @return 用户信息对象,如果用户不存在则返回默认信息*/@Overridepublic UserInfo getUserInfo(String userId) {// 从Map中获取用户信息UserInfo userInfo = userMap.get(userId);if (userInfo == null) {// 如果用户不存在,创建默认用户信息userInfo = new UserInfo();userInfo.setUserId(userId);userInfo.setUserName("Unknown User");userInfo.setEmail("unknown@example.com");userInfo.setPhone("00000000000");userInfo.setAge(0);userInfo.setAddress("Unknown Address");userMap.put(userId, userInfo); // 缓存默认用户信息System.out.println("创建默认用户信息:" + userId);} else {System.out.println("查询用户信息:" + userId);}return userInfo;}/*** 更新用户信息方法实现* @param userInfo 要更新的用户信息* @return 更新结果,成功返回true,失败返回false*/@Overridepublic boolean updateUserInfo(UserInfo userInfo) {// 验证参数有效性if (userInfo != null && userInfo.getUserId() != null) {userMap.put(userInfo.getUserId(), userInfo); // 更新用户信息System.out.println("更新用户信息:" + userInfo.getUserId());return true;}return false;}
}
1.6 实体类
import lombok.Data;
import javax.xml.bind.annotation.XmlRootElement;/*** 用户信息数据传输对象* @Data Lombok注解,自动生成getter/setter等方法* @XmlRootElement 标识该类可以被XML序列化和反序列化*/
@Data
@XmlRootElement
public class UserInfo {private String userId; // 用户IDprivate String userName; // 用户名private String email; // 邮箱private String phone; // 电话private Integer age; // 年龄private String address; // 地址
}
1.7 WebService 服务端启用与测试
项目启动后访问如下地址:http://localhost:8082/webservice/server?wsdl 显示你定义的方法名称说明服务端已经发布成功

第二章、WebService 客户端代码实现
2.1 pom
<!-- CXF WebService客户端依赖 --><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-spring-boot-starter-jaxws</artifactId><version>3.4.5</version></dependency><dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http</artifactId><version>3.4.5</version></dependency><!-- Lombok简化代码 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
2.2 yml
webservice:server:url: http://localhost:8082/webservice/server/userService # 远程WebService服务地址
2.3 config
import com.gitee.ht.client.UserServiceClient;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 客户端WebService配置类* 负责创建WebService客户端代理*/
@Configuration
public class WebServiceClientConfig {// 从配置文件中注入远程服务地址@Value("${webservice.server.url}")private String serviceUrl;/*** 创建WebService客户端代理Bean* @return WebService客户端代理实例*/@Beanpublic UserServiceClient userServiceClient() {// 创建JAX-WS代理工厂JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();// 设置服务接口类factory.setServiceClass(UserServiceClient.class);// 设置远程服务地址factory.setAddress(serviceUrl);// 创建并返回服务代理UserServiceClient client = (UserServiceClient) factory.create();System.out.println("WebService客户端代理创建成功,服务地址:" + serviceUrl);return client;}
}
2.4 bean实体类,需要与服务端定义一致,用于数据交换
/*** 客户端用户信息对象* 与服务端的UserInfo类对应,用于数据交换* @Data Lombok注解,自动生成getter/setter等方法* @XmlRootElement 标识该类可以被XML序列化和反序列化*/
@Data
@XmlRootElement
public class UserInfo {private String userId; // 用户IDprivate String userName; // 用户名private String email; // 邮箱private String phone; // 电话private Integer age; // 年龄private String address; // 地址
}
2.5 客户端接口层
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;/*** 客户端WebService接口定义* 必须与服务端接口保持一致,包括方法签名和命名空间* @WebService 注解配置必须与服务端一致*/
@WebService(name = "UserService",
// targetNamespace = "http://service.webserver.example.com/"targetNamespace = "http://localhost:8082/"
)
public interface UserServiceClient {/*** 打招呼方法* @param name 用户名* @return 问候语*/@WebMethodString sayHello(@WebParam(name = "name") String name);/*** 获取用户信息方法* @param userId 用户ID* @return 用户信息对象*/@WebMethodUserInfo getUserInfo(@WebParam(name = "userId") String userId);/*** 更新用户信息方法* @param userInfo 用户信息对象* @return 更新结果*/@WebMethodboolean updateUserInfo(@WebParam(name = "userInfo") UserInfo userInfo);
}
2.6 请求调用webService
import com.gitee.ht.client.UserInfo;
import com.gitee.ht.client.UserServiceClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;/*** 用户信息REST控制器* 提供RESTful接口,内部调用远程WebService服务*/
@RestController
@RequestMapping("/api/user")
public class UserController {@Autowiredprivate UserServiceClient userServiceClient; // 注入WebService客户端代理/*** 测试打招呼功能的REST接口* @param name 用户名* @return 问候语*/@GetMapping("/hello")public String sayHello(@RequestParam String name) {System.out.println("接收到打招呼请求,用户名:" + name);// 调用远程WebService的sayHello方法return userServiceClient.sayHello(name);}/*** 获取用户信息的REST接口* @param userId 用户ID* @return 用户信息对象*/@GetMapping("/{userId}")public UserInfo getUserInfo(@PathVariable String userId) {System.out.println("接收到获取用户信息请求,用户ID:" + userId);// 调用远程WebService的getUserInfo方法return userServiceClient.getUserInfo(userId);}/*** 更新用户信息的REST接口* @param userInfo 用户信息对象* @return 操作结果*/@PutMapping("/update")public String updateUserInfo(@RequestBody UserInfo userInfo) {System.out.println("接收到更新用户信息请求,用户ID:" + userInfo.getUserId());// 调用远程WebService的updateUserInfo方法boolean result = userServiceClient.updateUserInfo(userInfo);return result ? "更新成功" : "更新失败";}/*** WebService连接测试接口* @param userId 测试用户ID* @return 测试结果*/@PostMapping("/test")public String testWebService(@RequestParam String userId) {System.out.println("开始测试WebService连接,用户ID:" + userId);try {// 尝试调用远程服务UserInfo userInfo = userServiceClient.getUserInfo(userId);String result = "WebService调用成功,用户信息:" + userInfo.getUserName();System.out.println(result);return result;} catch (Exception e) {String errorMsg = "WebService调用失败:" + e.getMessage();System.out.println(errorMsg);return errorMsg;}}
}
2.8 请求测试,需保证服务端项目已启动或部署
启动客户端项目,浏览器访问客户端接口,程序调用webService服务端,拿到返回结果,输出浏览器

