我正在嘗試深入研究 Spring SOAP Web 服務和 JAXB 類生成。在 spring.io 教程之后,我設法創建了簡單的 Web 服務應用程式,但它并沒有像預期的那樣回應我的請求。這是我的代碼,配置(UPD已修復,感謝 DimasG,但仍然無法正常作業):
@EnableWs
@Configuration
public class WebServiceConfiguration extends WsConfigurerAdapter {
@Bean
public ServletRegistrationBean registrationBean(ApplicationContext context) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(context);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
@Bean(name = "employees")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema schema) {
DefaultWsdl11Definition definition = new DefaultWsdl11Definition();
definition.setPortTypeName("EmployeesPort");
definition.setLocationUri("/ws");
definition.setTargetNamespace("http://spring/demo/webservice");
definition.setSchema(schema);
return definition;
}
@Bean
public XsdSchema employeesSchema() {
return new SimpleXsdSchema(new ClassPathResource("xsd/employees.xsd"));
}
}
XSD 架構檔案:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://spring/demo/webservice"
targetNamespace="http://spring/demo/webservice" elementFormDefault="qualified">
<xs:element name="getEmployeeRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getEmployeeResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="employee" type="tns:employee"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="employee">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="age" type="xs:int"/>
<xs:element name="position" type="xs:string"/>
<xs:element name="gender" type="tns:gender"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="gender">
<xs:restriction base="xs:string">
<xs:enumeration value="M"/>
<xs:enumeration value="F"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
端點:
@Endpoint
public class EmployeeWebService {
private static final String NAMESPACE_URI = "http://spring/demo/webservice";
private final List<Employee> employees = new ArrayList<>();
@PostConstruct
public void init() {
employees.addAll(
Arrays.asList(
createEmployee("John Doe", 30, Gender.M, "Manager"),
createEmployee("Jane Doe", 27, Gender.F, "QA"),
createEmployee("Bob Johns", 28, Gender.M, "Programmer"),
createEmployee("Tiffany Collins", 24, Gender.F, "CEO"),
createEmployee("Alice", 25, Gender.F, "Secretary")
)
);
}
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getEmployeeRequest")
@ResponsePayload
public GetEmployeeResponse get(@RequestPayload GetEmployeeRequest request) {
Employee found = employees.stream()
.filter(emp -> emp.getName().equals(request.getName()))
.findFirst()
.orElseThrow(() -> new RuntimeException("Not found"));
GetEmployeeResponse response = new GetEmployeeResponse();
response.setEmployee(found);
return response;
}
}
SOAP getEmployeeRequest:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:gs="http://spring/demo/webservice">
<soapenv:Header/>
<soapenv:Body>
<gs:getEmployeeRequest>
<gs:name>Alice</gs:name>
</gs:getEmployeeRequest>
</soapenv:Body>
</soapenv:Envelope>
使用提供的代碼,我收到了錯誤訊息:
<faultstring xml:lang="en">No adapter for endpoint [public spring.demo.webservice.GetEmployeeResponse com.abondarenkodev.demo.spring.webservice.controller.EmployeeWebService.get(spring.demo.webservice.GetEmployeeRequest)]: Is your endpoint annotated with @Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?</faultstring>
我找到了一種使用 JAXBElement 包裝回應和請求類的可能解決方案。帶有它的端點方法如下所示:
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getEmployeeRequest")
@ResponsePayload
public JAXBElement<GetEmployeeResponse> get(@RequestPayload JAXBElement<GetEmployeeRequest> request) {
Employee found = employees.stream()
.filter(emp -> emp.getName().equals(request.getValue().getName()))
.findFirst()
.orElseThrow(() -> new RuntimeException("Not found"));
GetEmployeeResponse response = new GetEmployeeResponse();
response.setEmployee(found);
return new JAXBElement<>(
QName.valueOf("GetEmployeeResponse"),
GetEmployeeResponse.class,
response
);
}
JAXBElement 有兩個選項:jakarta.xml.bind.JAXBElement 和 javax.xml.bind.JAXBElement。使用 jakarta 元素,我得到了相同的“無配接器”訊息,使用 javax 元素,我得到了“未找到”例外,因為 request.getValue() 為空。
我發現的第二種可能的解決方案是檢查請求和回應生成的類是否使用 XmlRootElement 進行了注釋,并且它們確實被注釋了。這是我的pom檔案:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.abondarenkodev.demo.spring.webservice</groupId>
<artifactId>spring-soap-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-soap-demo</name>
<description>Demo project for Spring Boot WebServices</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.6.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<source>${project.basedir}/src/main/resources/xsd</source>
</sources>
<outputDirectory>${project.build.directory}/generated-sources/jaxb/</outputDirectory>
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>
</plugins>
</build>
</project>
我將不勝感激。謝謝你。
uj5u.com熱心網友回復:
在我看到的 DefaultWsdl11Definition 中,targetNameSpace 與 xsd 中的不同。而在 ServletRegistrationBean /ws/* 應該是 /webservice/*
uj5u.com熱心網友回復:
我已通過將 Jaxb2 Maven 插件降級到 2.5.0 版解決了這個問題。這個插件的最后一個可用版本(3.1.0)生成帶有 jakarta 匯入的類,而 2.5.0 生成帶有 javax 匯入的類。
如果有人不小心踩到這個問題,并且您知道如何使用 jakarta 進口解決此問題,請告訴我。
我的專案的最終 pom 檔案如下所示(控制器中不需要 JAXBElement):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo.spring.webservice</groupId>
<artifactId>demo-spring-webservice</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-spring-webservice</name>
<description>Demo project for Spring Boot WebServices</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<source>${project.basedir}/src/main/resources/xsd</source>
</sources>
<outputDirectory>${project.build.directory}/generated-sources/jaxb/</outputDirectory>
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>
</plugins>
</build>
</project>
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/495844.html