【问题标题】:Why don't my .jsp files work with Spring Boot using Spring MVC为什么我的 .jsp 文件不能与使用 Spring MVC 的 Spring Boot 一起使用
【发布时间】:2018-03-20 10:20:04
【问题描述】:

我花了一整天的时间试图获得一个简单的 Spring Boot 应用程序来显示我的 .jsp 文件。我无法切换到另一种技术(要求),也无法让它发挥作用。这是一个非常简单的应用程序。这是文件结构:

pom.xml
src/
  main/
    java/
      hello/
        HelloController.java
        MVCApplication.java
    resources/
      application.properties
      static/
        index.html
      templates/
        pages/
          helloworld.jsp

这是我的两个 java 文件:

HelloController.java:

// @RestController // From when I first posted this question. 
@Controller
public class HelloController {

  // Should I add a "produces" attribute to this? I don't know what to use for jsp.
  @RequestMapping("/hello")
  public String hello(Model model) {
    model.addAttribute("greeting", "Hello Spring MVC");
    // I see this message in the output, so I know this method is getting called.
    System.err.printf("Setting \"greeting\" to \"Hello Spring MVC\"%n");
    return "helloworld";
  }
}

MVCApplication.java:

@SpringBootApplication
public class MVCApplication extends SpringApplication {

  public static void main(String[] args) {
    SpringApplication.run(MVCApplication.class, args);
  }

  // Since I have the properties spring.mvc.view.prefix and spring.mvc.view.suffix
  // defined in applications.properties, I don't think I need this method.
  // I have tried it both with and without this method. It doesn't work either way.
  @Bean
  public ViewResolver getViewResolver() {
    // I see this line in the output, which confirms that this method gets called.
    System.err.printf("Creating custom JSP View Resolver%n"); // NON-NLS
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/templates/pages/");
    resolver.setSuffix(".jsp");
    resolver.setViewClass(JstlView.class);
    return resolver;
  }
}

我的 helloworld.jsp 文件很简单,但是我在浏览器中从来没有看到过:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Spring MVC -HelloWorld</title>
</head>
<body>
  <h1>Greeting: ${greeting}</h1>
</body>
</html>

我在 applications.properties 中定义了三个属性。

spring.mvc.view.prefix=/templates/pages/
spring.mvc.view.suffix=.jsp

server.port=7070

我知道正在读取属性,因为我需要在浏览器中指定端口 7070 才能看到任何内容。所以所有这些属性都应该起作用。

我的 pom 文件似乎具有所有正确的依赖项。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>

    <groupId>org.springframework</groupId>
    <artifactId>gs-spring-boot</artifactId>
    <version>0.1.0</version>

        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.2.RELEASE</version>
        </parent>

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>

            <!--JSP Enabled: -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-jasper</artifactId>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
            </dependency>
        </dependencies>

        <properties>
            <java.version>1.8</java.version>
        </properties>

        <packaging>jar</packaging>

        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>

    </project>

templates 目录曾经被称为 WEB-INF,但我在某处读到 WEB-INF 不适用于 Spring Boot。但这两种方法都不起作用。

我转到 localhost:7070/hello,我得到的只是一条错误消息:

出现意外错误(类型=未找到,状态=404)。 /templates/pages/helloworld.jsp

这告诉我我的控制器方法正在被调用,但它要么没有找到我的 .jsp 文件,要么甚至没有在寻找它。

我在这个论坛上看过很多类似的问题,到目前为止,没有任何帮助。人们提出了一些建议,比如改用百里香叶,这对其他人来说可能很好,但对我来说不是一个选择。谁能弄清楚我做错了什么?


附录:

在 Vipul Singh 的建议下,我尝试将控制器方法更改为:

@RequestMapping("/hello")
public ModelAndView hello(Model theModel) {
  // theModel.addAttribute("greeting", "Hello Spring MVC");  // this didn't work.
  ModelAndView modelView= new ModelAndView("helloworld", "helloworld", theModel);
  modelView.addObject("greeting", "Hello Spring MVC"); // This didn't work either.
  return modelView;
}

没有用。我得到了和以前一样的错误信息。

修订版。最初我使用@RestController,这是错误的。我还将 spring.boot.starter.parent 版本从 1.5.7 减少到 1.5.2

