Mkyong 中文博客翻译(五十)

原文:Mkyong

协议:CC BY-NC-SA 4.0

Spring Boot @配置属性示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-configurationproperties-example/

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Spring Boot @ConfigurationProperties让开发者可以轻松地将整个.propertiesyml文件映射成一个对象。

PS 用 Spring Boot 2.1.2.RELEASE 测试

1.@值

1.1 通常情况下,我们使用@Value来逐个注入.properties的值,这对于小且结构简单的.properties文件很好。举个例子,

global.properties

 email=test@mkyong.com
thread-pool=12 

GlobalProperties.java

 @Component
@PropertySource("classpath:global.properties")
public class GlobalProperties {
    
    

    @Value("${thread-pool}")
    private int threadPool;

    @Value("${email}")
    private String email;

    //getters and setters

} 

1.2@ConfigurationProperties中的等价物

GlobalProperties.java

 import org.springframework.boot.context.properties.ConfigurationProperties;

@Component
@PropertySource("classpath:global.properties")
@ConfigurationProperties
public class GlobalProperties {
    
    

    private int threadPool;
    private String email;

    //getters and setters

} 

2.@配置属性

2.1 查看下面的复杂结构.propertiesyml文件,我们如何通过@Value映射值?

application.properties

 #Logging
logging.level.org.springframework.web=ERROR
logging.level.com.mkyong=DEBUG

#Global
email=test@mkyong.com
thread-pool=10

#App
app.menus[0].title=Home
app.menus[0].name=Home
app.menus[0].path=/
app.menus[1].title=Login
app.menus[1].name=Login
app.menus[1].path=/login

app.compiler.timeout=5
app.compiler.output-folder=/temp/

app.error=/error/ 

或 YAML 的同等机构。

application.yml

 logging:
  level:
    org.springframework.web: ERROR
    com.mkyong: DEBUG
email: test@mkyong.com
thread-pool: 10
app:
  menus:
    - title: Home
      name: Home
      path: /
    - title: Login
      name: Login
      path: /login
  compiler:
    timeout: 5
    output-folder: /temp/
  error: /error/ 

Note
@ConfigurationProperties supports both .properties and .yml file.

2.2 @ConfigurationProperties前来救援:

AppProperties.java

 package com.mkyong;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
@ConfigurationProperties("app") // prefix app, find app.* values
public class AppProperties {
    
    

    private String error;
    private List<Menu> menus = new ArrayList<>();
    private Compiler compiler = new Compiler();

    public static class Menu {
    
    
        private String name;
        private String path;
        private String title;

        //getters and setters

        @Override
        public String toString() {
    
    
            return "Menu{" +
                    "name='" + name + '\'' +
                    ", path='" + path + '\'' +
                    ", title='" + title + '\'' +
                    '}';
        }
    }

    public static class Compiler {
    
    
        private String timeout;
        private String outputFolder;

        //getters and setters

        @Override
        public String toString() {
    
    
            return "Compiler{" +
                    "timeout='" + timeout + '\'' +
                    ", outputFolder='" + outputFolder + '\'' +
                    '}';
        }

    }

    //getters and setters
} 

GlobalProperties.java

 package com.mkyong;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties // no prefix, find root level values.
public class GlobalProperties {
    
    

    private int threadPool;
    private String email;

	//getters and setters
} 

3.@配置属性验证

这个@ConfigurationProperties支持 JSR-303 bean 验证。

3.1 在@ConfigurationProperties类上添加@Validated,在我们想要验证的字段上添加javax.validation注释。

GlobalProperties.java

 package com.mkyong;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;

@Component
@ConfigurationProperties
@Validated
public class GlobalProperties {
    
    

    @Max(5)
    @Min(0)
    private int threadPool;

    @NotEmpty
    private String email;

    //getters and setters
} 

3.2 设置线程池=10

application.properties

 #Global
email=test@mkyong.com
thread-pool=10 

3.3 启动 Spring Boot,我们将点击以下错误信息:

Console

 ***************************
APPLICATION FAILED TO START
***************************

Description:

Binding to target org.springframework.boot.context.properties.bind.BindException: 
	Failed to bind properties under '' to com.mkyong.GlobalProperties failed:

    Property: .threadPool
    Value: 10
    Origin: class path resource [application.properties]:7:13
    Reason: must be less than or equal to 5

Action:

Update your application's configuration 

4.演示

 $ git clone https://github.com/mkyong/spring-boot.git
$ cd externalize-config-properties-yaml
$ mvn spring-boot:run

access localhost:8080 

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传Note
For more detail, please refer to this official Spring Boot Externalized Configuration

下载源代码

$ git clone https://github.com/mkyong/spring-boot.git
$ cd externalize-config-properties-yaml
$ mvn spring-boot:run

访问本地主机:8080

参考

Spring Boot–在嵌入式 Tomcat 中配置 maxSwallowSize

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-configure-maxswallowsize-in-embedded-tomcat/

在 Spring Boot,你不能通过通用应用属性配置嵌入式 Tomcat maxSwallowSize,没有像server.tomcat.*.maxSwallowSize这样的选项

解决办法

要修复它,您需要声明一个TomcatEmbeddedServletContainerFactory bean,并像这样配置maxSwallowSize:

 //...
import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;

    private int maxUploadSizeInMb = 10 * 1024 * 1024; // 10 MB

    @Bean
    public TomcatEmbeddedServletContainerFactory tomcatEmbedded() {
    
    

        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();

        tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
    
    

            // connector other settings...

            // configure maxSwallowSize
            if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>)) {
    
    
                // -1 means unlimited, accept bytes
                ((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
            }

        });

        return tomcat;

    } 

参考

  1. Spring 文件上传和连接重置问题
  2. 常用应用属性
  3. Spring Boot 文件上传错误处理(Japanase)

connection reset file upload spring boot tomcat外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 (function (i,d,s,o,m,r,c,l,w,q,y,h,g) { var e=d.getElementById®;if(e=null){ var t = d.createElement(o); t.src = g; t.id = r; t.setAttribute(m, s);t.async = 1;var n=d.getElementsByTagName(o)[0];n.parentNode.insertBefore(t, n); var dt=new Date().getTime(); try{i[l]w+y;}catch(er){i[h]=dt;} } else if(typeof i[c]!‘undefined’){i[c]++} else{i[c]=1;} })(window, document, ‘InContent’, ‘script’, ‘mediaType’, ‘carambola_proxy’,‘Cbola_IC’,‘localStorage’,‘set’,‘get’,‘Item’,‘cbolaDt’,‘//web.archive.org/web/20190309055300/http://route.carambo.la/inimage/getlayer?pid=myky82&did=112239&wid=0’)

Spring Boot–自定义横幅示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-custom-banner-example/

这篇文章向你展示了如何用你的自定义横幅替换下面默认的 Spring 横幅。

 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.1.RELEASE) 

解决办法

1.要在 Spring Boot 应用程序中添加自定义横幅,请创建一个banner.txt文件,并将其放入resources文件夹。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.回顾一下banner.txt的内容,这个 ASCII Art 是由这个 ASCII Art Java 示例创建的,ANSI 颜色是手动添加的。

src/main/resources/banner.txt

 ${
    
    Ansi.RED}                  $$$        $$$$$      $$$$         $$$$     $$$$$
${
    
    Ansi.GREEN}                  $$$       $$$$$$$     $$$$         $$$$    $$$$$$$
${
    
    Ansi.BLUE}                  $$$       $$$$$$$     $$$$$       $$$$$    $$$$$$$
${
    
    Ansi.RED}                  $$$       $$$$$$$      $$$$       $$$$     $$$$$$$
${
    
    Ansi.GREEN}                  $$$      $$$$ $$$$     $$$$$     $$$$$    $$$$ $$$$
${
    
    Ansi.BLUE}                  $$$      $$$$ $$$$      $$$$     $$$$     $$$$ $$$$
${
    
    Ansi.RED}                  $$$     $$$$$ $$$$$     $$$$     $$$$    $$$$$ $$$$$
${
    
    Ansi.GREEN}                  $$$     $$$$   $$$$     $$$$$   $$$$$    $$$$   $$$$
${
    
    Ansi.BLUE}                  $$$     $$$$   $$$$      $$$$   $$$$     $$$$   $$$$
${
    
    Ansi.RED}                  $$$    $$$$$   $$$$$     $$$$$ $$$$$    $$$$$   $$$$$
