Springboot Manual

This is a General description of SpringBoot. All the Resources in this passage are from the official guide and some of these examples and codes are concluded myself, which are definitely not so authoritative
. However, hope the materials helps a little.

Overview

Structure Your Code

Technically, Spring Boot does not require any specific code layout to work. However, there are some best practices that help:

  • Your main application class:

  • It is generally recommend that you locate your main application class in a root package above other
    classes. The @SpringBootApplication annotation is often placed on your main class, and it implicitly
    defines a base “search package” for certain items

  • For example, the follwoing structure:

   com
   +- example
       +- myapplication
           +- Application.java
           |
           +- customer
           |   +- Customer.java
           |   +- CustomerController.java
           |   +- CustomerService.java
           |   +- CustomerRepository.java
           |
           +- order
               +- Order.java
               +- OrderController.java
               +- OrderService.java
               +- OrderRepository.java
  • Your primary configuration class

  • Although it is possible to use SpringApplication with XML sources, we generally recommend that your primary source be a single @Configuration class. Usually the class that defines the main method is a good candidate as the primary @Configuration.

  • You can also import configuration classes:

  • The @Import annotation can be used to import additional configuration classes. Alternatively, you can use @ComponentScan to automatically pick up all Spring components, including @Configuration classes.

  • Import XML Configuration

  • If you need to use an XML based configuration, we recommend that you still start with a @Configuration class. You can then use an @ImportResource annotation to load XML configuration files.

  • A single @SpringBootApplication annotation can be used to enable three features, that is:

    • @EnableAutoConfiguration: enable Spring Boot’s auto-configuration mechanism, which *imports many xxxAutoConfiguration classes defined by
      @Import(AutoConfigurationImportSelector.class) *(you will see this when you look at the @EnableAutoConfigurations class). More details see the section below.

    • @ComponentScan: enable @Component scan on the package where the application is located (see the best practices)

    • @Configuration: allow to register extra beans in the context or import additional configuration classes
      SO, the @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration, and @ComponentScan with their default attributes, as shown in the following example:

    package com.example.myapplication;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    
    }
    

Auro-Configuration

You can also choose to use the Spring Boot auto-configuration, which attempts to automatically configure your Spring application based on the jar dependencies that you have added.

For example, if the H2 database Jar is present in the classpath and we have not configured any beans related to the database manually, the Spring Boot’s auto-configuration feature automatically configures it in the project.

To enable auto-configuration, you need to add either @EnableAutoConfiguration or @SpringBootApplication annotations to one of your @Configuration classes.

EnableAutoConfiguration under the hood:

  • When you click into the @EnableAutoConfiguration annotation, you will see that it imports the AutoConfigurationImportSelector.class.

  • Within that class, it uses the method List<String> configurations = SpringFactoriesLoader.loadFactoryNames(..) to return to your configurations that will be imported into your application.

  • When you click into that method loadFactoryNames(), you will see the line: classLoader.getResources(FACTORIES_RESOURCE_LOCATION), where that Factories_RESOURCE_LOCATION points to: \.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.3.0.RELEASE\spring-boot-autoconfigure-2.3.0.RELEASE.jar!\META-INF\spring.factories

  • The xxxAutoConfiguration classes specified in that spring.factories file will be loaded into your application, if conditions specified in those classes are fulfilled (e.g. @ConditionalOnMissingProperties(..))

  • And it is those xxxAutoConfiguration classes that configures your Spring Boot Application by reading/injecting values from their respective .properties file. This means that you can configure those settings in your own application.properties file with the correct prefix

Springboot Configuration

Configuration Files

Springboot apply a global configuration file and this file name is fixed.

  • application.properties
  • syntactic structure: key = value
  • application.yml
  • syntactic structure: key: value

The function of configuration file: modify the default value in Springboot configuration, because Springboot has allocated these values in the background.

YAML Configuration File

TAML is the short for “YAML Ain’t a Markup Language”. It is a configuration language which can assign value to objects.

For example, to assgn values to the object Person:

package com.danny.pojo;

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

import java.util.Date;
import java.util.List;
import java.util.Map;

@Component
@ConfigurationProperties(prefix = "person")

//@ConfigurationProperties: To map the values in configuration file to the component.
// And tell SpringBoot to combine the properties in this class with the values in the configuration files
// The parameter prefix = "Person" : To correspond the values in configuration file with the properties of Person object

public class Person {
//    person:
//    name: Danny
//    happy: false
//    birth: 2020/7/11
//    maps: {k1: v1,k2 v2}
//    list:
//     - code
//     - music
//     - sport
//    dog=Dog{name='cat', age=3}
    private String name;
    private Integer age;
    private Boolean happy;
    private Date birth;
    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;

    public Person() {
    }

    public Person(String name, Integer age, Boolean happy, Date birth, Map<String, Object> maps, List<Object> lists, Dog dog) {
        this.name = name;
        this.age = age;
        this.happy = happy;
        this.birth = birth;
        this.maps = maps;
        this.lists = lists;
        this.dog = dog;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }

    public Boolean getHappy() {
        return happy;
    }

    public Date getBirth() {
        return birth;
    }

    public Map<String, Object> getMaps() {
        return maps;
    }

    public List<Object> getLists() {
        return lists;
    }