【问题讨论】:

    标签: jsp spring-mvc spring-boot


    【解决方案1】:

    问题原来是多种因素的组合,但最重要的细节是我如何打包应用程序以及如何启动它。 Spring 文档说 (https://docs.spring.io/spring-boot/docs/2.0.0.M5/reference/htmlsingle/#boot-features-jsp-limitations) 将文件打包为 .war 文件,声称 .jar 文件不起作用。事实证明,.jar 文件偶尔可以工作,但 .war 文件总是可以工作。但是应用程序需要从该文件启动,而不是从我的 IDE 构建的磁盘上的类文件启动。一旦我开始从打包的 war 文件中启动它,它就开始工作了。

    也就是说,关于如何编写映射方法有各种建议,而且它们似乎都可以正常工作,所以这不是问题。

    【讨论】:

      【解决方案2】:

      尝试用这个替换你的代码,它会成功的。
      它是如何工作的。
      当您使用诸如https://xxx/yyy/hello 之类的URL 访问浏览器时,您将触发此控制器,现在此控制器将加载您的jsp 页面,即helloworld,由viewHolder 调用,现在我们创建ModelAndView 对象和根据我们的要求传递值,viewHolder 将合并这些值并将其传递回控制器,然后控制器将其作为响应传递回用户。

       @Controller
          public class HelloController {
      
            // Should I add a "produces" attribute to this? I don't know what to use for jsp.
            @RequestMapping("/hello")
            public getForm() {
              ModelAndView model= new ModelAndView("helloworld");
              model.addObject("greeting", "Hello Spring MVC");
              return model;
            }
          }  
      

      您也可以将此函数编写为字符串类型。

      @Controller
          public class HelloController {
      @RequestMapping("/hello")
            public string getForm(ModelMap model) {
              model.addAttributes("greeting", "Hello Spring MVC");
              return "helloworld";
            }
          }      
      

      如果仍然无法正常工作,请检查您的 spring 调度程序 servlet 和 web xml 是否定义正确。
      spring dispatcher servlet中应该有这样的东西。

      <bean id="viewResolver"
              class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      
              <property name="prefix">
                  <value>/WEB-INF/views/</value>
              </property>
              <property name="suffix">
                  <value>.jsp</value>
              </property>
      
          </bean>
      

      WEB-INF 是我在 src 中的根文件夹,views 是包含 jsp 页面的文件夹

      【讨论】:

      • 您的代码无法编译。你在哪里说: [public ModelAndView hello("helloworld") { ] 你传递了一个值,你应该在其中声明一个参数。也就是说,我尝试了类似的东西。我声明了一个 Model 类型的参数,并将它传递给 ModelAndView 的构造函数。然后我尝试添加属性名称/值,返回 modelAndView。我在模型和modelAndView上都试过了。都没有奏效。在这两种情况下,浏览器都给了我这条消息:出现意外错误(类型=未找到,状态=404)。 /templates/pages/helloworld.jsp。但你可能走在正确的轨道上。
      • 我已经用正确的解释更新了答案,希望这会有所帮助
      • 你是用Maven构建的吗?因为 Maven 似乎并不期望在 src 文件夹中找到 WEB-INF。当我把它放在那里时,它不会在我构建后出现在 jar 文件中。另外,您使用的是 Spring Boot 吗?这里的任务不是如何让 jsp 文件工作。它让他们在 Spring Boot 中工作。我不认为 Spring Boot 应该需要一个 web.xml 文件,如果是,我不确定我应该把它放在哪里。
      • 是的,我正在使用 MAVEN 来配置我的项目并构建。
      • 谢谢。所以我接下来的两个问题是:1)你如何让它接受在你的jar文件中包含WEB-INF文件夹。 2) 你在使用 Spring Boot 吗?
      【解决方案3】:

      改变这个:

      @RestController
      

      到这里:

      @Controller
      

      您已将控制器声明为 REST 控制器,因此默认情况下,响应是“无视图”。通常当您想像您一样重新发送 JSON 序列化响应时使用它。

      你要使用的是全栈Sping MVC,这里MVC的控制器是@Controller`注解的组件。

      还请记住,如果控制器返回 String,它必须是 redirect: forward: 或(我猜你的情况是要渲染的模板的名称。

      【讨论】:

      • 你能解释一下你的答案吗?
      • @RestController 更改为@Controller 让我无法将请求映射到我的方法。 (我试过了。)即使我将 Controller 与 Rest 接口分开,这听起来是个好主意,我仍然需要将输入映射到一个方法,并返回一个将被解释为 .jsp 文件名的值。您的陈述是有道理的,但代码示例会有所帮助。
      • @MiguelMunoz 将@RestController 更改为@Controller 让我无法将请求映射到我的方法。 为什么会这样? @RequestMappings 在这两种情况下都是一样的。
      • 好问题。当我第一次尝试它时,它不起作用。现在它似乎正在工作,虽然我没有看到我的 jsp 页面。但是,代替字符串,我现在收到一条错误消息,表明它正在寻找具有正确名称的 jsp 文件。我还有一些问题需要解决,但看起来我正在取得进展。
      • 你的建议让我离目标更近了,但它仍然没有命中。现在我收到一条错误消息:“出现意外错误(类型=未找到,状态=404)。/templates/pages/helloworld.jsp”所以它正在正确路径中搜索 .jsp 文件,但它是没有找到它。我已经使用 Class.getResourceAsStream() 验证了该文件具有正确的路径,但它仍然无法正常工作。据我所知,它一定与 Spring Boot 配置事物的方式有关,但我不知道如何修复它。
      猜你喜欢
      • 1970-01-01
      • 2018-01-05
      • 2016-10-15
      • 2019-06-20
      • 2020-07-17
      • 2018-12-25
      • 1970-01-01
      • 2016-12-27
      • 2021-12-09
      相关资源
      最近更新 更多