java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory

java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory

Spring boot version 2.4.4

Java version 15

@Bean
    public WebClient webClient() {
        return WebClient.builder().baseUrl(BASE_URL)
                .defaultHeaders(header -> header.setBasicAuth("test",
                        "testpwd"))
                .clientConnector(new ReactorClientHttpConnector(HttpClient.newConnection()))
                .exchangeStrategies(ExchangeStrategies.builder().codecs(configurer -> {
                    configurer.defaultCodecs().jaxb2Encoder(new Jaxb2XmlEncoder());
                    configurer.defaultCodecs().jaxb2Decoder(new Jaxb2XmlDecoder());
                }).build()).build();
        
    }

使用 Spring 启动 2.4.4 webclient 并尝试使用具有 XML 响应的服务。

public Mono<ServerResponse> retrieveServices() {

        // Headers can be passed here or while building the client
        Mono<DirectoryOfService> serviceMono = webClient
             .get().uri("/api/v1/test/services")
            .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
            .accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML)
            .retrieve().bodyToMono(DirectoryOfService.class);

    }

错误:-

    org.springframework.core.codec.CodecException: Could not create JAXBContext for class [class com.test.model.DirectoryOfService]: Implementation of JAXB-API has not been found on module path or classpath.; nested exception is javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
 - with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory]
    at org.springframework.http.codec.xml.JaxbContextContainer.lambda$getJaxbContext[=15=](JaxbContextContainer.java:58) ~[spring-web-5.3.5.jar:5.3.5]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    |_ checkpoint ⇢ Body from GET https://test.com/api/v1/services [DefaultClientResponse]
    |_ checkpoint ⇢ HTTP GET "/api/v1/services" [ExceptionHandlingWebHandler]