    public Dog getDog() {
        return dog;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setHappy(Boolean happy) {
        this.happy = happy;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public void setLists(List<Object> lists) {
        this.lists = lists;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", happy=" + happy +
                ", birth=" + birth +
                ", maps=" + maps +
                ", lists=" + lists +
                ", dog=" + dog +
                '}';
    }
}

The configuration YAML file is demonstrated as the following:

person:
  name: Danny
  happy: false
  birth: 2020/7/11
  maps: {k1: v1,k2 v2}
  list:
    - code
    - music
    - sport
  dog:
    name: cat
    age: 3

In the test class:

package com.danny;

import com.danny.pojo.Dog;
import com.danny.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class Demo01HelloworldApplicationTests {

    @Autowired
    private Person person;
    @Test
    void contextLoads() {
        System.out.println(person);
    }
}

Ths output in the following :

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

2020-07-28 16:21:27.176  INFO 16576 --- [           main] c.d.Demo01HelloworldApplicationTests     : Starting Demo01HelloworldApplicationTests on 举世无双的暗影精灵 with PID 16576 (started by pc in D:\zwh52\coursework\SpringBoot\Springbootdemo)
2020-07-28 16:21:27.178  INFO 16576 --- [           main] c.d.Demo01HelloworldApplicationTests     : No active profile set, falling back to default profiles: default
2020-07-28 16:21:27.777  INFO 16576 --- [           main] c.d.Demo01HelloworldApplicationTests     : Started Demo01HelloworldApplicationTests in 1.175 seconds (JVM running for 2.81)

Person{name='Danny', age=null, happy=false, birth=Sat Jul 11 00:00:00 CST 2020, maps={k1=v1, k2v2=}, lists=null, dog=Dog{name='cat', age=3}}

Process finished with exit code 0

We can find that the vlues in the configuration YAMl file has been assigned to the object.
If we only require a single value in the configuration file, we can use @Value, if there are many values to be assigned, then application.yml configuration file is the first choice.

Multiple Configuration

When developing programs, it usually requires multiple running enviornments, such as developing configuration, testing configuration.

We can use multi-document module in YAML.

For example, the YAML can be seperated by ---:


person:
  name: Danny
  happy: false
  birth: 2020/7/11
  maps: {k1: v1,k2 v2}
  list:
    - code
    - music
    - sport
  dog:
    name: cat
    age: 3
dog:
  name: cat
  age: 3
spring:
  profiles:
    active: dev      //this indicate that the executing configuration is "dev" part

 ---
person:
  name: Frank
  happy: true
  birth: 2020/7/22
  maps: {k1: v1,k2 v2}
  list:
    - Math
    - music
    - Reading
  dog:
    name: Dig
    age: 10
dog:
  name: Dig
  age: 10
spring:
  profiles: dev 

Then, the output is the following:

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

2020-07-28 17:04:00.623  INFO 19092 --- [           main] c.d.Demo01HelloworldApplicationTests     : Starting Demo01HelloworldApplicationTests on 举世无双的暗影精灵 with PID 19092 (started by pc in D:\zwh52\coursework\SpringBoot\Springbootdemo)
2020-07-28 17:04:00.624  INFO 19092 --- [           main] c.d.Demo01HelloworldApplicationTests     : The following profiles are active: dev
2020-07-28 17:04:01.012  INFO 19092 --- [           main] c.d.Demo01HelloworldApplicationTests     : Started Demo01HelloworldApplicationTests in 0.77 seconds (JVM running for 1.605)

Person{name='Frank', age=null, happy=true, birth=Wed Jul 22 00:00:00 CST 2020, maps={k1=v1, k2v2=}, lists=null, dog=Dog{name='Dig', age=10}}
Dog{name='Dig', age=10}


Process finished with exit code 0

The principle of autoConfiguration:

  1. SpringBoot will load huge amount of autoConfigration classes.
  2. We can check if the function we need is in default autoConfiguration classes.
  3. If the componet we need is in the classes, we do not need to configurate the component mannully.
  4. When adding components in the autoConfigurated classes, it will obtain attributes in the properties classes. We only need to point out the properties of the values of these properties.

xxxAutoConfiguration: auto-generated configuration class.

xxxProperties: The relating attributes in the encapsulated configuration files.

Injecting Property Values

Basically, once the application.properties or other customized application.properties has been loaded, you can inject values with the placeholder ${}.

In the main application where you run your SpringApplication, you can inject them easily with @Value("${<some-expression>}"). For example:

inside application.properties:

app.my.name=jason

then in your main application:

@Value("${app.my.name}")
private String appName;

However, in some other places, besides the main application, you might need to specify your application.properties file again before injecting the @Value. For example, in a @Configuration file at some other place in your project hierarchy:

@Configuration
@PropertySource("classpath:application.properties")
public class MainConfig {
    @Bean
    public ProfileManager profileManager(@Autowired Environment env, @Value("${app.testname}") String s) {
        return new ProfileManager(env,s);
    }
}

You can also use this to calculate expressions, which will require #{}instead of ${} for @Value(). For example:

@Value(#{app.my.age*2})
private int age;
Binding with a Customized yml or properties file

You can also also specify a customized properties file for constructor injection or property bindings. The basic annotations and syntax are the same as above, except that you need to specify that customized yml or properties file with @PropertySource(). For example:

@PropertySource(value="classpath: customizedPropertyFile")
@ConfigurationProperties(prefix="person1")
public class Person
    ...

SpringBoot Features

The SpringApplication class provides a convenient way to bootstrap a Spring application that is started from a main() method. In many situations, you can delegate to the static SpringApplication.run method, as shown in the following example:

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

When your application starts, you should see something similar to the following output:

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

2020-06-16 15:35:35.216  INFO 47936 --- [  restartedMain] App                                      : Starting App on XY-Laptop with PID 47936 (E:\Maven Workspace\testSpringBoot\target\classes started by 26238 in E:\Maven Workspace\testSpringBoot)
2020-06-16 15:35:35.218  INFO 47936 --- [  restartedMain] App                                      : No active profile set, falling back to default profiles: default
2020-06-16 15:35:35.248  INFO 47936 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2020-06-16 15:35:35.248  INFO 47936 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2020-06-16 15:35:36.345  INFO 47936 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-06-16 15:35:36.351  INFO 47936 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-06-16 15:35:36.351  INFO 47936 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.35]
2020-06-16 15:35:36.399  INFO 47936 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-06-16 15:35:36.399  INFO 47936 --- [  restartedMain] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1151 ms
2020-06-16 15:35:36.504  INFO 47936 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-06-16 15:35:36.588  INFO 47936 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2020-06-16 15:35:36.623  INFO 47936 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-06-16 15:35:36.630  INFO 47936 --- [  restartedMain] App                                      : Started App in 1.652 seconds (JVM running for 1.947)

Startup Failures

If your application fails to start, registered FailureAnalyzers get a chance to provide a dedicated error message and a concrete action to fix the problem. For instance, if you start a web application on port 8080 and that port is already in use, you should see something similar to the following message:


***************************
APPLICATION FAILED TO START
***************************
Description:
Embedded servlet container failed to start. Port 8080 was already in use.
Action:
Identify and stop the process that's listening on port 8080 or configure this
application to listen on another port.

If no failure analyzers are able to handle the exception, you can still display the full conditions report to better understand what went wrong. To do so, you need to enable the debug property or enable DEBUG logging for org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener.

For instance, if you are running your application by using java -jar, you can enable the debug
property as follows:

$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug

SpringBoot Web

Spring Boot is well suited for web application development. You can create a self-contained HTTP server by using embedded Tomcat, Jetty, Undertow, or Netty. Most web applications use the springboot-starter-web module to get up and running quickly. You can also choose to build reactive web applications by using the spring-boot-starter-webflux module.

Spring Web MVC Framework

The Spring Web MVC framework (often referred to as simply “Spring MVC”) is a rich “model view controller” web framework. Spring MVC lets you create special @Controller or @RestController beans to handle incoming HTTP requests (@Controller would be returning data that is being rendered by view, and @RestController would be returning raw data). Methods in your controller are mapped to HTTP by using @RequestMapping annotations.

The following code shows a typical @RestController that serves JSON data (by default):

@RestController
@RequestMapping(value="/users")
public class MyRestController {
	@RequestMapping(value="/{user}", method=RequestMethod.GET)
	public User getUser(@PathVariable Long user) {	// objects returned are turned into JSON format
		// ...
	}

	@RequestMapping(value="/{user}/customers", method=RequestMethod.GET)
	List<Customer> getUserCustomers(@PathVariable Long user) {
		// ...
	}

	@RequestMapping(value="/{user}", method=RequestMethod.DELETE)
	public User deleteUser(@PathVariable Long user) {
		// ...
	}
}

Spring MVC is part of the core Spring Framework, and detailed information is available in the reference documentation. There are also several guides that cover Spring MVC available at spring.io/guides.

Spring Boot Framework

Since Spring Boot has all those AutoConfiguration classes doing the configuration work for us, it is much simpler and faster for us to develop a web application using Spring Boot. In summary, all we need to do is:

  • Create a Spring Boot project (if you use Spring Initialzr, you will see that it is based on Spring Boot) with your desired dependencies
  • Spring Boot will load all those AutoConfiguration files, which you can further customize using application.properties or application.yml
    Write your own program
  • The most important step is to understand the mechanism behind AutoConfiguration, which uses the xxxAutoConfiguration classes that has properties injected (identified with a certain prefix).

Spring Boot Web Application Project Structure

WebJars

WebJars is simply taking the concept of a JAR and applying it to client-side libraries or resources. For example, the jQuery library may be packaged as a JAR and made available to your Spring MVC application. There are several benefits to using WebJars, including support for Java build tools such as Gradle and Maven.

For Spring Boot to load and later package your web contents correctly, you need to add your contents at a correct place. If you look into your WebMVCAutoConfiguration class, you will see the following method:

public void addResourceHandlers(ResourceHandlerRegistry registry) {
    if (!this.resourceProperties.isAddMappings()) {
        logger.debug("Default resource handling disabled");
    } else {
        Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
        CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
        if (!registry.hasMappingForPattern("/webjars/**")) {
            this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[] "/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
        }

        String staticPathPattern = this.mvcProperties.getStaticPathPattern();
        if (!registry.hasMappingForPattern(staticPathPattern)) {
            this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
        }

    }
}

So you see that all your web contents need to be placed in classpath:/META-INF/resources/webjars/ directory. This means that within your project, any file stored under /META-INF/resources/webjars/ can be visited by localhost:<yourPort>/webjars/<filePath>

For example, on the https://www.webjars.org/ you can choose which webjars to import into your project by copying the following to your pom file.

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>bootstrap</artifactId>
    <version>4.0.0</version>
</dependency>

Then in your external dependency, you can see that it also has the structure mentioned above, and you can visit its resources with localhost:8080/webjars/bootstrap/4.0.0/webjars-requirejs.js, for example. Then you will see that js file displayed:

/*global requirejs */

// Ensure any request for this webjar brings in jQuery.
requirejs.config({
  paths: { 
    "bootstrap": webjars.path("bootstrap", "js/bootstrap"),
    "bootstrap-css": webjars.path("bootstrap", "css/bootstrap")  
  },
  shim: { "bootstrap": [ "jquery" ] }
});

Static contents

In the same method where you find those webjar structure, you can also find where you should store your static contents:

String staticPathPattern = this.mvcProperties.getStaticPathPattern();
                if (!registry.hasMappingForPattern(staticPathPattern)) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

which finds your resource under the following directories:

"classpath:/META-INF/resources/", 
"classpath:/resources/", 
"classpath:/static/", 
"classpath:/public/"
"/" (project root path)

This means that if a request is not handled, you will be redirected to the static files under those locations.

For example, if you have an html page under the following directory:

hrmlpage

Then you can visit the html by localhost:8080/signin/index.html.

Welcome Page

Welcome page is basically the home page of your application. Spring Boot also has a default mapping defined in the WebMvcAutoConfiguration class:

@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
    WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
    welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
    welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
    return welcomePageHandlerMapping;
}

This in the end will look for index.html below all static content directories mentioned above, and maps to /.**

For example, if you have the following structure:

html

Then you can visit this index.html by localhost:8080/

Configure Your Web Properties

If you want to customize those locations, you can also use the spring.resources.xxx to modify the default paths scanned.

This works because in the ResoucrProperties class, Spring Boot defines locations for scanning static resources as shown below:

@ConfigurationProperties(
    prefix = "spring.resources",
    ignoreUnknownFields = false
)
public class ResourceProperties {
    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};

This means you can change those locations by specifying in your application.properties or applications.yml:

spring.resources.static-locations=classpath:/hello/, classpath:/example

Banner page and Web icon cumstomization

There are four static resources :

