Sping Boot 在提供JSP内容时无限期挂起

55ooxyrt  于 2023-09-28  发布在  其他
关注(0)|答案(2)|浏览(130)

该应用程序以前在另一台机器上运行,因此代码应该都是有效的。我把它移植到另一台机器上有困难。也就是说,问题是当需要提供JSP视图时,应用程序会无限期地挂起。
控制器看起来像这样:

@RequestMapping(value = "", method = RequestMethod.GET)
    public String bookings(BookingFilterRequest bookingFilterRequest,
                           PeriodRequest periodRequest,
                           Model model,
                           BindingResult bindingResult) {
        // Fetch data from database, do things
        return "booking/bookings"; // serve JSP view
    }

代码运行良好,直到return "booking/bookings"行,这是它挂起的地方。JSP视图在正确的文件夹中,否则它将给予not found错误。
我试着安装了与之前服务器相同的java和gradle版本,没有任何变化。
版本信息(新服务器上默认安装的版本):

openjdk 11.0.4 2019-07-16
OpenJDK Runtime Environment (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3)
OpenJDK 64-Bit Server VM (build 11.0.4+11-post-Ubuntu-1ubuntu218.04.3, mixed mode)
Gradle 4.4.1

旧服务器有java 10.0.2gradle 5.0
我怎样才能让它运行而不挂起?
更新:
如果我等10分钟,它就会神奇地开始工作。但是重新启动应用程序会使它再次挂起,直到您再次等待10分钟。
更新2:
如果我将控制台打印行放在JSP文件中,那么它们就不会被打印出来。这意味着JSP不会被执行。

wljmcqd8

wljmcqd81#

解决方案:

看起来像是Tomcat中的一个bug。我终于能够让它工作使用码头。步骤:
1)使用Jetty而不是Tomcat。在build.gradle dependencies部分,注解掉org.springframework.boot:spring-boot-starter-weborg.apache.tomcat.embed:tomcat-embed-jasper行并添加:

compile("org.springframework.boot:spring-boot-starter-web") {
   exclude module: "spring-boot-starter-tomcat"
}
compile("org.springframework.boot:spring-boot-starter-jetty")
compile("org.eclipse.jetty:apache-jsp")
compile "javax.servlet:jstl:1.2"

2)建立战争档案。Jar文件对我不起作用,因为当我使用jar时,Jetty没有找到JSP文件。如果你不能构建war文件,那么确保你的build.gradle中有这个:

plugins {
  id 'war'
}

它需要在buildscript代码块之后。
使用以下命令构建war文件
gradle build war
它将出现在您的build/libs/目录中。
3)运行应用程序:
java -jar application.war
额外的东西
这里是我的完整的build.gradle文件,如果它对任何人都有用的话。我知道有一些不必要的线条。

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.2.RELEASE")
    }
}

plugins {
   id 'war'
}
apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

sourceCompatibility = 1.8
targetCompatibility = 1.8
mainClassName = 'com.project.foo.bar.Application'

bootJar {
    baseName = 'bar'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web") {
      exclude module: "spring-boot-starter-tomcat"
    }
    compile("org.springframework.boot:spring-boot-starter-jetty")    
    //compile("org.springframework.boot:spring-boot-starter-web")
    //compile("org.springframework.boot:spring-boot-starter-security")

    // persistence
    compile("org.springframework:spring-orm:4.0.3.RELEASE")
    compile("commons-dbcp:commons-dbcp:1.4")
    compile("org.hibernate:hibernate-core:4.3.11.Final")
    compile("org.hibernate:hibernate-entitymanager:4.3.11.Final")
    runtime('mysql:mysql-connector-java')

    // servlets
    compile("javax.servlet:javax.servlet-api:4.0.1")
    compile("javax.servlet.jsp:javax.servlet.jsp-api:2.3.1")
    // runtime("org.apache.tomcat.embed:tomcat-embed-jasper")
    compile("org.eclipse.jetty:apache-jsp")
    compile "javax.servlet:jstl:1.2"
}
dxxyhpgq

dxxyhpgq2#

我也刚刚遇到这个问题。这只会发生在我们的servlet过滤器中的某个代码路径之后,但我不知道这是如何导致的。
经过一些深入的调试,我发现JSP编译阶段正在做一些事情。我不知道是什么,但CPU被最大化,请求被挂起。这是在tomcat-embed-jasper.jar中发生的,所以是的,特定于Tomcat。
由于这只发生在servlet过滤器之后的编译期间,我想知道我们是否可以预编译它们。结果是的!
我从这个答案中添加了preCompileJspsAtStartup bean,现在一切正常:https://stackoverflow.com/a/35651338/397103
(Sping Boot 3、Tomcat 10.1.10、Java 17)

相关问题