Spring Grails应用程序响应.outputStream<&书信电报;升级到Grails 3.3后失败
我有一个最近从2.5升级到3.3的Grails应用程序。总的来说,一切正常,但今天我们遇到了一个似乎是其他人共同面临的问题,但我找不到解决方案 在控制器中,我有一个将字符串附加到response.outputStream的方法 代码现在显示为Spring Grails应用程序响应.outputStream<&书信电报;升级到Grails 3.3后失败,spring,servlets,grails,tomcat7,Spring,Servlets,Grails,Tomcat7,我有一个最近从2.5升级到3.3的Grails应用程序。总的来说,一切正常,但今天我们遇到了一个似乎是其他人共同面临的问题,但我找不到解决方案 在控制器中,我有一个将字符串附加到response.outputStream的方法 代码现在显示为 response.status = OK.value() response.contentType = 'text/csv;charset=UTF-8' response.setHeader "Content-disposition
response.status = OK.value()
response.contentType = 'text/csv;charset=UTF-8'
response.setHeader "Content-disposition", "attachment; filename=rcCandidate.csv"
response.outputStream << converted
response.outputStream.flush()
response.outputStream.close()
但在生产服务器上严重失败
$ java -version
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)
$ apt list | grep tomcat
tomcat7/trusty-security,trusty-updates,now 7.0.52-1ubuntu0.13 all [installed]
故障报告从以下内容开始:
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: javax/servlet/WriteListener
然后是堆栈跟踪,然后是
Caused by: java.lang.NoClassDefFoundError: javax/servlet/WriteListener
然后是关于WriteListener的更多堆栈跟踪和类似消息
我已经看到了替换这一行的建议
provided "org.springframework.boot:spring-boot-starter-tomcat"
与
但正如这里所指出的
这不是一个好主意,事实上,当我尝试它时,tomcat并没有启动
我相信我在某个地方读到过,用Tomcat8替换Tomcat7可能可以解决这个问题;然而,现在我在服务器上运行Ubuntu 14.04,而Tomcat8在存储库中不提供,所以测试它不是很简单
有人对我有什么建议吗?提前感谢。您可以通过在方法中添加@CompileStatic来解决此问题,但这并不总是可行的。我们在应用程序中通过添加静态实用程序方法解决了此问题:
@CompileStatic
public static sendResponseData(ServletOutputStream outputStream, String s) { // but this could be byte[] s or InputStream s or whatever you need
outputStream << s
}
为了方便起见,因为这一个也必须进行静态编译。Daniel,对于这个非常有用的信息,我非常感谢。为了防止其他人遇到同样的问题,我必须
导入groovy.transform.CompileStatic
和javax.servlet.ServletOutputStream
,以实现这一点。我还将这些方法输入为void(也许我还是太过挑剔了?)。非常感谢。我应该补充一点,我在另一个StackExchange post(可能是你的?)之后尝试过类似的方法,但直接将其应用于所讨论的控制器方法,基于所需的斗争量,这似乎不是正确的方法。这是好的,干净的,工作很好。再次感谢!我可能遇到过同一个帖子…我知道我们在这个帖子上工作了一段时间!我很高兴它对您有用,并感谢为其他需要此功能的人提供的附加信息!有没有一种方法可以编写一个集成测试,使它在本地框上失败,然后我们知道方法上的@CompileStatic可以工作
compile "org.springframework.boot:spring-boot-starter-tomcat"
@CompileStatic
public static sendResponseData(ServletOutputStream outputStream, String s) { // but this could be byte[] s or InputStream s or whatever you need
outputStream << s
}
@CompileStatic
public static flushOutputStream(ServletOutputStream outputStream) {
outputStream.flush()
}