Stack trace:
        at org.springframework.http.codec.xml.JaxbContextContainer.lambda$getJaxbContext[=15=](JaxbContextContainer.java:58) ~[spring-web-5.3.5.jar:5.3.5]
        at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708) ~[na:na]
        at org.springframework.http.codec.xml.JaxbContextContainer.getJaxbContext(JaxbContextContainer.java:52) ~[spring-web-5.3.5.jar:5.3.5]
        at org.springframework.http.codec.xml.JaxbContextContainer.createUnmarshaller(JaxbContextContainer.java:47) ~[spring-web-5.3.5.jar:5.3.5]
        at org.springframework.http.codec.xml.Jaxb2XmlDecoder.initUnmarshaller(Jaxb2XmlDecoder.java:235) ~[spring-web-5.3.5.jar:5.3.5]
        at org.springframework.http.codec.xml.Jaxb2XmlDecoder.unmarshal(Jaxb2XmlDecoder.java:216) ~[spring-web-5.3.5.jar:5.3.5]
        at org.springframework.http.codec.xml.Jaxb2XmlDecoder.decode(Jaxb2XmlDecoder.java:195) ~[spring-web-5.3.5.jar:5.3.5]
        at org.springframework.http.codec.xml.Jaxb2XmlDecoder.lambda$decodeToMono(Jaxb2XmlDecoder.java:183) ~[spring-web-5.3.5.jar:5.3.5]
        at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:113) ~[reactor-core-3.4.4.jar:3.4.4]
        at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.4.4.jar:3.4.4]
        at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:295) ~[reactor-core-3.4.4.jar:3.4.4]
        at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) ~[reactor-core-3.4.4.jar:3.4.4]
        at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815) ~[reactor-core-3.4.4.jar:3.4.4]
        at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:159) ~[reactor-core-3.4.4.jar:3.4.4]
        at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) ~[reactor-core-3.4.4.jar:3.4.4]
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:259) ~[reactor-core-3.4.4.jar:3.4.4]
        at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) ~[reactor-core-3.4.4.jar:3.4.4]
        at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:401) ~[reactor-netty-core-1.0.5.jar:1.0.5]
        at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:416) ~[reactor-netty-core-1.0.5.jar:1.0.5]
        at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:470) ~[reactor-netty-core-1.0.5.jar:1.0.5]
        at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:685) ~[reactor-netty-http-1.0.5.jar:1.0.5]
        at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94) ~[reactor-netty-core-1.0.5.jar:1.0.5]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) ~[netty-codec-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296) ~[netty-codec-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1534) ~[netty-handler-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1283) ~[netty-handler-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1330) ~[netty-handler-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508) ~[netty-codec-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447) ~[netty-codec-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.60.Final.jar:4.1.60.Final]
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.60.Final.jar:4.1.60.Final]
        at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]
Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:278) ~[jaxb-api-2.3.1.jar:2.3.0]
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:421) ~[jaxb-api-2.3.1.jar:2.3.0]
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721) ~[jaxb-api-2.3.1.jar:2.3.0]
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:662) ~[jaxb-api-2.3.1.jar:2.3.0]
    at org.springframework.http.codec.xml.JaxbContextContainer.lambda$getJaxbContext[=15=](JaxbContextContainer.java:54) ~[spring-web-5.3.5.jar:5.3.5]
    at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708) ~[na:na]
    at org.springframework.http.codec.xml.JaxbContextContainer.getJaxbContext(JaxbContextContainer.java:52) ~[spring-web-5.3.5.jar:5.3.5]
    at org.springframework.http.codec.xml.JaxbContextContainer.createUnmarshaller(JaxbContextContainer.java:47) ~[spring-web-5.3.5.jar:5.3.5]
    at org.springframework.http.codec.xml.Jaxb2XmlDecoder.initUnmarshaller(Jaxb2XmlDecoder.java:235) ~[spring-web-5.3.5.jar:5.3.5]
    at org.springframework.http.codec.xml.Jaxb2XmlDecoder.unmarshal(Jaxb2XmlDecoder.java:216) ~[spring-web-5.3.5.jar:5.3.5]
    at org.springframework.http.codec.xml.Jaxb2XmlDecoder.decode(Jaxb2XmlDecoder.java:195) ~[spring-web-5.3.5.jar:5.3.5]
    at org.springframework.http.codec.xml.Jaxb2XmlDecoder.lambda$decodeToMono(Jaxb2XmlDecoder.java:183) ~[spring-web-5.3.5.jar:5.3.5]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:113) ~[reactor-core-3.4.4.jar:3.4.4]
    at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.4.4.jar:3.4.4]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:295) ~[reactor-core-3.4.4.jar:3.4.4]
    at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) ~[reactor-core-3.4.4.jar:3.4.4]
    at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815) ~[reactor-core-3.4.4.jar:3.4.4]
    at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:159) ~[reactor-core-3.4.4.jar:3.4.4]
    at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) ~[reactor-core-3.4.4.jar:3.4.4]
    at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:259) ~[reactor-core-3.4.4.jar:3.4.4]
    at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:142) ~[reactor-core-3.4.4.jar:3.4.4]
    at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:401) ~[reactor-netty-core-1.0.5.jar:1.0.5]
    at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:416) ~[reactor-netty-core-1.0.5.jar:1.0.5]
    at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:470) ~[reactor-netty-core-1.0.5.jar:1.0.5]
    at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:685) ~[reactor-netty-http-1.0.5.jar:1.0.5]
    at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94) ~[reactor-netty-core-1.0.5.jar:1.0.5]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
    at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) ~[netty-codec-4.1.60.Final.jar:4.1.60.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296) ~[netty-codec-4.1.60.Final.jar:4.1.60.Final]
    at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[netty-transport-4.1.60.Final.jar:4.1.60.Final]

build.gradle,

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    implementation group: 'com.sun.xml.bind', name: 'jaxb-impl', version: '3.0.0'
    implementation group: 'com.sun.xml.bind', name: 'jaxb-core', version: '3.0.0'
    implementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1'
        
}

删除 com.sun.xml.bind 并添加 glassfish 后,出现以下错误。

implementation 'org.glassfish.jaxb:jaxb-runtime:2.3.1'

错误:

org.springframework.core.codec.CodecException: Could not create JAXBContext for class [class com.test.model.DirectoryOfService]: 10 counts of IllegalAnnotationExceptions; nested exception is com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 10 counts of IllegalAnnotationExceptions
Class has two properties of the same name "section"
    this problem is related to the following location:
        at public com.test.model.Section com.test.model.DirectoryOfService.getSection()
        at com.test.model.DirectoryOfService
    this problem is related to the following location:
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
Class has two properties of the same name "name"
    this problem is related to the following location:
        at public java.lang.String com.test.model.Section.getName()
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
    this problem is related to the following location:
        at private java.lang.String com.test.model.Section.name
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
Class has two properties of the same name "test"
    this problem is related to the following location:
        at public java.util.List com.test.model.Section.getTest()
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
    this problem is related to the following location:
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
Class has two properties of the same name "code"
    this problem is related to the following location:
        at public java.lang.String com.test.model.Test.getCode()
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
    this problem is related to the following location:
        at private java.lang.String com.test.model.Test.code
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
Class has two properties of the same name "currency"
    this problem is related to the following location:
        at public java.lang.String com.test.model.Test.getCurrency()
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
    this problem is related to the following location:
        at private java.lang.String com.test.model.Test.currency
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
Class has two properties of the same name "includes"
    this problem is related to the following location:
        at public java.lang.String com.test.model.Test.getIncludes()
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
    this problem is related to the following location:
        at private java.lang.String com.test.model.Test.includes
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
Class has two properties of the same name "name"
    this problem is related to the following location:
        at public java.lang.String com.test.model.Test.getName()
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
    this problem is related to the following location:
        at private java.lang.String com.test.model.Test.name
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
Class has two properties of the same name "nonDiscountable"
    this problem is related to the following location:
        at public boolean com.test.model.Test.isNonDiscountable()
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
    this problem is related to the following location:
        at private boolean com.test.model.Test.nonDiscountable
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
Class has two properties of the same name "replicate"
    this problem is related to the following location:
        at public int com.test.model.Test.getReplicate()
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
    this problem is related to the following location:
        at private int com.test.model.Test.replicate
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
Class has two properties of the same name "validFrom"
    this problem is related to the following location:
        at public java.util.Date com.test.model.Test.getValidFrom()
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService
    this problem is related to the following location:
        at private java.util.Date com.test.model.Test.validFrom
        at com.test.model.Test
        at private java.util.List com.test.model.Section.test
        at com.test.model.Section
        at private com.test.model.Section com.test.model.DirectoryOfService.section
        at com.test.model.DirectoryOfService

示例响应文件,

<?xml version='1.0' encoding='UTF-8'?>
<DirectoryOfService>
    <Section Name="Directory">
        <Test>
            <Name>Mike</Name>
            <Code>USA</Code>
            <Replicate>0</Replicate>
            <ValidFrom>2016-06-30</ValidFrom>
            <Includes>Test Includes</Includes>
            <Currency>None</Currency>
            <NonDiscountable>false</NonDiscountable>
        </Test>
        <Test>
            <Name>Bingo</Name>
            <Code>USA</Code>
            <Replicate>0</Replicate>
            <ValidFrom>2016-06-30</ValidFrom>
            <Includes>Test Includes</Includes>
            <Currency>None</Currency>
            <NonDiscountable>false</NonDiscountable>
        </Test>
    </Section>
</DirectoryOfService>

型号classes,

DirectoryOfService class,

import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement(name="DirectoryOfService")
public class DirectoryOfService {

    @XmlElementRef(name = "Section")
    private Section section;

    
    public Section getSection() {
        return section;
    }

    public void setSection(Section section) {
        this.section = section;
    }

}

节课,

    @XmlRootElement(name="Section")
    public class Section {
    
        @XmlElementRef(name = "Test")
        private List<Test> test;
        @XmlAttribute(name = "Name")
        private String name;
        //public String text;
    
        public List<Test> getTest() {
            return test;
        }
    
        
        public void setTest(List<Test> test) {
            this.test = test;
        }
    
        
        public String getName() {
            return name;
        }
    
        
        public void setName(String name) {
            this.name = name;
        }
    
    }

Test class,

@XmlRootElement(name = "Test")
public class Test {

    @XmlElement(name = "Name")
    private String name;
    @XmlElement(name = "Code")
    private String code;
    @XmlElement(name = "Replicate")
    private int replicate;
    @XmlElement(name = "ValidFrom")
    private Date validFrom;
    @XmlElement(name = "Includes")
    private String includes;
    @XmlElement(name = "Currency")
    private String currency;
    @XmlElement(name = "NonDiscountable")
    private boolean nonDiscountable;