${
    
    Ansi.GREEN}                  $$$    $$$$$$$$$$$$$      $$$$ $$$$     $$$$$$$$$$$$$
${
    
    Ansi.BLUE}          $$$$   $$$$    $$$$$$$$$$$$$      $$$$ $$$$     $$$$$$$$$$$$$
${
    
    Ansi.RED}          $$$$   $$$$   $$$$$$$$$$$$$$$      $$$$$$$     $$$$$$$$$$$$$$$
${
    
    Ansi.GREEN}          $$$$$ $$$$$   $$$$       $$$$      $$$$$$$     $$$$       $$$$
${
    
    Ansi.BLUE}          $$$$$$$$$$$  $$$$$       $$$$$     $$$$$$$    $$$$$       $$$$$
${
    
    Ansi.RED}           $$$$$$$$$   $$$$         $$$$      $$$$$     $$$$         $$$$
${
    
    Ansi.GREEN}            $$$$$$$    $$$$         $$$$      $$$$$     $$$$         $$$$

${
    
    Ansi.RED} :: Spring Boot${
    
    spring-boot.formatted-version} :: ${
    
    Ansi.DEFAULT} 

3.启动 Spring Boot,将显示以下输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

参考

  1. Spring Boot——定制横幅
  2. ASCII Art Java 示例

Spring Boot-将 WAR 文件部署到 Tomcat

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-deploy-war-file-to-tomcat/

在本文中,我们将向您展示如何将 Spring Boot 战争文件部署到 Tomcat servlet 容器中。

对于 Spring Boot 战争的部署,你需要做三个步骤:

  1. 扩展 SpringBootServletInitializer
  2. 将嵌入式 servlet 容器标记为已提供。
  3. 将包装更新到 war

已测试

  1. Spring Boot 1.4.2 版本
  2. Tomcat 8.5.9
  3. maven3

Note
In Spring Boot, the final executable JAR file with embedded server solution may not suitable in all production environments, especially the deployment team (a team with good knowledge of server optimization and monitoring skills, but lack of, the development experience), they want full control of the server, and they don’t touch code.

1.扩展 SpringBootServletInitializer

使现有的@SpringBootApplication类扩展SpringBootServletInitializer

1.1 经典的 Spring Boot JAR 部署。(更新此文件以支持 WAR 部署)

SpringBootWebApplication.java

 import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootWebApplication {
    
    

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

} 

1.2 Spring Boot 战争部署。

SpringBootWebApplication.java

 import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;

@SpringBootApplication
public class SpringBootWebApplication extends SpringBootServletInitializer {
    
    

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    
    
        return application.sources(SpringBootWebApplication.class);
    }

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

}

/*@SpringBootApplication
public class SpringBootWebApplication {

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

}*/ 

如果您为部署创建一个额外的SpringBootWebApplication类,一定要告诉 Spring Boot 要启动哪个主类:

pom.xml

 <properties>
        <start-class>com.mkyong.NewSpringBootWebApplicationForWAR</start-class>
  </properties> 

读读这个——Spring Boot——从哪个主班开始

2.将嵌入式 servlet 容器标记为已提供

pom.xml

 <dependencies>

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

	<!-- marked the embedded servlet container as provided -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-tomcat</artifactId>
		<scope>provided</scope>
	</dependency>

</dependencies> 

3.将包装更新到 war

pom.xml

 <packaging>war</packaging> 

完成后,mvn package并将$project/target/xxx.war复制到 Tomcat 进行部署。

4.完整示例——Spring Boot 战争+ Tomcat 部署

4.1 以这个 Spring Boot 百里香为例,手动更新并部署到 Tomcat。

4.2 更新现有的SpringBootWebApplication并使其扩展SpringBootServletInitializer

pom.xml

 package com.mkyong;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;

@SpringBootApplication
public class SpringBootWebApplication extends SpringBootServletInitializer {
    
    

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    
    
        return application.sources(SpringBootWebApplication.class);
    }

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

} 

4.3 将包装更新为war,并按规定标记spring-boot-starter-tomcat

pom.xml

 <?xml version="1.0" encoding="UTF-8"?>
<project  
	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>

    <artifactId>spring-boot-web-thymeleaf</artifactId>
    <packaging>war</packaging>
    <name>Spring Boot Web Thymeleaf Example</name>
    <description>Spring Boot Web Thymeleaf Example</description>
    <url>https://www.mkyong.com</url>
    <version>1.0</version>

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

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

    <dependencies>

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

        <!-- marked the embedded servlet container as provided -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>

        <!-- hot swapping, disable cache for template, enable live reload -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- Optional, for bootstrap -->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>3.3.7</version>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <!-- Package as an executable jar/war -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project> 

4.4 这是可选的,稍后更新contextPath/mkyong进行演示。完成了。准备战争部署。

application.properties

 welcome.message: Hello Mkyong

server.contextPath=/mkyong 

4.5 获取 Tomcat 并部署 WAR 文件。

Mac OS X : Terminal

 # Get Tomcat 8.5.9
spring-boot-project$ curl -O  http://www-us.apache.org/dist/tomcat/tomcat-8/v8.5.9/bin/apache-tomcat-8.5.9.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 9112k  100 9112k    0     0   799k      0  0:00:11  0:00:11 --:--:-- 1348k

# Extract it
$ tar -xvzf apache-tomcat-8.5.9.tar.gz 

# Maven clean and package everything into a WAR file.
$ mvn clean package

# Copy WAR to Tomcat/webapp, renamed to mkyong.war
# By default, Tomcat take the war file name as the context path
$ cp target/spring-boot-web-thymeleaf-1.0.war apache-tomcat-8.5.9/webapps/mkyong.war

# Start Tomcat
$ ./apache-tomcat-8.5.9/bin/startup.sh 
Using CATALINA_BASE:   /Users/mkyong/projects/spring-boot-web-thymeleaf/apache-tomcat-8.5.9
Using CATALINA_HOME:   /Users/mkyong/projects/spring-boot-web-thymeleaf/apache-tomcat-8.5.9
Using CATALINA_TMPDIR: /Users/mkyong/projects/spring-boot-web-thymeleaf/apache-tomcat-8.5.9/temp
Using JRE_HOME:        /Library/Java/JavaVirtualMachines/jdk1.8.0_74.jdk/Contents/Home
Using CLASSPATH:       /Users/mkyong/projects/spring-boot-web-thymeleaf/apache-tomcat-8.5.9/bin/bootstrap.jar:
/Users/mkyong/projects/spring-boot-web-thymeleaf/apache-tomcat-8.5.9/bin/tomcat-juli.jar
Tomcat started. 

4.6 访问http://localhost:8080/mkyong/

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.7 搞定。关闭 Tomcat。

Mac OS X : Terminal

 $ ./apache-tomcat-8.5.9/bin/shutdown.sh 

下载源代码

Download – spring-boot-war-tomcat.zip (13 KB)

参考

  1. Spring Boot–传统部署
  2. Spring Boot Hello World 示例–百里香叶
  3. 如何在 Debian 上安装 Apache Tomcat 8

deployment spring boot tomcat war

Spring Boot 文件上传示例–Ajax 和 REST

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-file-upload-example-ajax-and-rest/

这篇文章展示了如何使用 Ajax 请求在 Spring Boot web 应用程序(REST 结构)中上传文件。

本文中使用的工具:

  1. Spring Boot 1.4.3 版本
  2. 弹簧 4.3.5 .释放
  3. 百里香叶
  4. jQuery (webjars)
  5. 专家
  6. 嵌入式 Tomcat 8.5.6
  7. 谷歌 Chrome 浏览器(网络检查)

1.项目结构

一个标准的 Maven 项目结构。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 ## 2.项目依赖性

为 HTML 格式的 Ajax 请求声明一个额外的jQuery webjar 依赖项。

pom.xml

 <project 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mkyong</groupId>
    <artifactId>spring-boot-file-upload</artifactId>
    <packaging>jar</packaging>
    <version>1.0</version>

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

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

    <dependencies>

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

        <!-- hot swapping, disable cache for template, enable live reload -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>2.2.4</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <!-- Package as an executable jar/war -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project> 

3.文件上传

为了支持 Ajax 请求和响应,最简单的解决方案是返回一个ResponseEntity

