在 Spring 中定义 java.io.FileInputStream 的 bean 使 Struts2 流结果不起作用

Define a bean of java.io.FileInputStream in Spring makes the Struts2 stream result not work

我们正在项目中使用 Struts2 和 spring。

考虑具有 结果的简单操作

@Action(value = "sample-export", 
        results = { @Result(name = "success", type = "stream", params = {
        "inputName", "exportInputStream", "contentType",
        "${exportContentType}; charset=UTF-8", "Content-Disposition",
        "attachment; filename=\"${filename}\"", "contentDisposition",
        "attachment; filename=\"${filename}\"", "bufferSize", "2048" }) })
public String export() throws ClientException {
    //buildExportInputStream() creates and returns new ByteArrayOutputStream by using jasper
    exportInputStream = buildExportInputStream();
    LOG.debug("Exporting to {} file ", getFilename());

    return SUCCESS;

}

这很好用。

当我在 spring-applicaiton-context.xml !!

中添加以下行时发生了一些奇怪的事情
  <bean id="sampleStream" class="java.io.FileInputStream" >
        <constructor-arg  value="c:/sample.jks"/>  
  </bean>

添加以上行后,操作的 inputStream 将是一个零大小的文件!当我在 StreamResultdoExecute 方法中设置断点时,inputStream.read(oBuff) 总是 -1.


创建的bean (sampleStream) 将被其他bean 引用,例如<ref bean="sampleStream"/>。当我更改此结构并使用 sampleStream 作为内联参数时,它工作正常:

<bean id="anotherBean" class="foo.bar">
        <bean class="org.xml.sax.InputSource">
            <constructor-arg index="0" >
                    <bean class="java.io.FileInputStream">
                        <constructor-arg index="0" type="java.lang.String" value="c:/sample.jks"/>
                    </bean>
            </constructor-arg>
        </bean>
    </property>
</bean>

或者这也可以修复它:

<bean id="sampleStream" class="java.io.FileInputStream" autowire-candidate="false">
            <constructor-arg  value="c:/sample.jks"/> 
  </bean>

你能帮我找出问题所在吗?!为什么定义一个FileInputStream的bean会导致这种情况发生?!

已更新

我发现 sampleStream 将自动连接到 org.apache.struts2.dispatcher.StreamResult 并且我看到了这个日志:

DEBUG ort.DefaultListableBeanFactory Returning cached instance of singleton bean 'sampleStream'
DEBUG ort.DefaultListableBeanFactory Autowiring by type from bean name 'org.apache.struts2.dispatcher.StreamResult' via constructor to bean named 'sampleStream'

这个错误的自动装配是问题的根源!有没有解决方法。顺便说一下,为什么 sampleStream 在这里自动连接 !

https://issues.apache.org/jira/browse/WW-4559

目前,Struts2 Spring 默认情况下对象工厂将尝试确定自动装配组件的最佳策略,顺便说一句,这是遗留行为。

使用此行为,StreamResult 的实例是使用 StreamResult(InputStream in) 构造函数创建的,并且 Spring 也会尝试注入构造函数参数。

为避免这种情况,请在您的 struts.xml 文件中将 struts.objectFactory.spring.autoWire.alwaysRespect 常量设置为 true

<constant name="struts.objectFactory.spring.autoWire.alwaysRespect" value="true" />

这将确保始终遵守自动装配策略。 (默认为名称。)