    public String getName() {
        return name;
    }

    
    public void setName(String name) {
        this.name = name;
    }

    
    public String getCode() {
        return code;
    }

    
    public void setCode(String code) {
        this.code = code;
    }

    
    public int getReplicate() {
        return replicate;
    }

    
    public void setReplicate(int replicate) {
        this.replicate = replicate;
    }

    
    public Date getValidFrom() {
        return validFrom;
    }

    
    public void setValidFrom(Date validFrom) {
        this.validFrom = validFrom;
    }

    
    public String getIncludes() {
        return includes;
    }

    
    public void setIncludes(String includes) {
        this.includes = includes;
    }

    
    public String getCurrency() {
        return currency;
    }

    
    public void setCurrency(String currency) {
        this.currency = currency;
    }

    
    public boolean isNonDiscountable() {
        return nonDiscountable;
    }

    
    public void setNonDiscountable(boolean nonDiscountable) {
        this.nonDiscountable = nonDiscountable;
    }

}

尽管您测试了类似的方法,请考虑复习 this Github issue, especially the last comment,我认为它会有所帮助。

一定要有合适版本的 JAXB 运行时。在您之前的问题中,Spring 似乎无法在您的类路径中找到合适的 JAXB 实现。对于您在依赖项 2.3.1 中指定的 jaxb-api 版本,请删除与 com.sun.xml.bind 相关的依赖项并包含以下依赖项:

implementation group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '2.3.1'

最近的 org.glassfish.jaxb jaxb-runtime 版本,比如说 3.0.0,取决于 org.glassfish.jaxb jaxb-core 而后者又取决于 jakarta.xml.bind jakarta.xml.bind-api,Java EE 的基于 Eclipse Foundation 的 JAXB 实现。如果你想使用 org.glassfish.jaxb:jaxb-runtime:3.0.0 包括以下依赖项:

implementation group: 'jakarta.xml.bind', name: 'jakarta.xml.bind-api', version: '3.0.0'

而不是之前的 JAXB API 您定义的:

implementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1'

请更改您的导入并仔细测试,我从未使用 Spring WebClient 和相关的 JAXB 编解码器对其进行测试。

关于 section 重复的问题,似乎 JAXB 正在尝试序列化 POJO 的字段和方法定义的属性。为避免该问题,请使用 @XmlAccessorType 注释显式定义访问类型。例如:

@XmlRootElement(name="DirectoryOfService")
@XmlAccessorType(XmlAccessType.FIELD)
public class DirectoryOfService {

    @XmlElementRef(name = "Section")
    private Section section;

    
    public Section getSection() {
        return section;
    }

    public void setSection(Section section) {
        this.section = section;
    }

}
@XmlRootElement(name="Section")
@XmlAccessorType(XmlAccessType.FIELD)
public class Section {

    @XmlElementRef(name = "Test")
    private List<Test> test;
    @XmlAttribute(name = "Name")
    private String name;
    //public String text;

    public List<Test> getTest() {
        return test;
    }

    
    public void setTest(List<Test> test) {
        this.test = test;
    }

    
    public String getName() {
        return name;
    }

    
    public void setName(String name) {
        this.name = name;
    }

}
@XmlRootElement(name = "Test")
@XmlAccessorType(XmlAccessType.FIELD)
public class Test {

    @XmlElement(name = "Name")
    private String name;
    @XmlElement(name = "Code")
    private String code;
    @XmlElement(name = "Replicate")
    private int replicate;
    @XmlElement(name = "ValidFrom")
    private Date validFrom;
    @XmlElement(name = "Includes")
    private String includes;
    @XmlElement(name = "Currency")
    private String currency;
    @XmlElement(name = "NonDiscountable")
    private boolean nonDiscountable;

    public String getName() {
        return name;
    }

    
    public void setName(String name) {
        this.name = name;
    }

    
    public String getCode() {
        return code;
    }

    
    public void setCode(String code) {
        this.code = code;
    }

    
    public int getReplicate() {
        return replicate;
    }

    
    public void setReplicate(int replicate) {
        this.replicate = replicate;
    }

    
    public Date getValidFrom() {
        return validFrom;
    }

    
    public void setValidFrom(Date validFrom) {
        this.validFrom = validFrom;
    }

    
    public String getIncludes() {
        return includes;
    }

    
    public void setIncludes(String includes) {
        this.includes = includes;
    }

    
    public String getCurrency() {
        return currency;
    }

    
    public void setCurrency(String currency) {
        this.currency = currency;
    }

    
    public boolean isNonDiscountable() {
        return nonDiscountable;
    }

    
    public void setNonDiscountable(boolean nonDiscountable) {
        this.nonDiscountable = nonDiscountable;
    }

}