尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Spring Boot 3.x 构建 SOAP WebService:5步实现国家查询服务(附完整代码)
Spring Boot 3.x 构建 SOAP WebService5步实现国家查询服务附完整代码在当今企业级应用开发中SOAP协议仍然是金融、电信等关键领域的主流选择。Spring Boot 3.x与Spring Web Services的深度整合让开发者能够快速构建符合WS-I标准的Web服务。本文将手把手带你实现一个完整的国家信息查询服务涵盖从XSD定义到端点测试的全流程。1. 环境准备与项目初始化首先创建一个基础的Spring Boot 3.x项目添加以下关键依赖到pom.xmldependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web-services/artifactId /dependency dependency groupIdwsdl4j/groupId artifactIdwsdl4j/artifactId /dependency /dependencies build plugins plugin groupIdorg.codehaus.mojo/groupId artifactIdjaxb2-maven-plugin/artifactId version3.1.0/version executions execution idxjc/id goals goalxjc/goal /goals /execution /executions /plugin /plugins /build关键配置说明spring-boot-starter-web-services提供SOAP支持wsdl4j用于WSDL处理jaxb2-maven-plugin实现XSD到Java类的自动转换2. 定义XSD架构与WSDL在src/main/resources/schemas目录下创建countries.xsdxs:schema xmlns:xshttp://www.w3.org/2001/XMLSchema targetNamespacehttp://example.com/countries xmlns:tnshttp://example.com/countries elementFormDefaultqualified xs:element namegetCountryRequest xs:complexType xs:sequence xs:element namename typexs:string/ /xs:sequence /xs:complexType /xs:element xs:element namegetCountryResponse xs:complexType xs:sequence xs:element namecountry typetns:country/ /xs:sequence /xs:complexType /xs:element xs:complexType namecountry xs:sequence xs:element namename typexs:string/ xs:element namecapital typexs:string/ xs:element namepopulation typexs:int/ xs:element namecurrency typetns:currency/ /xs:sequence /xs:complexType xs:simpleType namecurrency xs:restriction basexs:string xs:enumeration valueUSD/ xs:enumeration valueEUR/ xs:enumeration valueCNY/ /xs:restriction /xs:simpleType /xs:schema执行mvn compile命令后JAXB会在target/generated-sources目录生成对应的Java类包括GetCountryRequestGetCountryResponseCountry等3. 实现数据仓库与端点创建内存型国家数据仓库Component public class CountryRepository { private static final MapString, Country countries new HashMap(); PostConstruct public void initData() { Country china new Country(); china.setName(China); china.setCapital(Beijing); china.setPopulation(1412000000); china.setCurrency(Currency.CNY); countries.put(china.getName(), china); Country usa new Country(); usa.setName(USA); usa.setCapital(Washington); usa.setPopulation(331000000); usa.setCurrency(Currency.USD); countries.put(usa.getName(), usa); } public Country findCountry(String name) { return countries.get(name); } }实现服务端点Endpoint public class CountryEndpoint { private static final String NAMESPACE_URI http://example.com/countries; private final CountryRepository countryRepository; Autowired public CountryEndpoint(CountryRepository countryRepository) { this.countryRepository countryRepository; } PayloadRoot(namespace NAMESPACE_URI, localPart getCountryRequest) ResponsePayload public GetCountryResponse getCountry(RequestPayload GetCountryRequest request) { GetCountryResponse response new GetCountryResponse(); response.setCountry(countryRepository.findCountry(request.getName())); return response; } }关键注解解析Endpoint标记为SOAP端点PayloadRoot定义处理的消息类型ResponsePayload声明返回值为响应体4. 服务配置与WSDL暴露配置WebService基础设置EnableWs Configuration public class WebServiceConfig extends WsConfigurerAdapter { Bean public ServletRegistrationBeanMessageDispatcherServlet messageDispatcherServlet(ApplicationContext context) { MessageDispatcherServlet servlet new MessageDispatcherServlet(); servlet.setApplicationContext(context); servlet.setTransformWsdlLocations(true); return new ServletRegistrationBean(servlet, /ws/*); } Bean(name countries) public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) { DefaultWsdl11Definition wsdl new DefaultWsDL11Definition(); wsdl.setPortTypeName(CountriesPort); wsdl.setLocationUri(/ws); wsdl.setTargetNamespace(http://example.com/countries); wsdl.setSchema(countriesSchema); return wsdl; } Bean public XsdSchema countriesSchema() { return new SimpleXsdSchema(new ClassPathResource(schemas/countries.xsd)); } }启动应用后可通过以下URL访问WSDLhttp://localhost:8080/ws/countries.wsdl5. 服务测试与验证使用cURL测试服务curl --header content-type: text/xml \ --data request.xml \ http://localhost:8080/ws其中request.xml内容为soapenv:Envelope xmlns:soapenvhttp://schemas.xmlsoap.org/soap/envelope/ xmlns:gshttp://example.com/countries soapenv:Header/ soapenv:Body gs:getCountryRequest gs:nameChina/gs:name /gs:getCountryRequest /soapenv:Body /soapenv:Envelope预期响应示例SOAP-ENV:Envelope xmlns:SOAP-ENVhttp://schemas.xmlsoap.org/soap/envelope/ SOAP-ENV:Header/ SOAP-ENV:Body ns2:getCountryResponse xmlns:ns2http://example.com/countries ns2:country ns2:nameChina/ns2:name ns2:capitalBeijing/ns2:capital ns2:population1412000000/ns2:population ns2:currencyCNY/ns2:currency /ns2:country /ns2:getCountryResponse /SOAP-ENV:Body /SOAP-ENV:Envelope对于更复杂的场景可以添加SOAP头处理PayloadRoot(namespace NAMESPACE_URI, localPart getCountryRequest) ResponsePayload public GetCountryResponse getCountry( RequestPayload GetCountryRequest request, SoapHeader({ SECURITY_NS }authentication) SoapHeaderElement auth) { // 验证头信息 if (!validateHeader(auth)) { throw new AuthenticationException(Invalid credentials); } // ...原有处理逻辑 }6. 高级配置与优化对于生产环境建议添加以下增强配置WS-Security配置Bean public Wss4jSecurityInterceptor securityInterceptor() { Wss4jSecurityInterceptor interceptor new Wss4jSecurityInterceptor(); interceptor.setSecurementActions(UsernameToken); interceptor.setSecurementUsername(admin); interceptor.setSecurementPassword(secret); return interceptor; } Override public void addInterceptors(ListEndpointInterceptor interceptors) { interceptors.add(securityInterceptor()); }性能优化建议启用JAXB编译缓存plugin groupIdorg.codehaus.mojo/groupId artifactIdjaxb2-maven-plugin/artifactId configuration clearOutputDirfalse/clearOutputDir /configuration /plugin配置HTTP压缩server.compression.enabledtrue server.compression.mime-typestext/xml,application/soapxml7. 异常处理与调试实现自定义SOAP错误处理Endpoint public class CountryEndpoint { // ...其他方法 ExceptionHandler public void handleException(Exception ex, SoapMessage response) { TransformerFactory.newInstance().newTransformer() .transform(new DOMSource(createFault(ex)), new StreamResult(response.getSoapBody().getResult())); } private org.w3c.dom.Document createFault(Exception ex) { // 构建详细的SOAP Fault XML } }调试技巧启用SOAP消息日志logging.level.org.springframework.ws.client.MessageTracing.sentTRACE logging.level.org.springframework.ws.client.MessageTracing.receivedTRACE使用SoapUI工具进行可视化测试通过WireShark抓包分析原始SOAP报文
RELATED

