带有 Spring 引导的 JSP

JSPs with Spring Boot

我一直在研究一个用 spring initialzr 初始化的 spring-boot 项目。生成的包没有 /webapp 目录,因此必须添加 /webapp 目录。我从 spring 文档中读到 spring 从 /staticresources 检测静态文件。我放置了 3 个不同的 index.jsp 来测试我的控制器显示哪一个。以下是代码片段。

目录树:

├── HELP.md
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── databasedisplay
│   │   │           └── app
│   │   │               ├── AppApplication.java
│   │   │               ├── config
│   │   │               │   ├── WebAppInitializer.java
│   │   │               │   └── WebConfig.java
│   │   │               ├── controller
│   │   │               │   ├── HomeController.java
│   │   │               │   └── IndexController.java
│   │   │               ├── repository
│   │   │               └── ServletInitializer.java
│   │   ├── resources
│   │   │   ├── application.properties
│   │   │   ├── index.jsp
│   │   │   ├── static
│   │   │   │   └── index.jsp
│   │   │   └── templates
│   │   └── webapp
│   │       └── WEB-INF
│   │           └── views
│   │               └── index.jsp
│   └── test
│       └── java
│           └── com
│               └── databasedisplay
│                   └── app
│                       └── AppApplicationTests.java
└── target
    ├── classes
    │   ├── application.properties
    │   ├── com
    │   │   └── databasedisplay
    │   │       └── app
    │   │           ├── AppApplication.class
    │   │           ├── config
    │   │           │   ├── WebAppInitializer.class
    │   │           │   └── WebConfig.class
    │   │           ├── controller
    │   │           │   ├── HomeController.class
    │   │           │   └── IndexController.class
    │   │           └── ServletInitializer.class
    │   ├── index.jsp
    │   └── static
    │       └── index.jsp
    ├── generated-sources
    │   └── annotations
    ├── generated-test-sources
    │   └── test-annotations
    ├── maven-status
    │   └── maven-compiler-plugin
    │       ├── compile
    │       │   └── default-compile
    │       │       ├── createdFiles.lst
    │       │       └── inputFiles.lst
    │       └── testCompile
    │           └── default-testCompile
    │               ├── createdFiles.lst
    │               └── inputFiles.lst
    └── test-classes
        └── com
            └── databasedisplay
                └── app
                    └── AppApplicationTests.class

index.jsp(在“/资源”中)

<html>
<head></head>
<body>
    <h1>This is the body of the sample view in /resources</h1>
</body>

index.jsp(在“/static”中)

<html>
    <head></head>
    <body>
        <h1>This is the body of the sample view in /static</h1>
    </body>
</html>

index.jsp(在'/WEB-INF/views/')

<html>
    <head></head>
    <body>
        <h1>This is the body of the sample view in WEB-INF/views</h1>
    </body>
</html>

控制器

@Controller
public class IndexController {

    @RequestMapping(value = "/indexA", method = RequestMethod.GET)
    public String index() {
        return "index";
    }
}

配置类

WebConfig.java

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public ViewResolver getViewResolver() {
        InternalResourceViewResolver resolver
                = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    @Override
    public void configureDefaultServletHandling(
            DefaultServletHandlerConfigurer configurer) {
        configurer.enable("testServlet");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/resources/").setCachePeriod(3600)
                .resourceChain(true).addResolver(new PathResourceResolver());
    }


}

WebInitializer.java

    public class WebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();

        context.scan("com.databasedisplay.app");

        container.addListener(new ContextLoaderListener(context));

        ServletRegistration.Dynamic dispatcher = container.addServlet("mvc", new DispatcherServlet(context));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

}

问题是当我 运行 与 mvn spring-boot:runmvn clean package spring-boot:run 时,目录树中显示的 \target 目录没有 index.jsp 来自 \WEB-INF\views\(实际上目标目录根本没有 WEB-INF 目录)。但是当我 curl http://localhost:8080/indexA 时我仍然得到以下输出: This is the body of the sample view in WEB-INF/views

  1. 谁能解释一下视图解析器是如何将视图名称映射到相应视图的? (我研究了 InternalResourceViewResolver 以及如何设置前缀和后缀,但这仍然没有解释它如何在不在目标中时呈现 jsp)

  2. 有人可以指出 mvn spring-boot:runmvn clean package spring-boot:run 之间的区别,因为后者在目标中有 WEB-INF 目录。

  3. 为什么我得到 index.jsp 对应于 /WEB-INF 而不是 curl 上的其他视图?

JSP 是遗留 Java 企业应用程序的一部分,不是 Spring Boot/MVC 的核心,它是更现代的模板引擎方法(尽管 Spring 基于 Java EE)。如果您有充分的理由使用 JSP,它就可以工作。但是对于 Spring,MVC approach/implementation 是使用更现代的模板引擎以及 ThymeleafFreeMarker 等技术, Groovy 标记,和小胡子

问题 1 如果您已正确配置 pom.xml,则可以使用不同的启动器来配置您的应用程序 deployed/run。 JSP 不是 Spring 的标准解决方案,应该单独配置,它需要配置以便将 JSP 编译到它们各自的位置,以便 Tomcat 从 webapps 文件夹中读取它。要编译和呈现 JSP,您的 pom.xml 需要 spring-boot-starter-webtomcat-embed-jasper,包括标签 <scope>provided</scope>.

问题 2 Spring 带有一个 嵌入式 Tomcat 服务器 (spring-boot -starter-web)。当您 运行 mvn spring-boot:run 时,它将启动 Tomcat 服务器并在 Tomcat localhost:8080 上部署您的 Spring 启动应用程序。 mvn clean,在 spring-boot:run 之前,只是通过删除构建目录来删除构建的输出。

问题3每个.HTML模板或.JSP文件在编译前在项目中都有各自的位置,因此有些.JSP 未编译到您的文件夹中。

A Java 企业应用程序及其对应的 JSP 使用与 Spring 不同的项目结构:所有 JSP 将从“src/main/webapp/WEB-INF/jsp/" 如果你有正确的依赖和 运行 spring-boot:run。如果您手动创建一个项目,通过 cmd -jar 编译,您应该将您的 JSP 包含在“/webapp/”文件夹和 Java.classes 在 WEB-INF/classes/MyServlet.class.

通过使用,例如 Thymeleaf (spring-boot-starter-thymeleaf),如果您构建您的工件,IDE 将从 /resources/templates 编译模板并从那里开始工作您的 MVC 项目,您可以在其中无缝集成您的 REST 控制器。

Tomcat 在您的企业应用程序的部署方式中保持关键,只是您需要在 Spring 中调整您的项目,以便它将正确的文件映射并编译到 .WAR 在部署之前。

我的建议是,对于 MVC,使用模板引擎而不是遗留的 JSP。当然,在 Spring 项目中会有 JSP 的用例,但它需要不同的结构和依赖关系。