3.1 以下示例演示了上传文件的三种可能方式:

  1. 单个文件上传-MultipartFile
  2. 多文件上传-MultipartFile[]
  3. 将地图文件上传到模型–@ModelAttribute

RestUploadController.java

 package com.mkyong.controller;

import com.mkyong.model.UploadModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@RestController
public class RestUploadController {
    
    

    private final Logger logger = LoggerFactory.getLogger(RestUploadController.class);

    //Save the uploaded file to this folder
    private static String UPLOADED_FOLDER = "F://temp//";

    // 3.1.1 Single file upload
    @PostMapping("/api/upload")
    // If not @RestController, uncomment this
    //@ResponseBody
    public ResponseEntity<?> uploadFile(
            @RequestParam("file") MultipartFile uploadfile) {
    
    

        logger.debug("Single file upload!");

        if (uploadfile.isEmpty()) {
    
    
            return new ResponseEntity("please select a file!", HttpStatus.OK);
        }

        try {
    
    

            saveUploadedFiles(Arrays.asList(uploadfile));

        } catch (IOException e) {
    
    
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }

        return new ResponseEntity("Successfully uploaded - " +
                uploadfile.getOriginalFilename(), new HttpHeaders(), HttpStatus.OK);

    }

    // 3.1.2 Multiple file upload
    @PostMapping("/api/upload/multi")
    public ResponseEntity<?> uploadFileMulti(
            @RequestParam("extraField") String extraField,
            @RequestParam("files") MultipartFile[] uploadfiles) {
    
    

        logger.debug("Multiple file upload!");

        // Get file name
        String uploadedFileName = Arrays.stream(uploadfiles).map(x -> x.getOriginalFilename())
                .filter(x -> !StringUtils.isEmpty(x)).collect(Collectors.joining(" , "));

        if (StringUtils.isEmpty(uploadedFileName)) {
    
    
            return new ResponseEntity("please select a file!", HttpStatus.OK);
        }

        try {
    
    

            saveUploadedFiles(Arrays.asList(uploadfiles));

        } catch (IOException e) {
    
    
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }

        return new ResponseEntity("Successfully uploaded - "
                + uploadedFileName, HttpStatus.OK);

    }

    // 3.1.3 maps html form to a Model
    @PostMapping("/api/upload/multi/model")
    public ResponseEntity<?> multiUploadFileModel(@ModelAttribute UploadModel model) {
    
    

        logger.debug("Multiple file upload! With UploadModel");

        try {
    
    

            saveUploadedFiles(Arrays.asList(model.getFiles()));

        } catch (IOException e) {
    
    
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }

        return new ResponseEntity("Successfully uploaded!", HttpStatus.OK);

    }

    //save file
    private void saveUploadedFiles(List<MultipartFile> files) throws IOException {
    
    

        for (MultipartFile file : files) {
    
    

            if (file.isEmpty()) {
    
    
                continue; //next pls
            }

            byte[] bytes = file.getBytes();
            Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
            Files.write(path, bytes);

        }

    }
} 

3.2 上述示例 3.1.3 的简单模型—@ModelAttribute

UploadModel.java

 package com.mkyong.model;

import org.springframework.web.multipart.MultipartFile;

public class UploadModel {
    
    

    private String extraField;

    private MultipartFile[] files;

    //getters and setters
} 

4.风景

用于多文件上传的 HTML 表单。

upload.html

 <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>

<h1>Spring Boot - Multiple file upload example - AJAX</h1>

<form method="POST" enctype="multipart/form-data" id="fileUploadForm">
    <input type="text" name="extraField"/><br/><br/>
    <input type="file" name="files"/><br/><br/>
    <input type="file" name="files"/><br/><br/>
    <input type="submit" value="Submit" id="btnSubmit"/>
</form>

<h1>Ajax Post Result</h1>
<pre>
    <span id="result"></span>
</pre>

<script type="text/javascript"
        src="webjars/jquery/2.2.4/jquery.min.js"></script>

<script type="text/javascript" src="js/main.js"></script>

</body>
</html> 

5.jQuery–Ajax 请求

jQuery 通过表单#id获取表单,并通过 Ajax 请求发送多部分表单数据。

resources/static/js/main.js

 $(document).ready(function () {
    
    

    $("#btnSubmit").click(function (event) {
    
    

        //stop submit the form, we will post it manually.
        event.preventDefault();

        fire_ajax_submit();

    });

});

function fire_ajax_submit() {
    
    

    // Get form
    var form = $('#fileUploadForm')[0];

    var data = new FormData(form);

    data.append("CustomField", "This is some extra data, testing");

    $("#btnSubmit").prop("disabled", true);

    $.ajax({
    
    
        type: "POST",
        enctype: 'multipart/form-data',
        url: "/api/upload/multi",
        data: data,
        //http://api.jquery.com/jQuery.ajax/
        //https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects
        processData: false, //prevent jQuery from automatically transforming the data into a query string
        contentType: false,
        cache: false,
        timeout: 600000,
        success: function (data) {
    
    

            $("#result").text(data);
            console.log("SUCCESS : ", data);
            $("#btnSubmit").prop("disabled", false);

        },
        error: function (e) {
    
    

            $("#result").text(e.responseText);
            console.log("ERROR : ", e);
            $("#btnSubmit").prop("disabled", false);

        }
    });

} 

6.异常处理程序

为了处理来自 Ajax 请求的异常,只需扩展ResponseEntityExceptionHandler并返回一个ResponseEntity

RestGlobalExceptionHandler.java

 package com.mkyong.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.servlet.http.HttpServletRequest;

//http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling
@ControllerAdvice
public class RestGlobalExceptionHandler extends ResponseEntityExceptionHandler {
    
    

    // Catch file size exceeded exception!
    @ExceptionHandler(MultipartException.class)
    @ResponseBody
    ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
    
    

        HttpStatus status = getStatus(request);
        return new ResponseEntity(ex.getMessage(), status);

        // example
        //return new ResponseEntity("success", responseHeaders, HttpStatus.OK);

    }

    private HttpStatus getStatus(HttpServletRequest request) {
    
    
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
    
    
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }

} 

7.演示

用默认的嵌入式 Tomcat mvn spring-boot:run启动 Spring Boot。

7.1 访问 http://localhost:8080/ ,选择几个文件,点击提交,启动 ajax 请求。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.2 Google Chrome,在“网络检查”中查看请求和响应

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.3 谷歌浏览器,“请求有效载荷”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

8.卷曲测试

使用cURL命令进行更多测试。

8.1 测试单个文件上传。

Terminal

 $ curl -F file=@"f:\\data.txt" http://localhost:8080/api/upload/
Successfully uploaded - data.txt 

8.2 测试多文件上传。

Terminal

 $ curl -F extraField="abc" -F files=@"f://data.txt" -F files=@"f://data2.txt"  http://localhost:8080/api/upload/multi/
Successfully uploaded - data.txt , data2.txt 

8.3 测试多个文件上传,映射到模型。

Terminal

 $ curl -F extraField="abc" -F files=@"f://data.txt" -F files=@"f://data2.txt"  http://localhost:8080/api/upload/multi/model
Successfully uploaded! 

8.4 测试一个大的电影文件(100MB),会显示以下错误信息。

Terminal

 $ curl -F file=@"F://movies//300//Sample.mkv"  http://localhost:8080/api/upload/
Attachment size exceeds the allowable limit! (10MB) 

9.cURL 测试+自定义错误对象

9.1 创建一个对象来存储错误详细信息。

CustomError.java

 package com.mkyong.exception;

public class CustomError {
    
    

    String errCode;
    String errDesc;

    public CustomError(String errCode, String errDesc) {
    
    
        this.errCode = errCode;
        this.errDesc = errDesc;
    }

    //getters and setters
} 

9.2 更新全局异常处理程序以支持CustomError对象。

RestGlobalExceptionHandler.java

 package com.mkyong.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.servlet.http.HttpServletRequest;

@ControllerAdvice
public class RestGlobalExceptionHandler extends ResponseEntityExceptionHandler {
    
    

    @ExceptionHandler(MultipartException.class)
    @ResponseBody
    ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
    
    

        HttpStatus status = getStatus(request);

        return new ResponseEntity(new CustomError("0x000123", 
                "Attachment size exceeds the allowable limit! (10MB)"), status);