相关推荐

Unity随机地图生成实战:从算法原理到2D地牢实现

Unity随机地图生成实战:从算法原理到2D地牢实现

1. 项目概述:为什么我们需要随机地图生成?在游戏开发中,尤其是Roguelike、沙盒建造、策略探索等类型的项目中,一张固定不变的地图很快就会让玩家感到厌倦。重复的关卡意味着重复的策略和体验,游戏的寿命和可玩性会大打…

📅 2026/10/5 3:00:13
Unity WebGL实现GLB模型本地下载:jslib插件实战指南

Unity WebGL实现GLB模型本地下载:jslib插件实战指南

1. 项目概述与核心挑战 最近在做一个基于Unity WebGL的3D产品展示项目,客户提了个很实际的需求:用户在网页上浏览完一个复杂的设备模型后,希望能把这个模型文件(GLB格式)下载到自己的电脑上,方便后续离线查…

📅 2026/11/1 19:36:11
拼多多订单批量导出:3种方案对比(浏览器脚本 vs RPA vs 插件)

拼多多订单批量导出:3种方案对比(浏览器脚本 vs RPA vs 插件)

拼多多订单批量导出:3种技术方案深度评测与实战指南在电商运营和个人消费管理中,拼多多订单数据的高效导出已成为刚需。无论是个人用户的年度消费统计,还是电商从业者的供应链管理,从海量订单中提取结构化数据都面临着平台原生功能…

📅 2026/10/7 15:39:01
MORE NEWS

更多资讯

📰

启动报Port 8088 was already in use?先查是谁占的

启动报Port 8088 was already in use?先查是谁占的 项目启动报 Port 8088 was already in use,意思很直白:这个端口已经有人占了。 先说原理:端口是"门牌号",一间房只住一个进程 端口就是一台机器上的门牌号…

📰

担心文档上云?本地运行的办公AI才敢放心用

单位上周开了个会,主题是"AI 提效",散会时领导补了一句:涉及客户资料的文档,不许往云端传。这话一出,会议室里本来跃跃欲试的同事全蔫了——大家平时用的那些在线 AI,文档一上传就不知道存哪儿去…

📰

先能用,再好用:从烂尾复盘到两周上线,全栈项目的‘原型—快速迭代‘方法论

先能用,再好用:从烂尾复盘到两周上线,全栈项目的“原型—快速迭代”方法论 全栈学习路径的文章已经很多了:怎么选技术栈、怎么搭环境、怎么记文档,几乎每个方向都有人写。但一个更扎心的问题很少有人正面讨论——为什…

📰

深度思考模式把 ARC-AGI-2 从 17.6% 拉到 45.1%:对照 Gemini 3 Pro 的三份能力评测,看‘会思考‘改写了哪些边界

深度思考模式把 ARC-AGI-2 从 17.6% 拉到 45.1%:对照 Gemini 3 Pro 的三份能力评测,看“会思考”改写了哪些边界 一、先说结论:变强的不是“知识”,而是“解法” 每次新模型发布,评测榜单都会涨几个点,大…

📰

1.c++入门篇

1.c中的关键字asmdoifreturntrycontinueautodoubleinlineshorttypedefforbooldynamic_castintsignedtypeidpublicbreakelselongsizeoftypenamethrowcaseenummutablestaticunionwchar_tcatchexplicitnamespacestatic_castunsigneddefaultcharexportnewstructusingfriendclassext…

📰

《江灯合声》:有可行的分框版,也仍可以选择连续鸣谢

武汉江岸区栎坡合唱团在免费节目册《江灯合声》中,以表格集中鸣谢资助者。各家共同要求改为独立小框,团里仍想保留表格。现有全名与支持事项清楚可见,双方此前未承诺具体排版。我支持保留表格。补充的试排材料让选择更具体:分框能…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