ZetCode

Spring Web 应用程序入门

最后修改于 2020 年 7 月 13 日

在本教程中,我们将使用 Spring 创建简单的 Web 应用程序。将创建三个 Web 应用程序;每个应用程序都以不同的方式进行配置。

在我们的 Spring Web 应用程序中,我们使用 Spring 5 和 Thymeleaf 3。

Spring 是一个流行的 Java 应用程序框架。Spring Boot 旨在以最小的努力创建独立的、生产级的基于 Spring 的应用程序。

配置 Spring Web 应用程序有三种基本方法

传统上,Spring 使用 XML 文件来配置应用程序。之后,创建了一种新方法,在该方法中,配置是在 Java 配置类中完成的。Spring Boot 自动配置魔法是配置 Spring Web 应用程序的最新方法。

使用 XML 配置 Spring Web 应用程序

在第一个示例中,我们创建一个用 XML 文件配置的 Spring Web 应用程序。

pom.mxl
src
├───main
│   ├───java
│   │   └───com
│   │       └───zetcode
│   │           └───controller
│   │                   HomeController.java
│   ├───resources
│   └───webapp
│       │   index.html
│       └───WEB-INF
│           │   spring-servlet.xml
│           │   web.xml
│           └───templates
│                   showMessage.html
└───test
    └───java

这是项目结构。

pom.xml
<?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>com.zetcode</groupId>
    <artifactId>springwebfirst</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.25</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>        

        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.11.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
            <version>3.0.11.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.3.RELEASE</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.2</version>
            </plugin>

        </plugins>
    </build>

</project>

这是 Maven 构建文件。我们有以下依赖项:`slf4j-api` 和 `slf4j-simple` 用于日志记录,`javax.servlet-api` 用于 Java Servlet 技术,`thymeleaf-spring5` 和 `thymeleaf` 用于 Thymeleaf 模板引擎,以及 `spring-webmvc` 用于创建 Spring Web MVC 应用程序。

`maven-war-plugin` 创建 Web 归档文件 (WAR)。

WEB-INF/spring-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd 
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="com.zetcode"/>
    <mvc:annotation-driven/>
    <mvc:default-servlet-handler/>

    <bean id="templateResolver" 
            class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
        <property name="prefix" value="/WEB-INF/templates/"/>
        <property name="suffix" value=".html"/>
        <property name="templateMode" value="HTML"/>
    </bean>

    <bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="templateEngine" ref="templateEngine"/>
    </bean>

    <bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
        <property name="templateResolver" ref="templateResolver"/>
    </bean>

</beans>

`spring-servlet.xml` 配置 Spring Web 应用程序。它启用组件扫描、Spring Web 注解 (@Controller) 并配置 Thymeleaf 模板。

<context:component-scan base-package="com.zetcode" />

这告诉 Spring 在哪里查找带有 `@Controller`、`@Repository`、`@Service`、`@Component` 注解的类并注册它们。在我们的例子中,我们有一个带有 `@Controller` 注解的控制器。

<mvc:annotation-driven/>

`<mvc:annotation-driven/>` 启用基于 Web 的 Spring 注解。

<mvc:default-servlet-handler/>

我们需要此标签来启用静态 HTML 文件。我们有一个静态 `index.html` 作为主页。

<bean id="templateResolver" 
        class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
    <property name="prefix" value="/WEB-INF/templates/"/>
    <property name="suffix" value=".html"/>
    <property name="templateMode" value="HTML"/>
</bean>

<bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
    <property name="templateEngine" ref="templateEngine"/>
</bean>

<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
    <property name="templateResolver" ref="templateResolver"/>
</bean>

这些行使用模板引擎、模板视图解析器和模板解析器配置 Thymeleaf。在模板解析器中,我们指定模板的位置及其扩展名。

WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
            http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
            version="4.0">
    
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>      
    
    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>    
    
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</web-app>

在 `web.xml` 文件中,我们设置了 Spring `DispatcherServlet` 并选择了欢迎文件。`DispatcherServlet` 是 Spring 的前端控制器。该 Servlet 映射到扩展名为 `*.html` 的 URL。

com/zetcode/controller/HomeController.java
package com.zetcode.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {

    @GetMapping("/message")
    public String message() {

        return "showMessage";
    }
}

HTTP 请求由控制器处理。它准备一个模型并返回一个视图。返回的 `showMessage` 字符串映射到位于 `WEB-INF/templates/` 目录中的 `showMessage.html` 文件。

WEB-INF/templates/showMessage.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Message</title>
</head>
<body>

<p>
    Hello there
</p>

</body>
</html>

`showMessage.html` 文件显示一条消息。

index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Home page</title>
</head>
<body>
<p>
    <a href="message">Show message</a>