        //return new ResponseEntity("Attachment size exceeds the allowable limit! (10MB)", status);

    }

    private HttpStatus getStatus(HttpServletRequest request) {
    
    
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
    
    
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }

} 

9.3 cURL 再次上传大文件。

Terminal

 $ curl -F file=@"F://movies//300//Sample.mkv"  http://localhost:8080/api/upload/

{
    
    "errCode":"0x000123","errDesc":"Attachment size exceeds the allowable limit! (10MB)"} 

完成了。欢迎反馈。

10.下载源代码

Download – spring-boot-file-upload-ajax-rest.zip (11 KB)

参考

  1. Spring Boot–错误处理
  2. Spring Boot 文件上传示例
  3. Spring MVC 文件上传示例
  4. Spring Boot Hello World 示例–百里香叶
  5. 维基百科–卷曲
  6. jQuery.ajax()
  7. MDN–使用表单数据对象

ajax curl file upload jquery multipart rest spring boot

Spring Boot 文件上传示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-file-upload-example/

这篇文章向你展示了如何在 Spring Boot 网络应用程序中上传文件。

使用的工具:

  1. Spring Boot 1.4.3 版本
  2. 弹簧 4.3.5 .释放
  3. 百里香叶
  4. 专家
  5. 嵌入式 Tomcat 8.5.6

1.项目结构

标准项目结构。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.项目依赖性

春季启动依赖,不需要额外的文件上传库。

pom.xml

 <project 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/maven-v4_0_0.xsd">
         <modelVersion>4.0.0</modelVersion>

    <groupId>com.mkyong</groupId>
    <artifactId>spring-boot-file-upload</artifactId>
    <packaging>jar</packaging>
    <version>1.0</version>

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

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

    <dependencies>

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

        <!-- hot swapping, disable cache for template, enable live reload -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <!-- Package as an executable jar/war -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project> 

3.文件上传示例

春季开机文件上传,零配置。

3.1 在控制器中,将上传的文件映射到MultipartFile

UploadController.java

 package com.mkyong.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@Controller
public class UploadController {
    
    

    //Save the uploaded file to this folder
    private static String UPLOADED_FOLDER = "F://temp//";

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

    @PostMapping("/upload") // //new annotation since 4.3
    public String singleFileUpload(@RequestParam("file") MultipartFile file,
                                   RedirectAttributes redirectAttributes) {
    
    

        if (file.isEmpty()) {
    
    
            redirectAttributes.addFlashAttribute("message", "Please select a file to upload");
            return "redirect:uploadStatus";
        }

        try {
    
    

            // Get the file and save it somewhere
            byte[] bytes = file.getBytes();
            Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
            Files.write(path, bytes);

            redirectAttributes.addFlashAttribute("message",
                    "You successfully uploaded '" + file.getOriginalFilename() + "'");

        } catch (IOException e) {
    
    
            e.printStackTrace();
        }

        return "redirect:/uploadStatus";
    }

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

} 

3.2 在百里香里,只是一些普通的 HTML 文件标签。

upload.jsp

 <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>

<h1>Spring Boot file upload example</h1>

<form method="POST" action="/upload" enctype="multipart/form-data">
    <input type="file" name="file" /><br/><br/>
    <input type="submit" value="Submit" />
</form>

</body>
</html> 

3.3 上传状态的另一个页面

uploadStatus.jsp

 <!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>

<h1>Spring Boot - Upload Status</h1>

<div th:if="${message}">
    <h2 th:text="${message}"/>
</div>

</body>
</html> 

4.超过最大上传大小

为了处理超过最大上传大小的异常,声明一个@ControllerAdvice并捕捉MultipartException

GlobalExceptionHandler.java

 package com.mkyong.controller;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@ControllerAdvice
public class GlobalExceptionHandler {
    
    

    //https://jira.spring.io/browse/SPR-14651
    //Spring 4.3.5 supports RedirectAttributes
    @ExceptionHandler(MultipartException.class)
    public String handleError1(MultipartException e, RedirectAttributes redirectAttributes) {
    
    

        redirectAttributes.addFlashAttribute("message", e.getCause().getMessage());
        return "redirect:/uploadStatus";

    }

    /* Spring < 4.3.5
	@ExceptionHandler(MultipartException.class)
    public String handleError2(MultipartException e) {

        return "redirect:/errorPage";

    }*/

} 

5.Tomcat 连接重置

如果你部署到 Tomcat,配置maxSwallowSize来避免这个 Tomcat 连接重置问题。对于嵌入式 Tomcat,声明如下的TomcatEmbeddedServletContainerFactory:

SpringBootWebApplication.java

 package com.mkyong;

import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class SpringBootWebApplication {
    
    

    private int maxUploadSizeInMb = 10 * 1024 * 1024; // 10 MB

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

    //Tomcat large file upload connection reset
    //http://www.mkyong.com/spring/spring-file-upload-and-connection-reset-issue/
    @Bean
    public TomcatEmbeddedServletContainerFactory tomcatEmbedded() {
    
    

        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();

        tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
    
    
            if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>)) {
    
    
                //-1 means unlimited
                ((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
            }
        });

        return tomcat;

    }

} 

6.多部分文件大小

默认情况下,Spring Boot 最大文件上传大小为 1MB,您可以通过以下应用程序属性配置该值:

application.properties

 #http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties
#search multipart
spring.http.multipart.max-file-size=10MB
spring.http.multipart.max-request-size=10MB 

7.演示

用默认的嵌入式 Tomcat mvn spring-boot:run启动 Spring Boot。

Terminal

 $ mvn spring-boot:run
 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.4.3.RELEASE)

2017-01-21 07:48:53 INFO  com.mkyong.SpringBootWebApplication - Starting SpringBootWebApplication on MKYONG-WIN10 with PID 2384 (E:\spring-boot-file-upload\target\classes started by mkyong in E:\spring-boot-file-upload)
2017-01-21 07:48:53 DEBUG com.mkyong.SpringBootWebApplication - Running with Spring Boot v1.4.3.RELEASE, Spring v4.3.5.RELEASE
2017-01-21 07:48:53 INFO  com.mkyong.SpringBootWebApplication - No active profile set, falling back to default profiles: default
2017-01-21 07:48:55 INFO  com.mkyong.SpringBootWebApplication - Started SpringBootWebApplication in 2.54 seconds (JVM running for 2.924) 

7.1 访问 http://localhost:8080/

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.2 选择一个文件并上传。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.3 选择一个大于 10mb 的文件,您将访问此页面。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

8.下载源代码

Download – spring-boot-file-upload-example.zip (7 KB)

参考

  1. Spring Boot 常用应用属性
  2. Spring MVC 文件上传示例
  3. Spring @ExceptionHandler 和 RedirectAttributes
  4. Spring Boot Hello World 示例–百里香叶

Spring Boot Hello World 示例 JSP

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-hello-world-example-jsp/

一个 Spring Boot 的 web 应用例子,使用embedded Tomcat + JSP template,并打包成一个可执行的 WAR 文件。

使用的技术:

  1. Spring Boot 1.4.2 版本
  2. 弹簧 4.3.4 释放
  3. Tomcat Embed 8.5.6
  4. maven3
  5. Java 8

1.项目目录

手动创建以下文件夹:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.项目相关性

Maven 例子。阅读注释,了解更多信息。

pom.xml

 <?xml version="1.0" encoding="UTF-8"?>
<project  
	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>

	<artifactId>spring-boot-web-jsp</artifactId>
	<packaging>war</packaging>
	<name>Spring Boot Web JSP Example</name>
	<description>Spring Boot Web JSP Example</description>
	<url>https://www.mkyong.com</url>
	<version>1.0</version>

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

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

	<dependencies>

		<!-- This is a web application -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- Tomcat embedded container-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>

		<!-- JSTL for JSP -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>

		<!-- Need this to compile JSP -->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>

		<!-- Need this to compile JSP, 
			tomcat-embed-jasper version is not working, no idea why -->
		<dependency>
			<groupId>org.eclipse.jdt.core.compiler</groupId>
			<artifactId>ecj</artifactId>
			<version>4.6.1</version>
			<scope>provided</scope>
		</dependency>

		<!-- Optional, test for static content, bootstrap CSS-->
		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>bootstrap</artifactId>
			<version>3.3.7</version>
		</dependency>

	</dependencies>
	<build>
		<plugins>
			<!-- Package as an executable jar/war -->
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project> 

