在 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
将是一个零大小的文件!当我在 StreamResult、doExecute 方法中设置断点时,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
在这里自动连接 !
目前,Struts2 Spring 默认情况下对象工厂将尝试确定自动装配组件的最佳策略,顺便说一句,这是遗留行为。
使用此行为,StreamResult
的实例是使用 StreamResult(InputStream in)
构造函数创建的,并且 Spring 也会尝试注入构造函数参数。
为避免这种情况,请在您的 struts.xml 文件中将 struts.objectFactory.spring.autoWire.alwaysRespect
常量设置为 true
。
<constant name="struts.objectFactory.spring.autoWire.alwaysRespect" value="true" />
这将确保始终遵守自动装配策略。 (默认为名称。)
我们正在项目中使用 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
将是一个零大小的文件!当我在 StreamResult、doExecute 方法中设置断点时,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
在这里自动连接 !
目前,Struts2 Spring 默认情况下对象工厂将尝试确定自动装配组件的最佳策略,顺便说一句,这是遗留行为。
使用此行为,StreamResult
的实例是使用 StreamResult(InputStream in)
构造函数创建的,并且 Spring 也会尝试注入构造函数参数。
为避免这种情况,请在您的 struts.xml 文件中将 struts.objectFactory.spring.autoWire.alwaysRespect
常量设置为 true
。
<constant name="struts.objectFactory.spring.autoWire.alwaysRespect" value="true" />
这将确保始终遵守自动装配策略。 (默认为名称。)