SOAP 1.2 协议实战:Spring Boot 3.x 构建国家查询服务(附完整代码)

📅 2026/7/9 15:33:13
SOAP 1.2 协议实战:Spring Boot 3.x 构建国家查询服务(附完整代码)
SOAP 1.2 协议实战Spring Boot 3.x 构建国家查询服务附完整代码在当今企业级应用集成领域SOAP协议依然是金融、电信等关键行业的数据交换标准。本文将带您使用Spring Boot 3.x实现一个符合SOAP 1.2规范的国家信息查询服务涵盖从WSDL定义到异常处理的完整开发流程。1. 环境准备与项目初始化首先创建一个基础的Spring Boot项目添加必要的依赖dependencies !-- Spring Boot Starter for Web Services -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web-services/artifactId /dependency !-- XML Binding (JAXB) -- dependency groupIdjakarta.xml.bind/groupId artifactIdjakarta.xml.bind-api/artifactId /dependency !-- XJC工具链 -- dependency groupIdorg.glassfish.jaxb/groupId artifactIdjaxb-runtime/artifactId scoperuntime/scope /dependency /dependencies配置Maven插件用于XSD到Java类的生成build plugins plugin groupIdorg.codehaus.mojo/groupId artifactIdjaxb2-maven-plugin/artifactId version3.1.0/version executions execution idxjc/id goalsgoalxjc/goal/goals /execution /executions configuration sources sourcesrc/main/resources/schemas/countries.xsd/source /sources /configuration /plugin /plugins /build2. 定义服务契约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 namecurrency typetns:currency/ xs:element namepopulation typexs:int/ /xs:sequence /xs:complexType xs:simpleType namecurrency xs:restriction basexs:string xs:enumeration valueUSD/ xs:enumeration valueEUR/ xs:enumeration valueGBP/ /xs:restriction /xs:simpleType /xs:schema执行mvn compile命令后JAXB将在target/generated-sources目录生成对应的Java类。3. 实现数据仓储层创建内存型国家数据仓库Component public class CountryRepository { private static final MapString, Country countries new ConcurrentHashMap(); PostConstruct public void initData() { Country china new Country(); china.setName(China); china.setCapital(Beijing); china.setCurrency(Currency.USD); china.setPopulation(1412000000); countries.put(china.getName(), china); Country france new Country(); france.setName(France); france.setCapital(Paris); france.setCurrency(Currency.EUR); france.setPopulation(67390000); countries.put(france.getName(), france); } public Country findCountry(String name) { return countries.get(name); } }4. 构建SOAP服务端点创建处理SOAP请求的端点类Endpoint public class CountryEndpoint { private static final String NAMESPACE_URI http://example.com/countries; private final CountryRepository countryRepository; 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())); if(response.getCountry() null) { throw new CountryNotFoundException(Country not found: request.getName()); } return response; } }实现自定义SOAP Fault处理ControllerAdvice public class EndpointExceptionHandler { ExceptionHandler(CountryNotFoundException.class) public void handleCountryNotFoundException(CountryNotFoundException ex, SoapMessage message) throws IOException { SoapFault fault new SoapFault(ex.getMessage(), SoapFault.FAULT_CODE_CLIENT); fault.setFaultStringOrReason(ex.getMessage()); message.setFault(fault); } }5. 服务配置与WSDL发布配置Spring WS基础设置EnableWs Configuration public class WebServiceConfig extends WsConfigurerAdapter { Bean public ServletRegistrationBeanMessageDispatcherServlet messageDispatcherServlet( ApplicationContext applicationContext) { MessageDispatcherServlet servlet new MessageDispatcherServlet(); servlet.setApplicationContext(applicationContext); servlet.setTransformWsdlLocations(true); return new ServletRegistrationBean(servlet, /ws/*); } Bean(name countries) public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) { DefaultWsdl11Definition wsdl11Definition new DefaultWsdl11Definition(); wsdl11Definition.setPortTypeName(CountriesPort); wsdl11Definition.setLocationUri(/ws); wsdl11Definition.setTargetNamespace(http://example.com/countries); wsdl11Definition.setSchema(countriesSchema); return wsdl11Definition; } Bean public XsdSchema countriesSchema() { return new SimpleXsdSchema( new ClassPathResource(schemas/countries.xsd)); } }6. 高级SOAP特性实现6.1 SOAP Header处理扩展端点以处理认证HeaderPayloadRoot(namespace NAMESPACE_URI, localPart GetCountryRequest) ResponsePayload public GetCountryResponse getCountry( RequestPayload GetCountryRequest request, SoapHeader({ SECURITY_NS }Authentication) Source securityHeader) { try { // 解析Header内容 String authToken extractAuthToken(securityHeader); if(!validateToken(authToken)) { throw new AuthenticationException(Invalid auth token); } // 处理业务逻辑 return processRequest(request); } catch (Exception e) { throw new SoapFaultClientException(e); } }6.2 消息日志拦截添加SOAP消息日志拦截器Bean public WsConfigurerAdapter wsConfigurerAdapter() { return new WsConfigurerAdapter() { Override public void addInterceptors(ListEndpointInterceptor interceptors) { interceptors.add(new PayloadLoggingInterceptor()); interceptors.add(new SoapEnvelopeLoggingInterceptor()); } }; } class SoapEnvelopeLoggingInterceptor extends PayloadLoggingInterceptor { Override protected Source getSource(MessageContext messageContext) { return messageContext.getRequest() instanceof SoapMessage ? ((SoapMessage)messageContext.getRequest()).getEnvelope().getSource() : super.getSource(messageContext); } }7. 测试与验证使用Postman测试SOAP服务获取WSDL定义GET http://localhost:8080/ws/countries.wsdl发送SOAP请求示例POST /ws HTTP/1.1 Host: localhost:8080 Content-Type: text/xml;charsetUTF-8 SOAPAction: soapenv:Envelope xmlns:soapenvhttp://schemas.xmlsoap.org/soap/envelope/ xmlns:couhttp://example.com/countries soapenv:Header cou:Authentication cou:TokenSECRET_KEY/cou:Token /cou:Authentication /soapenv:Header soapenv:Body cou:GetCountryRequest cou:nameChina/cou:name /cou: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:currencyUSD/ns2:currency ns2:population1412000000/ns2:population /ns2:country /ns2:GetCountryResponse /SOAP-ENV:Body /SOAP-ENV:Envelope8. 性能优化建议启用HTTP压缩# application.properties server.compression.enabledtrue server.compression.mime-typestext/xml配置JAXB上下文缓存Bean public Jaxb2Marshaller marshaller() { Jaxb2Marshaller marshaller new Jaxb2Marshaller(); marshaller.setContextPath(com.example.countries); marshaller.setMtomEnabled(true); // 启用MTOM附件优化 return marshaller; }使用SAX解析器提升性能Bean public SaajSoapMessageFactory messageFactory() { SaajSoapMessageFactory factory new SaajSoapMessageFactory(); factory.setMessageFactory(MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL)); return factory; }实际项目中建议结合Spring Boot Actuator监控端点/actuator/httptrace来跟踪SOAP请求性能指标。对于高并发场景可以考虑引入异步处理机制或增加WS-Security加密带来的性能开销。