显示项目部门:

 $ mvn dependency:tree

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Spring Boot Web JSP Example 1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.10:tree (default-cli) @ spring-boot-web-jsp ---
[INFO] org.springframework.boot:spring-boot-web-jsp:war:1.0
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:1.4.2.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:1.4.2.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:1.4.2.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:1.4.2.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:1.4.2.RELEASE:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.1.7:compile
[INFO] |  |  |  |  +- ch.qos.logback:logback-core:jar:1.1.7:compile
[INFO] |  |  |  |  \- org.slf4j:slf4j-api:jar:1.7.21:compile
[INFO] |  |  |  +- org.slf4j:jcl-over-slf4j:jar:1.7.21:compile
[INFO] |  |  |  +- org.slf4j:jul-to-slf4j:jar:1.7.21:compile
[INFO] |  |  |  \- org.slf4j:log4j-over-slf4j:jar:1.7.21:compile
[INFO] |  |  +- org.springframework:spring-core:jar:4.3.4.RELEASE:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.17:runtime
[INFO] |  +- org.hibernate:hibernate-validator:jar:5.2.4.Final:compile
[INFO] |  |  +- javax.validation:validation-api:jar:1.1.0.Final:compile
[INFO] |  |  +- org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile
[INFO] |  |  \- com.fasterxml:classmate:jar:1.3.3:compile
[INFO] |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.8.4:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.4:compile
[INFO] |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.8.4:compile
[INFO] |  +- org.springframework:spring-web:jar:4.3.4.RELEASE:compile
[INFO] |  |  +- org.springframework:spring-aop:jar:4.3.4.RELEASE:compile
[INFO] |  |  +- org.springframework:spring-beans:jar:4.3.4.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-context:jar:4.3.4.RELEASE:compile
[INFO] |  \- org.springframework:spring-webmvc:jar:4.3.4.RELEASE:compile
[INFO] |     \- org.springframework:spring-expression:jar:4.3.4.RELEASE:compile
[INFO] +- org.springframework.boot:spring-boot-starter-tomcat:jar:1.4.2.RELEASE:provided
[INFO] |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.6:provided
[INFO] |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:8.5.6:provided
[INFO] |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.5.6:provided
[INFO] +- javax.servlet:jstl:jar:1.2:compile
[INFO] +- org.apache.tomcat.embed:tomcat-embed-jasper:jar:8.5.6:provided
[INFO] +- org.eclipse.jdt.core.compiler:ecj:jar:4.6.1:provided
[INFO] \- org.webjars:bootstrap:jar:3.3.7:compile
[INFO]    \- org.webjars:jquery:jar:1.11.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.327 s
[INFO] Finished at: 2016-11-28T16:57:00+08:00
[INFO] Final Memory: 20M/309M
[INFO] ------------------------------------------------------------------------ 

3.弹簧弹簧

3.1 这个SpringBootServletInitializer运行一个来自传统战争部署的SpringApplication

SpringBootWebApplication.java

 package com.mkyong;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;

@SpringBootApplication
public class SpringBootWebApplication extends SpringBootServletInitializer {
    
    

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    
    
		return application.sources(SpringBootWebApplication.class);
	}

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

} 

3.2 一个简单的 Spring 控制器类。

WelcomeController.java

 package com.mkyong;

import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class WelcomeController {
    
    

	// inject via application.properties
	@Value("${welcome.message:test}")
	private String message = "Hello World";

	@RequestMapping("/")
	public String welcome(Map<String, Object> model) {
    
    
		model.put("message", this.message);
		return "welcome";
	}

} 

4.JSP +资源+静态文件

4.1 对于 JSP 文件,放入src/main/webapp/WEB-INF/jsp/

src/main/webapp/WEB-INF/jsp/welcome.jsp

 <!DOCTYPE html>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html lang="en">
<head>

	<!-- Access the bootstrap Css like this, 
		Spring boot will handle the resource mapping automcatically -->
	<link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css" />

	<!-- 
	<spring:url value="/css/main.css" var="springCss" />
	<link href="${springCss}" rel="stylesheet" />
	 -->
	<c:url value="/css/main.css" var="jstlCss" />
	<link href="${jstlCss}" rel="stylesheet" />

</head>
<body>

	<nav class="navbar navbar-inverse">
		<div class="container">
			<div class="navbar-header">
				<a class="navbar-brand" href="#">Spring Boot</a>
			</div>
			<div id="navbar" class="collapse navbar-collapse">
				<ul class="nav navbar-nav">
					<li class="active"><a href="#">Home</a></li>
					<li><a href="#about">About</a></li>
				</ul>
			</div>
		</div>
	</nav>

	<div class="container">

		<div class="starter-template">
			<h1>Spring Boot Web JSP Example</h1>
			<h2>Message: ${
    
    message}</h2>
		</div>

	</div>

	<script type="text/javascript" src="webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script>

</body>

</html> 

4.2 对于 CSS 或 Javascript 等静态文件,放入/src/main/resources/static/

/src/main/resources/static/css/main.css

 h1{
    
    
	color:#0000FF;
}

h2{
    
    
	color:#FF0000;
} 

4.3 对于属性文件,输入/src/main/resources/

/src/main/resources/application.properties

 spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp

welcome.message: Hello Mkyong 

Note
Spring Boot, convention over configuration, no need to declare the resource mapping like this. The resource mapping just handles automatically – Read this article – Spring Boot Serving static content

5.演示

5.1 启动 Spring Boot 网络应用程序。

 project$ mvn spring-boot:run

//...
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.4.2.RELEASE)

2016-11-28 17:25:24.809  INFO 4696 --- [           main] com.mkyong.SpringBootWebApplication      : Starting SpringBootWebApplication on MKYONG-WIN10 with PID 4696 (C:\spring-boot\spring-boot-examples\spring-boot-web-jsp\target\classes started by mkyong in C:\spring-boot\spring-boot-examples\spring-boot-web-jsp)
2016-11-28 17:25:24.812  INFO 4696 --- [           main] com.mkyong.SpringBootWebApplication      : No active profile set, falling back to default profiles: default
2016-11-28 17:25:24.861  INFO 4696 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@69410cd3: startup date [Mon Nov 28 17:25:24 SGT 2016]; root of context hierarchy
2016-11-28 17:25:25.950  INFO 4696 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2016-11-28 17:25:25.965  INFO 4696 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2016-11-28 17:25:25.966  INFO 4696 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.6
2016-11-28 17:25:26.171  INFO 4696 --- [ost-startStop-1] org.apache.jasper.servlet.TldScanner     : At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
2016-11-28 17:25:26.180  INFO 4696 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2016-11-28 17:25:26.180  INFO 4696 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1322 ms
2016-11-28 17:25:26.304  INFO 4696 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2016-11-28 17:25:26.312  INFO 4696 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2016-11-28 17:25:26.313  INFO 4696 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2016-11-28 17:25:26.313  INFO 4696 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2016-11-28 17:25:26.314  INFO 4696 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]

//...

2016-11-28 17:25:26.841  INFO 4696 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2016-11-28 17:25:26.846  INFO 4696 --- [           main] com.mkyong.SpringBootWebApplication      : Started SpringBootWebApplication in 2.403 seconds (JVM running for 5.08) 

5.2 访问 http://localhost:8080

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.3 Maven 将项目打包成可执行的WAR文件。在target文件夹中会生成一个 18M++的WAR文件。

 project$ mvn clean package

...
[INFO] Building war: ...\spring-boot-web-jsp\target\spring-boot-web-jsp-1.0.war
[INFO]
[INFO] --- spring-boot-maven-plugin:1.4.2.RELEASE:repackage (default) @ spring-boot-web-jsp ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------ 

运行它,再次访问 http://localhost:8080

 project$ java -jar target/spring-boot-web-jsp-1.0.war 

JSP limitations
You can’t create an executable jar to run this embedded Tomcat + JSP web example, because of a hard coded file pattern in Tomcat. Read this Spring Boot – JSP limitation.

下载源代码

Download it – spring-boot-web-jsp.zip (8KB)

参考

  1. Spring Boot–静态内容
  2. SpringBootServletInitializer JavaDoc
  3. 部署 Spring Boot 应用
  4. Spring Boot–JSP 限制
  5. spring MVC–in ucci CSS 文件

Spring Boot Hello World 示例-小胡子

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-hello-world-example-mustache/

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一个 Spring Boot 的 web 应用实例,使用embedded Tomcat + Mustache template engine,并打包成一个可执行的JAR文件。