</p>
</body>
</html>

`index.html` 是主页。它包含一个链接。

使用 Java 配置配置 Spring Web 应用程序

在第二个示例中,我们创建了一个使用 Java 配置类配置的 Spring Web 应用程序。在此示例中,`web.xml` 和 `spring-servlet.xml` 被 `MyWebInitializer.java` 和 `WebConfig.java` 替换。

pom.xml
src
├───main
│   ├───java
│   │   └───com
│   │       └───zetcode
│   │           ├───config
│   │           │       MyWebInitializer.java
│   │           │       WebConfig.java
│   │           └───controller
│   │                   MyController.java
│   ├───resources
│   └───webapp
│       └───WEB-INF
│           └───templates
│                   index.html
│                   showMessage.html
└───test
    └───java

这是项目结构。`pom.xml` 文件与第一个示例相同。

com/zetcode/config/WebConfig.java
package com.zetcode.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.zetcode"})
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public SpringResourceTemplateResolver templateResolver() {

        var templateResolver = new SpringResourceTemplateResolver();

        templateResolver.setApplicationContext(applicationContext);
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");

        return templateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine() {

        var templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        templateEngine.setEnableSpringELCompiler(true);

        return templateEngine;
    }

    @Bean
    public ViewResolver viewResolver() {

        var resolver = new ThymeleafViewResolver();
        var registry = new ViewResolverRegistry(null, applicationContext);

        resolver.setTemplateEngine(templateEngine());
        registry.viewResolver(resolver);

        return resolver;
    }
}

`WebConfig.java` 文件用于替代 `spring-servlet.xml` 文件。在 `WebConfig` 中,我们使用 `@EnableWebMvc` 启用 Spring Web 注解,使用 `@ComponentScan` 启用组件扫描,并配置 Thymeleaf 模板引擎。

com/zetcode/config/MyWebInitializer.java
package com.zetcode.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class MyWebInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

`MyWebInitializer` 类用于替代 `web.xml` 文件。我们指定了 Servlet 配置类的名称。

com/zetcode/controller/MyController.java
package com.zetcode.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MyController {

    @GetMapping("/")
    public String index() {
        return "index";
    }

    @GetMapping("/message")
    public String message() {
        return "showMessage";
    }
}

这是控制器。我们有主页和 showMessage 页面的映射。

WEB-INF/templates/showMessage.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Message</title>
</head>
<body>
<p>Today is a sunny day!</p>
</body>
</html>

`showMessage.html` 文件显示一条消息。

WEB-INF/templates/index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Home page</title>
</head>
<body>
<p>
    <a href="message.html">Show message</a>
</p>
</body>
</html>

`index.html` 是主页。它包含一个链接。

Spring Boot Web 应用程序

在第三个示例中,我们使用 Spring Boot 创建了一个 Web 应用程序。Spring Boot 使用不同的默认方法。它使用带有嵌入式 Web 服务器的 JAR 归档文件。

pom.xml
src
├───main
│   ├───java
│   │   └───com
│   │       └───zetcode
│   │           │   Application.java
│   │           └───controller
│   │                   MyController.java
│   └───resources
│       │   application.properties
│       ├───static
│       │       index.html
│       └───templates
│               showMessage.html
└───test
    └───java

这是项目结构。

pom.xml
<?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>com.zetcode</groupId>
    <artifactId>springbootwebfirst</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

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

    <dependencies>

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

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

    </dependencies>

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

</project>

这是 Maven 构建文件。`spring-boot-starter-web` 是用于使用 Spring MVC 构建 Web(包括 RESTful)应用程序的启动 POM。`spring-boot-starter-thymeleaf` 是 Thymeleaf 模板引擎的启动 POM。

请注意,打包设置为 JAR。

com/zetcode/controller/MyController.java
package com.zetcode.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MyController {

    @GetMapping("/message")
    public String message() {

        return "showMessage";
    }
}

这是 Spring Boot Web 应用程序的控制器类。控制器用 `@Controller` 注解修饰。控制器有一个映射。该映射解析到 `showMessage.html` 模板,该模板位于 `WEB-INF/templates` 目录中。

com/zetcode/Application.java
package com.zetcode;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

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

`Application` 设置了 Spring Boot 应用程序。

WEB-INF/templates/showMessage.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Message</title>
</head>
<body>
<p>Today is a cold day</p>
</body>
</html>

`showMessage.html` 显示一条简单的消息。

WEB-INF/static/index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Home page</title>
</head>
<body>
<p>
    <a href="message">Show message</a>
</p>
</body>
</html>

`index.html` 是应用程序的主页,包含一个链接。静态资源,如纯 HTML 文件,放在 `static` 目录中。

在本教程中,我们创建了我们的第一个 Spring Web 应用程序。