  • public
  • static
  • template
  • resources

You can put your index.html in either of these files.

To set customized web icon, you can put your onw ico in the public resource, Then, set the spring.mvc.favicon.enable=false in the application.properties.

Importing Thymeleaf

Since we are using Spring Boot with Maven, it is easy to include thymeleaf into your project. If you have already inherited the parent spring-boot-starter, then you just need to include the following dependency in your pom:

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

However, this uses the version 2.3.1 (specified in the parent pom). It is recommended to use thymeleaf 3 or above for more functionalities. To do this, you need to configure the properties in your pom.

<properties>
    <!-- This is how you change your Thymeleaf version -->
	<thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
    <thymeleaf-layout-dialect.version>2.1.1</thymeleaf-layout-dialect.version>
</properties>

Using Thymeleaf

The simplest example of using Thymeleaf would be to return an html page upon a request.

If we look into the ThymeleafProperties class (located in SpringBootAutoConfigure jar, under the folder thymeleaf), you will see:

@ConfigurationProperties(
    prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
    private static final Charset DEFAULT_ENCODING;
    public static final String DEFAULT_PREFIX = "classpath:/templates/";
    public static final String DEFAULT_SUFFIX = ".html";
    private boolean checkTemplate = true;
    private boolean checkTemplateLocation = true;
    private String prefix = "classpath:/templates/";
    private String suffix = ".html";
    private String mode = "HTML";
    ...

where

public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";

means that Thymeleaf scans through classpath:/templates/ for files ending with .html to be rendered.

Now, to hand you back a html page based on request using Thymeleaf, all you need to do is add a html page with the same return result as your html in your templates folder:

For example, if you have:

structure
Then your handler could look like:

@Controller
public class HTMLRequests {
    @RequestMapping("/getHtmlPage")
    public String testHTMLRequest(){
        return "request1";  // this has to be the same as the html file name
    }
}
  • Note:
    Now you should not use a @RestController, since it will automatically use the @ResponceBody which will render the page by Spring Boot itself instead of by Thymeleaf

For more information, you can follow the official thymeleaf guide.

  1. th:xxx

    If you place th: inside any html tag, where could be any HTML property (including text, class, id, etc.), then Thymeleaf will replace the original value with the value you specified. For example, you can replace the text appearing in a div with:

    <!-- Value placed would be parsed as a key, whose value you need to specifiy in your Handler method -->
    <div th:text="${Hello}">
        Original Text
    </div>
    

    and the corresponding Java class could look like:

@Controller
public class HTMLRequests {
@RequestMapping("/getHtmlPage")
public String testHTMLRequest(Map<String, String> map1){
map1.put(“Hello”,“Value Retrieved from key Hello”); // the value will be retrieved

    return "request1";  // this tells you which html file to return
}

}
```
2. Precendence

Since there is no notion of code precedence in html, if we specified multiple th:xxx within the same tag, collision will happen. To solve this, Thymeleaf defines its own precedence rule:
![presence RUle](https://jasonyux.github.io/2020/06/29/SpringBoot-Manual/thymeleaf-precedence.png)
  1. Thymeleaf Expressions

    • Simple expressions:
      • Variable Expressions: ${…}
        • can be used to read/store objects, and invoking certain methods on them
      • Selection Variable Expressions: *{…}
        • mainly used in combination with th:object, which stores an object in the current scope
        • then using *{…} will select/read a certain attribute of that stored object
      • Message Expressions: #{…}
        • used for internationalization
      • Link URL Expressions: @{…}
        • used for generating dynamic URL addresses
        • for example:
        <!-- Will produce 'http://localhost:8080/gtvg/order/details?orderId=3' (plus rewriting) -->
        <a href="details.html" th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view</a>
        
        <!-- Will produce '/gtvg/order/details?orderId=3' (plus rewriting) -->
        <a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>
        
      • Fragment Expressions: ~{…}
        • this will be talked about later
    • Literals:
      • Text literals: ‘one text’ , ‘Another one!’ ,…
      • Number literals: 0 , 34 , 3.0 , 12.3 ,…
      • Boolean literals: true , false
      • Null literal: null
      • Literal tokens: one , sometext , main ,…
    • Text operations:
      • String concatenation: +
      • Literal substitutions: |The name is ${name}|
    • Arithmetic operations:
      • Binary operators: + , - , * , / , %
      • Minus sign (unary operator): -
    • Boolean operations:
      • Binary operators: and , or
      • Boolean negation (unary operator): ! , not
    • Comparisons and equality:
      • Comparators: > , < , >= , <= ( gt , lt , ge , le )
      • Equality operators: == , != ( eq , ne )
    • Conditional operators:
      • If-then: (if) ? (then)
      • If-then-else: (if) ? (then) : (else)
        • same as Java tertiary operation
      • Default: (value) ?: (defaultvalue)
    • Special tokens:
      • No-Operation: _

    (For more information, please visit Chapter 4 of the Thymeleaf Documentation)

    Example:

    In your Java program, you can have:

    @Controller
    public class HTMLRequests {
        @RequestMapping("/getHtmlPage")
        public String testHTMLRequest(Map<String, String> map1, Map<String, Object> map2){
            map1.put("Hello","<h3>Value Retrieved from key Hello with h3 heading<h3>");
    
            String[] names = {"jason","michael","bowen"};
            List users = Arrays.asList(names);
            map2.put("Users",users);
            return "request1";
        }
    }
    

    In your html code, you can have:

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">    <!-- Adding this line enables syntax correction/suggestion -->
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>Test Request</h1>
        <p> A paragraph here </p>
        <!-- th:text configures/replaces the text appearing in the div to display value that maps to key=hello -->
        <!-- th:utext does not translate html element tags, which means if you had h1 tag in your value, it will be displayed as h1 -->
        <div th:utext="${Hello}">Original text</div>
        <hr/>
    
        <!-- This for each will generate multiple h5 tags -->
        <h5 th:text="${user}" th:each="user:${Users}"></h5>
        <hr/>
    
        <h5>
            <span th:each="user:${Users}">[[${user}]] </span>
        </h5>
    
    </body>
    </html>
    

    where

    • th:each can be seen as a for loop iteration, that does the work of for element: iterable.
    • [[ ] ] i s t h e i n l i n e v e r s i o n o f t h : t e x t = {}]] is the inline version of th:text= ]]istheinlineversionofth:text={}. [( ) ] i s t h e i n l i n e v e r s i o n o f t h : u t e x t = " {})] is the inline version of th:utext=" )]istheinlineversionofth:utext="{}"

Internalization

To enable your website to show contents in different languages based on users’ preferences (e.g. browser language used), you need to use internationalization(i18n), which is supported by Spring Boot. (In Spring MVC, this is configured by MessageResouce class. However, in Spring Boot, it is configured automatically with MessageSourceAutoConfiguration.)

In summary, you need to do the following steps:

  • Create a new folder under your resource folder, in which you will store all your internationalization properties file.

  • Create properties file in the format of <xxx>.properties, which will be used as the default properties file for that specific page xxx (for example).

  • Create other properties file in the format of <xxx>_<language>_<CountryCode>.properties. In this way, IntelliJ will recognize them, knowing that you are doing internationalization.

  • Now, since IntelliJ recognized them as internationalization files, you can use the Resource Bundle option when editing your properties file.

  • After configuring your properties file, you need to specify the base path (e.g. a property under the location resources/i18n/login_en_US.properties have the base path of i18n.login ) of your properties file with spring.messages.basename=<yourBasePath> in your application.properties.

  • Finally, you just need to go to your html page and use the thmeleaf messages expression #{...} (for example, if you had a property named login.title=... in your login_en_US.properties file, you should use #{login.title} to render your message expression text automatically based on your browser language.

For example:

if you have done step 1-4 correctly, you should be working like this:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n87wQVEG-1596166376545)(https://jasonyux.github.io/2020/06/29/SpringBoot-Manual/interationalization-example.png)]

Internalization Property Files

Note:

  • If you used Chinese in your properties files, and you get unreadable codes, you might need to change your decoding to enable ASCII conversion. For example, you can try the following:

text encoding

Text Encoding Setting

If you want to achieve the language swapping by a button on your page, you need to use the LocaleResolver class (also inside the MessageResouceAutoConfiguration class).

By default, this works by getting the section Accept-Language in the request header when you send your html request. To override this behavior, you need to write your own LocaleResolver class.

For example,

firstly, in your html page, you would have a button that creates those request with language:

<!-- this will be parsed as index.html?l=zh_CN, where index.html would be this same page -->
<... th:href="@{/index.html(l="zh_CN")}">中文</...>
<... th:href="@{/index.html(l="en_US")}">English</...>

In your MyLocaleResolver class, you can write:

public class MyLocaleResolver implements LocaleResolver{
    @Override
    public Locale resolveLocale(HttpServletRequest request){
        String lang = request.getParameter("l"); // getting the information l=zh_Ch from the request, for example
        Locale locale = Locale.getDefault(); // if there is none, then gets the default Locale information
        if(!StringUtils.isEmpty(l)){
            String[] split = l.split("_"); // gets the language and country code
            locale = new Locale(split[0]. split[1]);
        }
        return locale;
    }
    
    @Override 
    public void setLocale(...){
        ...
    }
}

Add this component to your application as a bean. This is because the Spring Boot LocaleResolver is injected with the condition: @ConditionalOnMissingBean, meaning that if we injected this bean, then Spring Boot’s default resolver will not be activated:

// in one of your `@Configuration` class, for example
@Bean
public LocaleResolver localeResolver(){
    return new MyLocaleResolver();
}

Sending and Handling Post Request
To handle a user login, for example, you need to do two parts (in abstract).

First, in your HTML page, you need to send a request (th:action="@{<xxx>}") with your form, in which you have each field that you need to be set with a specific name=xxx attribute.

Then, you add a handler to with PostController() to map to that request, and gets the value in those fields with @RequestParam("<xxx>") String xxx.
For example:

In your html page, you can have:

<form class="..." action="..." th:action="@{/user-login}" method="post">
    ...
    <input type="..." class="..." placeholder="..." name="username">
    <input type="..." class="..." placeholder="..." name="password">
    ...
</form>

In your Java class, you can have:

@Controller
public class LoginController{
    // same as @RequestMapping(method=RequestMethod.POST)
    @PostMapping(value="/user-login")
    public String login(@RequestParam("username") String username,
                       @RequestParam("password") String password){
        ... // your logic to check those username and passwords
        return "dashboard"	// the page in templates folder that you want to show to logged in users
    }
}

Note:

  • If hot swapping is not working (assuming you have enabled it) when you changed those static/templates html code, you should try:
    • add the line spring.thymeleaf.cache=false in your application.properties file
    • use Ctrl+F9 or manually click the build button to rebuild your project

If you want to add the functionality of popping up red text in your html page with Login Failed when your user failed the authentication, you can use the th:if functionality with some small changes to your controller code:

In your controller:

@Controller
public class LoginController{
    // same as @RequestMapping(method=RequestMethod.POST)
    @PostMapping(value="/user-login")
    public String login(@RequestParam("username") String username,
                       @RequestParam("password") String password
                       Map<String, String> errmsg){
        ... // your logic to check those username and passwords
        if(failed to authenticate){
            errmsg.put("msg","Login Failed");
            return "login" // your original page
        }
        return "dashboard"	// the page in templates folder that you want to show to logged in users
    }
}

Then in your html code, you can have:

<!-- For example, you can place in inside the form you use to submit login information -->
<p style="color: red" th:text="${msg}" th:if="not #strings.isEmpty(msg)"></p>

Spring Boot MVC Extensions

Spring Boot provides auto-configuration for Spring MVC that works well with most applications. The auto-configuration adds the following features on top of Spring’s defaults:

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
  • Support for serving static resources, including support for WebJars (covered before)).
  • Automatic registration of Converter, GenericConverter, and Formatter beans.
  • For example, converting an object to json format
  • Support for HttpMessageConverters.
  • For example, converts and handles http request
  • Automatic regis tration of MessageCodesResolver (covered later in this document).
  • Static index.html support (covered before)
  • Custom Favicon support
  • Automatic use of a ConfigurableWebBindingInitializer bean.

If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc.

If you want to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components.

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc, or alternatively add your own @Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc.

Example: Adding a ViewController

If you want to control a certain request to show the output of another request, you can use a ViewController to control the view of a page. However, by default Spring Boot does not have AutoConfiguration classes for that. Therefore, you would need to add your own ViewController by “adding your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc (mentioned above).

For instance, to map the request /request to request1 (which you specified as a html page configured by Thymeleaf), you need to write the configuration class:

@Configuration
public class myMVCExtensionConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/request").setViewName("request1");
    }
}
Mechanism

Since WebMvcAutoConfiguration is the AutoConfiguration class for Spring MVC, we can look into that class to understand those extension mechanisms. Within that class, you will see:

@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class})
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
    ...
}

Which imports WebMvcAutoConfiguration.EnableWebMvcConfiguration.class, and that class extends DelegatingWebMvcConfiguration by having the following signature:

public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {

Finally, in the parent class, you will see:

@Autowired(
    required = false
)	// since it is AutoWired, those configures are obtained from the IoC container
public void setConfigurers(List<WebMvcConfigurer> configurers) {
    if (!CollectionUtils.isEmpty(configurers)) {
        this.configurers.addWebMvcConfigurers(configurers);
    }

}

protected void addViewControllers(ViewControllerRegistry registry) {
    this.configurers.addViewControllers(registry);
}

And finally if we trace the configureViewResolvers method, we will see:

public void addViewControllers(ViewControllerRegistry registry) {
    Iterator var2 = this.delegates.iterator();

    while(var2.hasNext()) {
        WebMvcConfigurer delegate = (WebMvcConfigurer)var2.next();
        delegate.addViewControllers(registry);	// calls the method addViewControllers on each WebMvcConfigurer class
        										// and add them to the registry object
    }

}

This is why we needed to extend WebMvcConfigurer class for extending its functionality, add calling the method addViewControllers() in the above example to add our ViewController.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
I. Spring Boot Documentation 1. About the Documentation 2. Getting Help 3. First Steps 4. Working with Spring Boot 5. Learning about Spring Boot Features 6. Moving to Production 7. Advanced Topics II. Getting Started 8. Introducing Spring Boot 9. System Requirements 9.1. Servlet Containers 10. Installing Spring Boot 10.1. Installation Instructions for the Java Developer 10.1.1. Maven Installation 10.1.2. Gradle Installation 10.2. Installing the Spring Boot CLI 10.2.1. Manual Installation 10.2.2. Installation with SDKMAN! 10.2.3. OSX Homebrew Installation 10.2.4. MacPorts Installation 10.2.5. Command-line Completion 10.2.6. Quick-start Spring CLI Example 10.3. Upgrading from an Earlier Version of Spring Boot 11. Developing Your First Spring Boot Application 11.1. Creating the POM 11.2. Adding Classpath Dependencies 11.3. Writing the Code 11.3.1. The @RestController and @RequestMapping Annotations 11.3.2. The @EnableAutoConfiguration Annotation 11.3.3. The “main” Method 11.4. Running the Example 11.5. Creating an Executable Jar 12. What to Read Next III. Using Spring Boot 13. Build Systems 13.1. Dependency Management 13.2. Maven 13.2.1. Inheriting the Starter Parent 13.2.2. Using Spring Boot without the Parent POM 13.2.3. Using the Spring Boot Maven Plugin 13.3. Gradle 13.4. Ant 13.5. Starters 14. Structuring Your Code 14.1. Using the “default” Package 14.2. Locating the Main Application Class 15. Configuration Classes 15.1. Importing Additional Configuration Classes 15.2. Importing XML Configuration 16. Auto-configuration 16.1. Gradually Replacing Auto-configuration 16.2. Disabling Specific Auto-configuration Classes 17. Spring Beans and Dependency Injection 18. Using the @SpringBootApplication Annotation 19. Running Your Application 19.1. Running from an IDE 19.2. Running as a Packaged Application 19.3. Using the Maven Plugin 19.4. Using the Gradle Plugin 19.5. Hot Swapping 20. Developer Tools 20.1. Property Defaults 20.2. Automatic Restart 20.2.1. Logging changes in condition evaluation 20.2.2. Excluding Resources 20.2.3. Watching Additional Paths 20.2.4. Disabling Restart 20.2.5. Using a Trigger File 20.2.6. Customizing the Restart Classloader 20.2.7. Known Limitations 20.3. LiveReload 20.4. Global Settings 20.5. Remote Applications 20.5.1. Running the Remote Client Application 20.5.2. Remote Update 21. Packaging Your Application for Production 22. What to Read Next IV. Spring Boot features 23. SpringApplication 23.1. Startup Failure 23.2. Customizing the Banner 23.3. Customizing SpringApplication 23.4. Fluent Builder API 23.5. Application Events and Listeners 23.6. Web Environment 23.7. Accessing Application Arguments 23.8. Using the ApplicationRunner or CommandLineRunner 23.9. Application Exit 23.10. Admin Features 24. Externalized Configuration 24.1. Configuring Random Values 24.2. Accessing Command Line Properties 24.3. Application Property Files 24.4. Profile-specific Properties 24.5. Placeholders in Properties 24.6. Using YAML Instead of Properties 24.6.1. Loading YAML 24.6.2. Exposing YAML as Properties in the Spring Environment 24.6.3. Multi-profile YAML Documents 24.6.4. YAML Shortcomings 24.7. Type-safe Configuration Properties 24.7.1. Third-party Configuration 24.7.2. Relaxed Binding 24.7.3. Merging Complex Types 24.7.4. Properties Conversion Converting durations 24.7.5. @ConfigurationProperties Validation 24.7.6. @ConfigurationProperties vs. @Value 25. Profiles 25.1. Adding Active Profiles 25.2. Programmatically Setting Profiles 25.3. Profile-specific Configuration Files 26. Logging 26.1. Log Format 26.2. Console Output 26.2.1. Color-coded Output 26.3. File Output 26.4. Log Levels 26.5. Custom Log Configuration 26.6. Logback Extensions 26.6.1. Profile-specific Configuration 26.6.2. Environment Properties 27. Developing Web Applications 27.1. The “Spring Web MVC Framework” 27.1.1. Spring MVC Auto-configuration 27.1.2. HttpMessageConverters 27.1.3. Custom JSON Serializers and Deserializers 27.1.4. MessageCodesResolver 27.1.5. Static Content 27.1.6. Welcome Page 27.1.7. Custom Favicon 27.1.8. Path Matching and Content Negotiation 27.1.9. ConfigurableWebBindingInitializer 27.1.10. Template Engines 27.1.11. Error Handling Custom Error Pages Mapping Error Pages outside of Spring MVC 27.1.12. Spring HATEOAS 27.1.13. CORS Support 27.2. The “Spring WebFlux Framework” 27.2.1. Spring WebFlux Auto-configuration 27.2.2. HTTP Codecs with HttpMessageReaders and HttpMessageWriters 27.2.3. Static Content 27.2.4. Template Engines 27.2.5. Error Handling Custom Error Pages 27.2.6. Web Filters 27.3. JAX-RS and Jersey 27.4. Embedded Servlet Container Support 27.4.1. Servlets, Filters, and listeners Registering Servlets, Filters, and Listeners as Spring Beans 27.4.2. Servlet Context Initialization Scanning for Servlets, Filters, and listeners 27.4.3. The ServletWebServerApplicationContext 27.4.4. Customizing Embedded Servlet Containers Programmatic Customization Customizing ConfigurableServletWebServerFactory Directly 27.4.5. JSP Limitations 28. Security 28.1. MVC Security 28.2. WebFlux Security 28.3. OAuth2 28.3.1. Client 28.3.2. Server 28.4. Actuator Security 28.4.1. Cross Site Request Forgery Protection 29. Working with SQL Databases 29.1. Configure a DataSource 29.1.1. Embedded Database Support 29.1.2. Connection to a Production Database 29.1.3. Connection to a JNDI DataSource 29.2. Using JdbcTemplate 29.3. JPA and “Spring Data” 29.3.1. Entity Classes 29.3.2. Spring Data JPA Repositories 29.3.3. Creating and Dropping JPA Databases 29.3.4. Open EntityManager in View 29.4. Using H2’s Web Console 29.4.1. Changing the H2 Console’s Path 29.5. Using jOOQ 29.5.1. Code Generation 29.5.2. Using DSLContext 29.5.3. jOOQ SQL Dialect 29.5.4. Customizing jOOQ 30. Working with NoSQL Technologies 30.1. Redis 30.1.1. Connecting to Redis 30.2. MongoDB 30.2.1. Connecting to a MongoDB Database 30.2.2. MongoTemplate 30.2.3. Spring Data MongoDB Repositories 30.2.4. Embedded Mongo 30.3. Neo4j 30.3.1. Connecting to a Neo4j Database 30.3.2. Using the Embedded Mode 30.3.3. Neo4jSession 30.3.4. Spring Data Neo4j Repositories 30.3.5. Repository Example 30.4. Gemfire 30.5. Solr 30.5.1. Connecting to Solr 30.5.2. Spring Data Solr Repositories 30.6. Elasticsearch 30.6.1. Connecting to Elasticsearch by Using Jest 30.6.2. Connecting to Elasticsearch by Using Spring Data 30.6.3. Spring Data Elasticsearch Repositories 30.7. Cassandra 30.7.1. Connecting to Cassandra 30.7.2. Spring Data Cassandra Repositories 30.8. Couchbase 30.8.1. Connecting to Couchbase 30.8.2. Spring Data Couchbase Repositories 30.9. LDAP 30.9.1. Connecting to an LDAP Server 30.9.2. Spring Data LDAP Repositories 30.9.3. Embedded In-memory LDAP Server 30.10. InfluxDB 30.10.1. Connecting to InfluxDB 31. Caching 31.1. Supported Cache Providers 31.1.1. Generic 31.1.2. JCache (JSR-107) 31.1.3. EhCache 2.x 31.1.4. Hazelcast 31.1.5. Infinispan 31.1.6. Couchbase 31.1.7. Redis 31.1.8. Caffeine 31.1.9. Simple 31.1.10. None 32. Messaging 32.1. JMS 32.1.1. ActiveMQ Support 32.1.2. Artemis Support 32.1.3. Using a JNDI ConnectionFactory 32.1.4. Sending a Message 32.1.5. Receiving a Message 32.2. AMQP 32.2.1. RabbitMQ support 32.2.2. Sending a Message 32.2.3. Receiving a Message 32.3. Apache Kafka Support 32.3.1. Sending a Message 32.3.2. Receiving a Message 32.3.3. Additional Kafka Properties 33. Calling REST Services with RestTemplate 33.1. RestTemplate Customization 34. Calling REST Services with WebClient 34.1. WebClient Customization 35. Validation 36. Sending Email 37. Distributed Transactions with JTA 37.1. Using an Atomikos Transaction Manager 37.2. Using a Bitronix Transaction Manager 37.3. Using a Narayana Transaction Manager 37.4. Using a Java EE Managed Transaction Manager 37.5. Mixing XA and Non-XA JMS Connections 37.6. Supporting an Alternative Embedded Transaction Manager 38. Hazelcast 39. Quartz Scheduler 40. Spring Integration 41. Spring Session 42. Monitoring and Management over JMX 43. Testing 43.1. Test Scope Dependencies 43.2. Testing Spring Applications 43.3. Testing Spring Boot Applications 43.3.1. Detecting Web Application Type 43.3.2. Detecting Test Configuration 43.3.3. Excluding Test Configuration 43.3.4. Testing with a running server 43.3.5. Using JMX 43.3.6. Mocking and Spying Beans 43.3.7. Auto-configured Tests 43.3.8. Auto-configured JSON Tests 43.3.9. Auto-configured Spring MVC Tests 43.3.10. Auto-configured Spring WebFlux Tests 43.3.11. Auto-configured Data JPA Tests 43.3.12. Auto-configured JDBC Tests 43.3.13. Auto-configured jOOQ Tests 43.3.14. Auto-configured Data MongoDB Tests 43.3.15. Auto-configured Data Neo4j Tests 43.3.16. Auto-configured Data Redis Tests 43.3.17. Auto-configured Data LDAP Tests 43.3.18. Auto-configured REST Clients 43.3.19. Auto-configured Spring REST Docs Tests Auto-configured Spring REST Docs Tests with Mock MVC Auto-configured Spring REST Docs Tests with REST Assured 43.3.20. User Configuration and Slicing 43.3.21. Using Spock to Test Spring Boot Applications 43.4. Test Utilities 43.4.1. ConfigFileApplicationContextInitializer 43.4.2. TestPropertyValues 43.4.3. OutputCapture 43.4.4. TestRestTemplate 44. WebSockets 45. Web Services 46. Creating Your Own Auto-configuration 46.1. Understanding Auto-configured Beans 46.2. Locating Auto-configuration Candidates 46.3. Condition Annotations 46.3.1. Class Conditions 46.3.2. Bean Conditions 46.3.3. Property Conditions 46.3.4. Resource Conditions 46.3.5. Web Application Conditions 46.3.6. SpEL Expression Conditions 46.4. Testing your Auto-configuration 46.4.1. Simulating a Web Context 46.4.2. Overriding the Classpath 46.5. Creating Your Own Starter 46.5.1. Naming 46.5.2. autoconfigure Module 46.5.3. Starter Module 47. Kotlin support 47.1. Requirements 47.2. Null-safety 47.3. Kotlin API 47.3.1. runApplication 47.3.2. Extensions 47.4. Dependency management 47.5. @ConfigurationProperties 47.6. Testing 47.7. Resources 47.7.1. Further reading 47.7.2. Examples 48. What to Read Next V. Spring Boot Actuator: Production-ready features 49. Enabling Production-ready Features 50. Endpoints 50.1. Enabling Endpoints 50.2. Exposing Endpoints 50.3. Securing HTTP Endpoints 50.4. Configuring Endpoints 50.5. Hypermedia for Actuator Web Endpoints 50.6. Actuator Web Endpoint Paths 50.7. CORS Support 50.8. Implementing Custom Endpoints 50.8.1. Receiving Input Input type conversion 50.8.2. Custom Web Endpoints Web Endpoint Request Predicates Path HTTP method Consumes Produces Web Endpoint Response Status Web Endpoint Range Requests Web Endpoint Security 50.8.3. Servlet endpoints 50.8.4. Controller endpoints 50.9. Health Information 50.9.1. Auto-configured HealthIndicators 50.9.2. Writing Custom HealthIndicators 50.9.3. Reactive Health Indicators 50.9.4. Auto-configured ReactiveHealthIndicators 50.10. Application Information 50.10.1. Auto-configured InfoContributors 50.10.2. Custom Application Information 50.10.3. Git Commit Information 50.10.4. Build Information 50.10.5. Writing Custom InfoContributors 51. Monitoring and Management over HTTP 51.1. Customizing the Management Endpoint Paths 51.2. Customizing the Management Server Port 51.3. Configuring Management-specific SSL 51.4. Customizing the Management Server Address 51.5. Disabling HTTP Endpoints 52. Monitoring and Management over JMX 52.1. Customizing MBean Names 52.2. Disabling JMX Endpoints 52.3. Using Jolokia for JMX over HTTP 52.3.1. Customizing Jolokia 52.3.2. Disabling Jolokia 53. Loggers 53.1. Configure a Logger 54. Metrics 54.1. Getting started 54.2. Supported monitoring systems 54.2.1. Atlas 54.2.2. Datadog 54.2.3. Ganglia 54.2.4. Graphite 54.2.5. Influx 54.2.6. JMX 54.2.7. New Relic 54.2.8. Prometheus 54.2.9. SignalFx 54.2.10. Simple 54.2.11. StatsD 54.2.12. Wavefront 54.3. Supported Metrics 54.3.1. Spring MVC Metrics 54.3.2. Spring WebFlux Metrics 54.3.3. RestTemplate Metrics 54.3.4. Cache Metrics 54.3.5. DataSource Metrics 54.3.6. RabbitMQ Metrics 54.4. Registering custom metrics 54.5. Customizing individual metrics 54.5.1. Per-meter properties 54.6. Metrics endpoint 55. Auditing 56. HTTP Tracing 56.1. Custom HTTP tracing 57. Process Monitoring 57.1. Extending Configuration 57.2. Programmatically 58. Cloud Foundry Support 58.1. Disabling Extended Cloud Foundry Actuator Support 58.2. Cloud Foundry Self-signed Certificates 58.3. Custom context path 59. What to Read Next VI. Deploying Spring Boot Applications 60. Deploying to the Cloud 60.1. Cloud Foundry 60.1.1. Binding to Services 60.2. Heroku 60.3. OpenShift 60.4. Amazon Web Services (AWS) 60.4.1. AWS Elastic Beanstalk Using the Tomcat Platform Using the Java SE Platform 60.4.2. Summary 60.5. Boxfuse and Amazon Web Services 60.6. Google Cloud 61. Installing Spring Boot Applications 61.1. Supported Operating Systems 61.2. Unix/Linux Services 61.2.1. Installation as an init.d Service (System V) Securing an init.d Service 61.2.2. Installation as a systemd Service 61.2.3. Customizing the Startup Script Customizing the Start Script when It Is Written Customizing a Script When It Runs 61.3. Microsoft Windows Services 62. What to Read Next VII. Spring Boot CLI 63. Installing the CLI 64. Using the CLI 64.1. Running Applications with the CLI 64.1.1. Deduced “grab” Dependencies 64.1.2. Deduced “grab” Coordinates 64.1.3. Default Import Statements 64.1.4. Automatic Main Method 64.1.5. Custom Dependency Management 64.2. Applications with Multiple Source Files 64.3. Packaging Your Application 64.4. Initialize a New Project 64.5. Using the Embedded Shell 64.6. Adding Extensions to the CLI 65. Developing Applications with the Groovy Beans DSL 66. Configuring the CLI with settings.xml 67. What to Read Next VIII. Build tool plugins 68. Spring Boot Maven Plugin 68.1. Including the Plugin 68.2. Packaging Executable Jar and War Files 69. Spring Boot Gradle Plugin 70. Spring Boot AntLib Module 70.1. Spring Boot Ant Tasks 70.1.1. spring-boot:exejar 70.1.2. Examples 70.2. spring-boot:findmainclass 70.2.1. Examples 71. Supporting Other Build Systems 71.1. Repackaging Archives 71.2. Nested Libraries 71.3. Finding a Main Class 71.4. Example Repackage Implementation 72. What to Read Next IX. ‘How-to’ guides 73. Spring Boot Application 73.1. Create Your Own FailureAnalyzer 73.2. Troubleshoot Auto-configuration 73.3. Customize the Environment or ApplicationContext Before It Starts 73.4. Build an ApplicationContext Hierarchy (Adding a Parent or Root Context) 73.5. Create a Non-web Application 74. Properties and Configuration 74.1. Automatically Expand Properties at Build Time 74.1.1. Automatic Property Expansion Using Maven 74.1.2. Automatic Property Expansion Using Gradle 74.2. Externalize the Configuration of SpringApplication 74.3. Change the Location of External Properties of an Application 74.4. Use ‘Short’ Command Line Arguments 74.5. Use YAML for External Properties 74.6. Set the Active Spring Profiles 74.7. Change Configuration Depending on the Environment 74.8. Discover Built-in Options for External Properties 75. Embedded Web Servers 75.1. Use Another Web Server 75.2. Disabling the Web Server 75.3. Configure Jetty 75.4. Add a Servlet, Filter, or Listener to an Application 75.4.1. Add a Servlet, Filter, or Listener by Using a Spring Bean Disable Registration of a Servlet or Filter 75.4.2. Add Servlets, Filters, and Listeners by Using Classpath Scanning 75.5. Change the HTTP Port 75.6. Use a Random Unassigned HTTP Port 75.7. Discover the HTTP Port at Runtime 75.8. Configure SSL 75.9. Configure HTTP/2 75.9.1. HTTP/2 with Undertow 75.9.2. HTTP/2 with Jetty 75.9.3. HTTP/2 with Tomcat 75.10. Configure Access Logging 75.11. Running Behind a Front-end Proxy Server 75.11.1. Customize Tomcat’s Proxy Configuration 75.12. Configure Tomcat 75.13. Enable Multiple Connectors with Tomcat 75.14. Use Tomcat’s LegacyCookieProcessor 75.15. Configure Undertow 75.16. Enable Multiple Listeners with Undertow 75.17. Create WebSocket Endpoints Using @ServerEndpoint 75.18. Enable HTTP Response Compression 76. Spring MVC 76.1. Write a JSON REST Service 76.2. Write an XML REST Service 76.3. Customize the Jackson ObjectMapper 76.4. Customize the @ResponseBody Rendering 76.5. Handling Multipart File Uploads 76.6. Switch Off the Spring MVC DispatcherServlet 76.7. Switch off the Default MVC Configuration 76.8. Customize ViewResolvers 77. HTTP Clients 77.1. Configure RestTemplate to Use a Proxy 78. Logging 78.1. Configure Logback for Logging 78.1.1. Configure Logback for File-only Output 78.2. Configure Log4j for Logging 78.2.1. Use YAML or JSON to Configure Log4j 2 79. Data Access 79.1. Configure a Custom DataSource 79.2. Configure Two DataSources 79.3. Use Spring Data Repositories 79.4. Separate @Entity Definitions from Spring Configuration 79.5. Configure JPA Properties 79.6. Configure Hibernate Naming Strategy 79.7. Use a Custom EntityManagerFactory 79.8. Use Two EntityManagers 79.9. Use a Traditional persistence.xml File 79.10. Use Spring Data JPA and Mongo Repositories 79.11. Expose Spring Data Repositories as REST Endpoint 79.12. Configure a Component that is Used by JPA 79.13. Configure jOOQ with Two DataSources 80. Database Initialization 80.1. Initialize a Database Using JPA 80.2. Initialize a Database Using Hibernate 80.3. Initialize a Database 80.4. Initialize a Spring Batch Database 80.5. Use a Higher-level Database Migration Tool 80.5.1. Execute Flyway Database Migrations on Startup 80.5.2. Execute Liquibase Database Migrations on Startup 81. Messaging 81.1. Disable Transacted JMS Session 82. Batch Applications 82.1. Execute Spring Batch Jobs on Startup 83. Actuator 83.1. Change the HTTP Port or Address of the Actuator Endpoints 83.2. Customize the ‘whitelabel’ Error Page 84. Security 84.1. Switch off the Spring Boot Security Configuration 84.2. Change the UserDetailsService and Add User Accounts 84.3. Enable HTTPS When Running behind a Proxy Server 85. Hot Swapping 85.1. Reload Static Content 85.2. Reload Templates without Restarting the Container 85.2.1. Thymeleaf Templates 85.2.2. FreeMarker Templates 85.2.3. Groovy Templates 85.3. Fast Application Restarts 85.4. Reload Java Classes without Restarting the Container 86. Build 86.1. Generate Build Information 86.2. Generate Git Information 86.3. Customize Dependency Versions 86.4. Create an Executable JAR with Maven 86.5. Use a Spring Boot Application as a Dependency 86.6. Extract Specific Libraries When an Executable Jar Runs 86.7. Create a Non-executable JAR with Exclusions 86.8. Remote Debug a Spring Boot Application Started with Maven 86.9. Build an Executable Archive from Ant without Using spring-boot-antlib 87. Traditional Deployment 87.1. Create a Deployable War File 87.2. Convert an Existing Application to Spring Boot 87.3. Deploying a WAR to WebLogic 87.4. Use Jedis Instead of Lettuce X. Appendices A. Common application properties B. Configuration Metadata B.1. Metadata Format B.1.1. Group Attributes B.1.2. Property Attributes B.1.3. Hint Attributes B.1.4. Repeated Metadata Items B.2. Providing Manual Hints B.2.1. Value Hint B.2.2. Value Providers Any Class Reference Handle As Logger Name Spring Bean Reference Spring Profile Name B.3. Generating Your Own Metadata by Using the Annotation Processor B.3.1. Nested Properties B.3.2. Adding Additional Metadata C. Auto-configuration classes C.1. From the “spring-boot-autoconfigure” module C.2. From the “spring-boot-actuator-autoconfigure” module D. Test auto-configuration annotations E. The Executable Jar Format E.1. Nested JARs E.1.1. The Executable Jar File Structure E.1.2. The Executable War File Structure E.2. Spring Boot’s “JarFile” Class E.2.1. Compatibility with the Standard Java “JarFile” E.3. Launching Executable Jars E.3.1. Launcher Manifest E.3.2. Exploded Archives E.4. PropertiesLauncher Features E.5. Executable Jar Restrictions E.6. Alternative Single Jar Solutions F. Dependency versions
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值