使用的技术:

  1. Spring Boot 1.5.2 .版本
  2. 弹簧 4.3.7 .释放
  3. jmustache 1.13
  4. 百里香叶
  5. Tomcat Embed 8.5.11
  6. maven3
  7. Java 8

Note
Spring Boot uses jmustache to integrate Mustache as template engine.

1.项目目录

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.项目相关性

声明spring-boot-starter-mustache,它将获得开发Spring + Mustache web 应用程序所需的任何东西。

pom.xml

 <?xml version="1.0" encoding="UTF-8"?>
<project  
	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>

	<artifactId>spring-boot-web-mustache</artifactId>
	<packaging>jar</packaging>
	<name>Spring Boot Web Mustache Example</name>
	<description>Spring Boot Web Mustache Example</description>
	<url>https://www.mkyong.com</url>
	<version>1.0</version>

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

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

	<dependencies>

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

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

		<!-- hot swapping, live reload -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>

		<!-- Optional, for bootstrap -->
		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>bootstrap</artifactId>
			<version>3.3.7</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<!-- Package as an executable jar/war -->
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project> 

显示项目相关性:

 $ mvn dependency:tree

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Spring Boot Web Mustache Example 1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.10:tree (default-cli) @ spring-boot-web-mustache ---
                               [INFO] org.springframework.boot:spring-boot-web-mustache:jar:1.0
[INFO] +- org.springframework.boot:spring-boot-starter-mustache:jar:1.5.2.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:1.5.2.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:1.5.2.RELEASE:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.1.11:compile
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.1.11:compile
[INFO] |  |  |  +- org.slf4j:jcl-over-slf4j:jar:1.7.24:compile
[INFO] |  |  |  +- org.slf4j:jul-to-slf4j:jar:1.7.24:compile
[INFO] |  |  |  \- org.slf4j:log4j-over-slf4j:jar:1.7.24:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.17:runtime
[INFO] |  +- org.springframework.boot:spring-boot-starter-web:jar:1.5.2.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:1.5.2.RELEASE:compile
[INFO] |  |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.11:compile
[INFO] |  |  |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:8.5.11:compile
[INFO] |  |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.5.11:compile
[INFO] |  |  +- org.hibernate:hibernate-validator:jar:5.3.4.Final:compile
[INFO] |  |  |  +- javax.validation:validation-api:jar:1.1.0.Final:compile
[INFO] |  |  |  +- org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile
[INFO] |  |  |  \- com.fasterxml:classmate:jar:1.3.3:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.8.7:compile
[INFO] |  |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.0:compile
[INFO] |  |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.8.7:compile
[INFO] |  |  +- org.springframework:spring-web:jar:4.3.7.RELEASE:compile
[INFO] |  |  |  +- org.springframework:spring-aop:jar:4.3.7.RELEASE:compile
[INFO] |  |  |  \- org.springframework:spring-beans:jar:4.3.7.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-webmvc:jar:4.3.7.RELEASE:compile
[INFO] |  |     \- org.springframework:spring-expression:jar:4.3.7.RELEASE:compile
[INFO] |  \- com.samskivert:jmustache:jar:1.13:compile
[INFO] +- org.springframework.boot:spring-boot-starter-test:jar:1.5.2.RELEASE:test
[INFO] |  +- org.springframework.boot:spring-boot-test:jar:1.5.2.RELEASE:test
[INFO] |  +- org.springframework.boot:spring-boot-test-autoconfigure:jar:1.5.2.RELEASE:test
[INFO] |  +- com.jayway.jsonpath:json-path:jar:2.2.0:test
[INFO] |  |  +- net.minidev:json-smart:jar:2.2.1:test
[INFO] |  |  |  \- net.minidev:accessors-smart:jar:1.1:test
[INFO] |  |  |     \- org.ow2.asm:asm:jar:5.0.3:test
[INFO] |  |  \- org.slf4j:slf4j-api:jar:1.7.24:compile
[INFO] |  +- junit:junit:jar:4.12:test
[INFO] |  +- org.assertj:assertj-core:jar:2.6.0:test
[INFO] |  +- org.mockito:mockito-core:jar:1.10.19:test
[INFO] |  |  \- org.objenesis:objenesis:jar:2.1:test
[INFO] |  +- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] |  +- org.hamcrest:hamcrest-library:jar:1.3:test
[INFO] |  +- org.skyscreamer:jsonassert:jar:1.4.0:test
[INFO] |  |  \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
[INFO] |  +- org.springframework:spring-core:jar:4.3.7.RELEASE:compile
[INFO] |  \- org.springframework:spring-test:jar:4.3.7.RELEASE:test
[INFO] +- org.springframework.boot:spring-boot-devtools:jar:1.5.2.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot:jar:1.5.2.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-context:jar:4.3.7.RELEASE:compile
[INFO] |  \- org.springframework.boot:spring-boot-autoconfigure:jar:1.5.2.RELEASE:compile
[INFO] \- org.webjars:bootstrap:jar:3.3.7:compile
[INFO]    \- org.webjars:jquery:jar:1.11.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.796 s
[INFO] Finished at: 2017-04-19T11:46:09+08:00
[INFO] Final Memory: 22M/437M
[INFO] ------------------------------------------------------------------------ 

3.Spring Boot

3.1 创建一个@SpringBootApplication类。运行这个类来启动 Spring Boot web 应用程序。

SpringBootWebApplication.java

 package com.mkyong;

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

@SpringBootApplication
public class SpringBootWebApplication {
    
    

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

} 

3.2 一个简单的控制器类。

WelcomeController.java

 package com.mkyong;

import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class WelcomeController {
    
    

	// inject via application.properties
	@Value("${app.welcome.message}")
	private String MESSAGE = "";

	@Value("${app.welcome.title}")
	private String TITLE = "";

	@RequestMapping("/")
	public String welcome(Map<String, Object> model) {
    
    
		model.put("title", TITLE);
		model.put("message", MESSAGE);
		return "welcome";
	}

	// test 5xx errors
	@RequestMapping("/5xx")
	public String ServiceUnavailable() {
    
    
		throw new RuntimeException("ABC");
	}

} 

4.小胡子+资源+静态文件

4.1 对于小胡子模板文件,放入src/main/resources/templates/

src/main/resources/templates/layout/header.html

 <!DOCTYPE HTML>
<head>

<title>{
    
    {
    
    title}}</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css" />
<link rel="stylesheet" href="css/main.css" />

</head>
<!--  this is header --> 

src/main/resources/templates/layout/footer.html

 <!--  this is footer -->
</html> 

src/main/resources/templates/welcome.html

 {
    
    {
    
    >layout/header}}
<body>

	<nav class="navbar navbar-inverse">
		<div class="container">
			<div class="navbar-header">
				<a class="navbar-brand" href="#">Spring Boot</a>
			</div>
		</div>
	</nav>

	<div class="container">

		<div class="starter-template">
			<h1>Spring Boot Web Mustache Example</h1>
			<h2>
				{
    
    {
    
    message}}
			</h2>
		</div>

	</div>
	<!-- /.container -->

	<script type="text/javascript" src="webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script>

</body>
{
    
    {
    
    >layout/footer}} 

4.2 对于 CSS 或 Javascript 等静态文件,放入/src/main/resources/static/

/src/main/resources/static/css/main.css

 h1{
    
    
	color:#0000FF;
}

h2{
    
    
	color:#FF0000;
} 

4.3 对于错误模板。

Note
Read this Spring Boot – Error Handling to understand how the default error mapping page works.src/main/resources/templates/error.html

 <!DOCTYPE html>

<html lang="en">

<body>
	Something went wrong: {
    
    {
    
    status}} {
    
    {
    
    error}}
</body>

</html> 

src/main/resources/templates/error/5xx.html

 <!DOCTYPE html>

<html lang="en">

<body>
	I'm a 5xx
</body>

</html> 

4.4 对于属性文件,输入/src/main/resources/

/src/main/resources/application.properties

 app.welcome.message: Hello Mkyong
app.welcome.title: Spring Boot Mustache Hello World Example 

Note
Read this Spring Boot Serving static content to understand the resource mapping.

5.单元测试

5.1 单元测试示例测试上面的 Spring Boot web 应用程序。

