JAXB 无法从soap (WSDL) 服务获取附件

问题描述 投票:0回答:1

我需要调用返回附件的 SOAP 服务。

定义“附加”数据的 XSD 是

<xs:complexType name="transferableFileData">
    <xs:complexContent>
      <xs:extension base="tns:transferableFile">
        <xs:sequence>
          <xs:element name="fileData" type="xs:base64Binary" minOccurs="0"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

我在 pom.xml 文件中使用此插件从 WSDL 和 XSD 文件生成类

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.15.1</version>
</plugin>

自动生成的类是这样的

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "transferableFileData", propOrder = {
    "fileData"
})
public class TransferableFileData
    extends TransferableFile
{

    protected byte[] fileData;

    
    public byte[] getFileData() {
        return fileData;
    }

   
    public void setFileData(byte[] value) {
        this.fileData = value;
    }

}

服务器的响应是:

Cache-Control: max-age=0
Cache-Control: no-cache
Cache-Control: no-store
Server-Timing: ak_p; desc="1705942361025_1611673733_335963847_52691_3577_46_71_-";dur=1
Server-Timing: origin; dur=520
Server-Timing: edge; dur=7
Server-Timing: cdn-cache; desc=MISS
Connection: keep-alive
Set-Cookie: LtpaToken2=Jss03JN+gXMYTd; Path=/; HttpOnly
Expires: Mon
Expires: 22 Jan 2024 16:52:41 GMT
Pragma: no-cache
Content-Length: 2912
Content-Language: en-US
Date: Mon
Date: 22 Jan 2024 16:52:41 GMT
Content-Type: Multipart/Related; boundary="----=_Part_11_2001319686.1705942360849"; type="application/xop+xml"; start-info="text/xml"
SOAPAction: ""
Accept: text/xml
------=_Part_11_2001319686.1705942360849
Content-Type: application/xop+xml; charset=utf-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <[email protected]>

<?xml version="1.0" encoding="utf-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns2:downloadPendingFileResponse xmlns:ns2="http://iris.somewhere.cp,/web_services/external/downloadFile" xmlns:ns3="http://iris.somewhere.com/web_services/external/uploadFile"><downloadPendingFileResult><fileExchangeNo>1174649</fileExchangeNo><fileName>TEST00001_2024-01-22-18.46.08.00000_APA.zip</fileName><fileData><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:[email protected]"/></fileData></downloadPendingFileResult></ns2:downloadPendingFileResponse></soapenv:Body></soapenv:Envelope>
------=_Part_11_2001319686.1705942360849
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-ID: <[email protected]>

�������f��G��v�+p�,����
��K�ɁZt �K�>b�La���^m��_э���1$�t�dqV�A;�ف� F�K��   ��ކO�X![

我的Java代码是这样的:

if (response instanceof JAXBElement) {

                DownloadPendingFileResponse downloadPendingFileResponse = ((JAXBElement<DownloadPendingFileResponse>) response).getValue();
                if(downloadPendingFileResponse == null) {

及以后

final TransferableFileData transferableData = response.getDownloadPendingFileResult();
...
byte[] bytes = transferableData.getFileData();

log.info("length {}", bytes.length);

但是长度始终为零。看来我无法正确获取文件。

我注意到 WSDL 将 fileData 元素定义为 base64Binary,而 POJO 将它们定义为 byte[]。数据流似乎没有被整理。知道如何解决这个问题吗?

java spring-boot web-services jaxb wsdl
1个回答
0
投票

我在 WSDL 服务上获得了完全相同的 XSD

<complexType name="myType">
    <sequence>
...
        <element name="myFile" type="xsd:base64Binary"/>
...
    </sequence>
</complexType>

这由

org.apache.cxf:cxf-codegen-plugin
:

生成
@XmlElement(required = true)
protected byte[] myFile;

但是为了进行解组,我必须将 XSLT 设置为

jaxws:feature
spring 客户端,以便告诉 CXF 理解响应中的
href
(文件
transform.xsl
的内容如下):

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" >

    <xsl:key name="multiref-by-id" match="multiRef" use="@id"/>

    <xsl:template match="/">
        <xsl:copy>
            <xsl:apply-templates select="@*|*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[starts-with(@href, '#')]">
        <xsl:copy>
            <xsl:apply-templates select="@* |
             key('multiref-by-id', substring-after(@href, '#'))/@* |
            key('multiref-by-id', substring-after(@href, '#'))/node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@href[starts-with(., '#')] | multiRef[@id] | @soapenc:root"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

这是在 XML Spring Config 中定义的 bean :

    <bean id="xsltFeature" class="org.apache.cxf.feature.transform.XSLTFeature">
        <property name="inXSLTPath" value="transform.xsl" />
        <property name="outXSLTPath" value="transform.xsl" />
    </bean>

    <jaxws:client id="myService" serviceClass="my.web.Service" address="myurl">
        <jaxws:features>
            <ref bean="xsltFeature" />
        </jaxws:features>
    </jaxws:client>

通过这样做,我可以通过Java中的

myFile
的getter读取附件的内容,而无需额外的配置。

我认为您可以对其进行调整,以使其在您自己的应用程序上下文中工作。

© www.soinside.com 2019 - 2024. All rights reserved.