MustacheApplicationTests

 package com.mkyong;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Arrays;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@DirtiesContext
public class MustacheApplicationTests {
    
    

	@Autowired
	private TestRestTemplate restTemplate;

	@Test
	public void testMainPage() throws Exception {
    
    

		ResponseEntity<String> entity = this.restTemplate.getForEntity("/", String.class);
		assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
		assertThat(entity.getBody()).contains("Hello Mkyong");

	}

	@Test
	public void test404Page() throws Exception {
    
    

		HttpHeaders headers = new HttpHeaders();
		headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
		HttpEntity<String> requestEntity = new HttpEntity<String>(headers);
		ResponseEntity<String> responseEntity = this.restTemplate.exchange("/uri-not-exist", HttpMethod.GET,
				requestEntity, String.class);
		assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
		assertThat(responseEntity.getBody()).contains("Something went wrong: 404 Not Found");

	}

	@Test
	public void test5xxPage() throws Exception {
    
    

		HttpHeaders headers = new HttpHeaders();
		headers.setAccept(Arrays.asList(MediaType.TEXT_HTML));
		HttpEntity<String> requestEntity = new HttpEntity<String>(headers);
		ResponseEntity<String> responseEntity = this.restTemplate.exchange("/5xx", HttpMethod.GET, requestEntity,
				String.class);
		assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
		assertThat(responseEntity.getBody()).contains("I'm a 5xx");

	}

} 

6.演示

Note
In IDE, run the @SpringBootApplication annotated class, and the entire Spring Boot application will be started.

6.1 启动 Spring Boot 网络应用程序。

Terminal

 project$ mvn spring-boot:run

//...
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.2.RELEASE)

2017-04-19 12:17:38.014  INFO 6232 --- [  restartedMain] com.mkyong.SpringBootWebApplication      : Starting SpringBootWebApplication on MKYONG-WIN10 with PID 6232 (C:\spring-boot\spring-boot-examples\spring-boot-web-mustache\target\classes started by mkyong in C:\spring-boot\spring-boot-examples\spring-boot-web-mustache)
2017-04-19 12:17:38.015  INFO 6232 --- [  restartedMain] com.mkyong.SpringBootWebApplication      : No active profile set, falling back to default profiles: default
2017-04-19 12:17:38.074  INFO 6232 --- [  restartedMain] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@af1619: startup date [Wed Apr 19 12:17:38 SGT 2017]; root of context hierarchy
2017-04-19 12:17:39.352  INFO 6232 --- [  restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2017-04-19 12:17:39.370  INFO 6232 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service Tomcat
2017-04-19 12:17:39.372  INFO 6232 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.11
2017-04-19 12:17:39.481  INFO 6232 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-04-19 12:17:39.481  INFO 6232 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1410 ms
2017-04-19 12:17:39.649  INFO 6232 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2017-04-19 12:17:39.658  INFO 6232 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-04-19 12:17:39.659  INFO 6232 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-04-19 12:17:39.659  INFO 6232 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-04-19 12:17:39.660  INFO 6232 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2017-04-19 12:17:39.938  INFO 6232 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@af1619: startup date [Wed Apr 19 12:17:38 SGT 2017]; root of context hierarchy
2017-04-19 12:17:39.997  INFO 6232 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String com.mkyong.WelcomeController.welcome(java.util.Map<java.lang.String, java.lang.Object>)
2017-04-19 12:17:39.997  INFO 6232 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/5xx]}" onto public java.lang.String com.mkyong.WelcomeController.ServiceUnavailable()
2017-04-19 12:17:40.006  INFO 6232 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2017-04-19 12:17:40.006  INFO 6232 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2017-04-19 12:17:40.041  INFO 6232 --- [  restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-04-19 12:17:40.041  INFO 6232 --- [  restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-04-19 12:17:40.090  INFO 6232 --- [  restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-04-19 12:17:40.332  INFO 6232 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2017-04-19 12:17:40.373  INFO 6232 --- [  restartedMain] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-04-19 12:17:40.427  INFO 6232 --- [  restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2017-04-19 12:17:40.435  INFO 6232 --- [  restartedMain] com.mkyong.SpringBootWebApplication      : Started SpringBootWebApplication in 2.737 seconds (JVM running for 3.124) 

6.2 访问 http://localhost:8080

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6.2 访问http://localhost:8080/uri-not-exist

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6.2 访问http://localhost:8080/5xx

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6.构建可执行的 JAR

6.1 将项目打包,创建一个可执行的JAR文件。

 project$ mvn clean package 

6.2 运行它,再次访问 http://localhost:8080

 project$ java -jar target/spring-boot-web-mustache-1.0.jar 

下载源代码

Download it – spring-boot-web-mustache.zip (11 KB)

参考

  1. 小胡子模板引擎
  2. jmustache——Mustache 模板语言的 Java 实现
  3. Spring Boot–错误处理
  4. Spring Boot–静态内容
  5. 部署 Spring Boot 应用
  6. spring MVC–in ucci CSS 文件
  7. Spring Boot——开发者工具
  8. 使用 Spring MVC 提供 Web 内容
  9. Spring Boot Hello World 示例–JSP

Spring Boot Hello World 示例-百里香叶

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-hello-world-example-thymeleaf/

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在本文中,我们将向您展示如何开发一个 Spring Boot web 应用程序,使用百里香叶视图,嵌入式 Tomcat,并将其打包为一个可执行的JAR文件。

使用的技术:

  • Spring Boot 2.1.2 .版本
  • 弹簧 5.1.4 释放
  • 百里香叶
  • Tomcat embed 9.0.14
  • JUnit 4.12
  • maven3
  • Java 8

1.项目目录

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.专家

放上spring-boot-starter-webspring-boot-starter-thymeleaf,它将获得我们开发 Spring MVC + Thymeleaf web 应用程序所需的任何东西,包括嵌入式 Tomcat 服务器。

pom.xml

 <?xml version="1.0" encoding="UTF-8"?>
<project  
		 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>

    <artifactId>web-thymeleaf</artifactId>
    <packaging>jar</packaging>
    <name>Spring Boot Web Thymeleaf Example</name>
    <description>Spring Boot Web Thymeleaf Example</description>
    <version>1.0</version>

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

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

    <dependencies>

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

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

        <!-- test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- hot swapping, disable cache for template, enable live reload -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- Optional, for bootstrap -->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>${
    
    bootstrap.version}</version>
        </dependency>

    </dependencies>
    <build>
        <plugins>

            <!-- Package as an executable jar/war -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <addResources>true</addResources>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.0</version>
            </plugin>

        </plugins>

    </build>
</project> 

显示项目依赖关系。

 $ mvn dependency:tree

[INFO] org.springframework.boot:web-thymeleaf:jar:1.0
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.1.2.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.1.2.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.1.2.RELEASE:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.11.1:compile
[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.11.1:compile
[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.25:compile
[INFO] |  |  +- javax.annotation:javax.annotation-api:jar:1.3.2:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.23:runtime
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.1.2.RELEASE:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.9.8:compile
[INFO] |  |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.9.0:compile
[INFO] |  |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.9.8:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.9.8:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.9.8:compile
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.9.8:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-tomcat:jar:2.1.2.RELEASE:compile
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:9.0.14:compile
[INFO] |  |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:9.0.14:compile
[INFO] |  |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:9.0.14:compile
[INFO] |  +- org.hibernate.validator:hibernate-validator:jar:6.0.14.Final:compile
[INFO] |  |  +- javax.validation:validation-api:jar:2.0.1.Final:compile
[INFO] |  |  +- org.jboss.logging:jboss-logging:jar:3.3.2.Final:compile
[INFO] |  |  \- com.fasterxml:classmate:jar:1.4.0:compile
[INFO] |  +- org.springframework:spring-web:jar:5.1.4.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-beans:jar:5.1.4.RELEASE:compile
[INFO] |  \- org.springframework:spring-webmvc:jar:5.1.4.RELEASE:compile
[INFO] |     +- org.springframework:spring-aop:jar:5.1.4.RELEASE:compile
[INFO] |     +- org.springframework:spring-context:jar:5.1.4.RELEASE:compile
[INFO] |     \- org.springframework:spring-expression:jar:5.1.4.RELEASE:compile
[INFO] +- org.springframework.boot:spring-boot-starter-thymeleaf:jar:2.1.2.RELEASE:compile
[INFO] |  +- org.thymeleaf:thymeleaf-spring5:jar:3.0.11.RELEASE:compile
[INFO] |  |  +- org.thymeleaf:thymeleaf:jar:3.0.11.RELEASE:compile
[INFO] |  |  |  +- org.attoparser:attoparser:jar:2.0.5.RELEASE:compile
[INFO] |  |  |  \- org.unbescape:unbescape:jar:1.1.6.RELEASE:compile
[INFO] |  |  \- org.slf4j:slf4j-api:jar:1.7.25:compile
[INFO] |  \- org.thymeleaf.extras:thymeleaf-extras-java8time:jar:3.0.2.RELEASE:compile
[INFO] +- org.springframework.boot:spring-boot-starter-test:jar:2.1.2.RELEASE:test
[INFO] |  +- org.springframework.boot:spring-boot-test:jar:2.1.2.RELEASE:test
[INFO] |  +- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.1.2.RELEASE:test
[INFO] |  +- com.jayway.jsonpath:json-path:jar:2.4.0:test
[INFO] |  |  \- net.minidev:json-smart:jar:2.3:test
[INFO] |  |     \- net.minidev:accessors-smart:jar:1.2:test
[INFO] |  |        \- org.ow2.asm:asm:jar:5.0.4:test
[INFO] |  +- junit:junit:jar:4.12:test
[INFO] |  +- org.assertj:assertj-core:jar:3.11.1:test
[INFO] |  +- org.mockito:mockito-core:jar:2.23.4:test
[INFO] |  |  +- net.bytebuddy:byte-buddy:jar:1.9.7:test
[INFO] |  |  +- net.bytebuddy:byte-buddy-agent:jar:1.9.7:test
[INFO] |  |  \- org.objenesis:objenesis:jar:2.6:test
[INFO] |  +- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] |  +- org.hamcrest:hamcrest-library:jar:1.3:test
[INFO] |  +- org.skyscreamer:jsonassert:jar:1.5.0:test
[INFO] |  |  \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
[INFO] |  +- org.springframework:spring-core:jar:5.1.4.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-jcl:jar:5.1.4.RELEASE:compile
[INFO] |  +- org.springframework:spring-test:jar:5.1.4.RELEASE:test
[INFO] |  \- org.xmlunit:xmlunit-core:jar:2.6.2:test
[INFO] |     \- javax.xml.bind:jaxb-api:jar:2.3.1:test
[INFO] |        \- javax.activation:javax.activation-api:jar:1.2.0:test
[INFO] +- org.springframework.boot:spring-boot-devtools:jar:2.1.2.RELEASE:compile (optional)
[INFO] |  +- org.springframework.boot:spring-boot:jar:2.1.2.RELEASE:compile
[INFO] |  \- org.springframework.boot:spring-boot-autoconfigure:jar:2.1.2.RELEASE:compile
[INFO] \- org.webjars:bootstrap:jar:4.2.1:compile
[INFO]    +- org.webjars:jquery:jar:3.0.0:compile
[INFO]    \- org.webjars:popper.js:jar:1.14.3:compile 

3.开发者工具

 <dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-devtools</artifactId>
		<optional>true</optional>
	</dependency> 

这个spring-boot-devtools有助于禁用高速缓存并启用热插拔,这样开发人员将总是看到最后的更改。有利于发展。阅读此–Spring Boot–开发者工具尝试修改百里香模板或属性文件,刷新浏览器以查看更改是否立即生效。

4.Spring Boot + MVC

4.1 简单的控制器。

WelcomeController.java

 package com.mkyong.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.Arrays;
import java.util.List;

@Controller
public class WelcomeController {
    
    

    // inject via application.properties
    @Value("${welcome.message}")
    private String message;

    private List<String> tasks = Arrays.asList("a", "b", "c", "d", "e", "f", "g");

    @GetMapping("/")
    public String main(Model model) {
    
    
        model.addAttribute("message", message);
        model.addAttribute("tasks", tasks);

        return "welcome"; //view
    }

    // /hello?name=kotlin
    @GetMapping("/hello")
    public String mainWithParam(
            @RequestParam(name = "name", required = false, defaultValue = "") 
			String name, Model model) {
    
    

        model.addAttribute("message", name);

        return "welcome"; //view
    }

} 

4.2 创建一个类并用@SpringBootApplication标注。在 IDE 中,运行此类来启动整个 web 应用程序。

StartWebApplication.java

 package com.mkyong;

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

@SpringBootApplication
public class StartWebApplication {
    
    

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

} 

5.百里香+静态文件

Note
Read this Spring Boot Serving static content to understand the resource mapping.

5.1 对于百里香模板文件,放入src/main/resources/templates/

src/main/resources/templates/welcome.html

 <!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <title>Spring Boot Thymeleaf Hello World Example</title>

    <link rel="stylesheet" th:href="@{webjars/bootstrap/4.2.1/css/bootstrap.min.css}"/>
    <link rel="stylesheet" th:href="@{/css/main.css}"/>

</head>

<body>

<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
    <a class="navbar-brand" href="#">Mkyong.com</a>
</nav>

<main role="main" class="container">

    <div class="starter-template">
        <h1>Spring Boot Web Thymeleaf Example</h1>
        <h2>
            <span th:text="'Hello, ' + ${message}"></span>
        </h2>
    </div>

    <ol>
        <li th:each="task : ${tasks}" th:text="${task}"></li>
    </ol>

</main>
<!-- /.container -->

<script type="text/javascript" th:src="@{webjars/bootstrap/4.2.1/js/bootstrap.min.js}"></script>
</body>
</html> 

5.2 Spring Boot 通用应用属性

src/main/resources/application.properties

 welcome.message: Mkyong

spring.thymeleaf.cache=false 

5.3 对于 CSS 或 JS 等静态文件,放入src/main/resources/static/

src/main/resources/static/css/main.css

 body {
    
    
  padding-top: 5rem;
}
.starter-template {
    
    
  padding: 3rem 1.5rem;
  text-align: center;
}

h1{
    
    
	color:#0000FF;
}

h2{
    
    
	color:#FF0000;
} 

6.单元测试

MockMvc测试 Spring MVC 控制器。

WelcomeControllerTest.java

 package com.mkyong;

import com.mkyong.controller.WelcomeController;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.web.servlet.ModelAndView;

import java.util.Arrays;
import java.util.List;

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = WelcomeController.class)
public class WelcomeControllerTest {
    
    

    @Autowired
    private MockMvc mockMvc;

    List<String> expectedList = Arrays.asList("a", "b", "c", "d", "e", "f", "g");

    @Test
    public void main() throws Exception {
    
    
        ResultActions resultActions = mockMvc.perform(get("/"))
                .andExpect(status().isOk())
                .andExpect(view().name("welcome"))
                .andExpect(model().attribute("message", equalTo("Mkyong")))
                .andExpect(model().attribute("tasks", is(expectedList)))
                .andExpect(content().string(containsString("Hello, Mkyong")));

        MvcResult mvcResult = resultActions.andReturn();
        ModelAndView mv = mvcResult.getModelAndView();
        //
    }

    // Get request with Param
    @Test
    public void hello() throws Exception {
    
    
        mockMvc.perform(get("/hello").param("name", "I Love Kotlin!"))
                .andExpect(status().isOk())
                .andExpect(view().name("welcome"))
                .andExpect(model().attribute("message", equalTo("I Love Kotlin!")))
                .andExpect(content().string(containsString("Hello, I Love Kotlin!")));
    }

} 

7.演示

 $ mvn spring-boot:run

: Tomcat initialized with port(s): 8080 (http)
: Starting service [Tomcat]
: Starting Servlet engine: [Apache Tomcat/9.0.14]

: Tomcat started on port(s): 8080 (http) with context path ''
 Started StartWebApplication in 1.858 seconds (JVM running for 2.222) 

URL = http://localhost:8080

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

URL =http://localhost:8080/hello?name=abc

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

8.创建可执行的 JAR

对于部署,只需普通的 Maven 包来创建一个可执行的 JAR 文件。

 $ mvn clean package

$ java -jar target\web-thymeleaf-1.0.jar 

下载源代码

$ git clone https://github.com/mkyong/spring-boot.git
$ cd web-thymeleaf
$ mvn spring-boot:run

参考

猜你喜欢

转载自blog.csdn.net/wizardforcel/article/details/143497633