This series of tutorials is based on my own experience with the SpringBoot2.x process.

1. Introduction to Spring Boot

Spring Boot is designed to simplify Spring application development. With conventions over configurations, just Run can create a standalone, production-grade application

  • Background:

    J2EE (such as Spring) is cumbersome in development, has many configurations, low development efficiency, responsible deployment processes, and is difficult to integrate with third-party technologies.

  • Solution:

    The era of “Spring Buckets” :

    Spring Boot → J2EE one-stop solution

    Spring Cloud → Distributed total solution

  • Advantages:

    Quickly create standalone Spring projects and integrate with mainstream frameworks

    With the embedded Servlet container, the application does not need to be packaged in a WAR

    The starters automatically rely on version control

    Extensive automatic configuration, simplified development, and the ability to modify default property values

    Out of the box, no XML configuration, no code generation

    Runtime application monitoring for production environments

    Natural integration with cloud computing

Conclusion:

  • A framework to simplify Spring application development;
  • A major integration of the entire Spring technology stack;
  • J2EE development of one-stop solution;

2. Micro services

  • 2014 was proposed by Martin Fowler
  • Microservices: Architectural Style (Service Miniaturization)
  • An application should be a set of small services; They can communicate with each other through HTTP.
  • Single application: ALL IN ONE
  • Microservices: Each functional element is ultimately a unit of software that can be independently replaced and upgraded;
  • Refer to the microservices documentation for details

Single application:

The service:

3. Environmental preparation

Development environment:

  • Jdk1.8: Spring Boot recommended JDK1.7 or higher; Java version “1.8.0 comes with _221”
  • Maven3.x: Maven version 3.3 or later; Apache maven — 3.6.1
  • IntelliJIDEA2019: IntelliJIDEA 2019.1.3×64
  • SpringBoot 2.2.1.RELEASE: 2.2.1;

Development configuration:

1. MAVEN Settings:

Add the following configuration to the Profiles TAB of Maven’s settings. XML configuration file to set the default compiled version of Maven to use JDK8 when creating projects

<profile>
<id>JDK - 1.8 -</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
Copy the code

2. IDEA setting:

Idea integration Maven:

Create Spring Boot HelloWorld

1. Start fast

First, we will create a unified Maven project to manage all the projects we will study in the future:

1. New projects

2. Select the Maven project

3. Fill in GroupId and ArtifactId

GroupId: com. Demo. Springboot

ArtifactId: SpringBoot – In – Action

5. Fill in the project name and project path

6. Create an empty Maven project and select allow automatic import

7. Delete unnecessary directories

Just keep a pom.xml file and add springBoot dependencies and packaging types to the POM file

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1. RELEASE</version>
</parent>
<packaging>pom</packaging>
Copy the code

Now start our Spring Boot HelloWorld project:

One function: the browser sends a Hello request, the server accepts and processes the request, and responds with a Hello World string.

1. Create a Maven project; (jar)

Create a new Module In the Springboot-in-Action project, select the Maven project and name it Spring-boot-01-HelloWorld

Import spring Boot-related dependencies

Because the SpringBoot dependencies are already imported into the parent POM

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1. RELEASE</version>
</parent>
Copy the code

So in the current POM, just import the spring-boot-starter-Web dependency:

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

The complete POM file is as follows:

<?xml version="1.0" encoding="UTF-8"? >
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>SpringBoot-In-Action</artifactId>
        <groupId>com.demo.springboot</groupId>
        <version>1.0 the SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-boot-01-helloworld</artifactId>

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

</project>
Copy the code

3. Write a main program; Start the Spring Boot application

/ * * *@SpringBootApplicationTo mark a main program class, indicating that this is a Spring Boot application */
@SpringBootApplication
public class HelloWorldMainApplication {
    public static void main(String[] args) {
        // The Spring application startsSpringApplication.run(HelloWorldMainApplication.class, args); }}Copy the code

4. Write related Controller and Service

For demonstration purposes, I create only the Controller class here, omitting the Service

@Controller
public class HelloController {

    @ResponseBody
    @RequestMapping("/hello")
    public String hello(a) {
        return "Hello World!"; }}Copy the code

5. Run the main program to test the effect

Selected HelloWorldMainApplication right click on the select Run… , or open HelloWorldMainApplication press the shortcut Ctrl + Shift + F10 to run the program, you can see the project start in port 8080:

In the browser to http://localhost:8080/hello you can see the normal returned to the Hello World.

At this point, our first Spring Boot project is complete.

6. Add: Simplify deployment

Add the following configuration to the POM file of the current project, spring-boot-01-HelloWorld

<! -- This plugin can package the application into an executable JAR package; -->
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
Copy the code

Then select the current POM file, right-click on it, and select Run Maven → Package to jar the application. Can see that the target folder to generate a called spring – the boot – 01 – the helloworld – 1.0 – the SNAPSHOT. Jar jar file, we can directly on the command line using Java – jar XXX. The jar command to execute, Starts in the browser to http://localhost:8080/hello can see normal returned to the Hello World. To end the program, close the command line window.

Consider: Why can our packaged programs be deployed directly from the command line using Java JAR commands?

With doubt, let us analysis the spring – the boot – 01 – the helloworld – 1.0 – the SNAPSHOT. Jar, we use the compressed file to open the spring – the boot – 01 – the helloworld – 1.0 – the SNAPSHOT. The jar, You can see the following directory structure:

If we open the boot-INF folder, there are two folders: classes and lib. The binary bytecode for our code is in the classes directory, and lib is where we can see all the JARS that our project depends on. Most importantly, our project is a Web project. You can see the dependent embedded Tomcat JAR package, which is the key for our project to deploy independently:

The meta-inf directory stores the pom files of the project, and the org directory stores the springframework code.

5, Hello World

1. POM files

1. Parent project

The dependency path is shown below:

Spring – the boot – 01 – the helloworld pom:

<parent>
    <artifactId>SpringBoot-In-Action</artifactId>
    <groupId>com.demo.springboot</groupId>
    <version>1.0 the SNAPSHOT</version>
</parent>
Copy the code

Its parent project is the POM In SpringBoot-in-Action:

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

<packaging>pom</packaging>

<groupId>com.demo.springboot</groupId>
<artifactId>SpringBoot-In-Action</artifactId>
<version>1.0 the SNAPSHOT</version>

<modules>
    <module>spring-boot-01-helloworld</module>
</modules>
Copy the code

while

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1. RELEASE</version>
</parent>
Copy the code

The parent POM is spring-boot-starter-parent-2.1.1.release.pom:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.2.1. RELEASE</version>
    <relativePath>. /.. /spring-boot-dependencies</relativePath>
</parent>
<artifactId>spring-boot-starter-parent</artifactId>
Copy the code

The parent pom is spring-boot-dependencies- 2.2.1.release.pom:

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.1. RELEASE</version>
<packaging>pom</packaging>As you can see in this POM, it is used to actually manage all the dependency versions in the Spring Boot application, defining each dependency version;Copy the code

Spring-boot-dependencies 2.x.lerese. pom can be a version arbitration center called Spring boot.

By default, we don’t need to write versions to import other dependencies later; (Of course, dependencies that are not managed in dependencies need to be declared.)

2. Import other dependencies

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

Spring-boot-starter-web: We can split it into spring-boot-starter and Web

  • Spring-boot-starter: indicates an initiator in the spring-boot scenario. Spring-boot-starter-web helps us import the components that our Web module depends on to function properly.

Spring-boot-starter-web: spring-boot-starter-web-2.1.1.release.pom: Spring-boot-starter-web-2.1.1.release.pom: Spring-boot-starter-web-2.1.1.release.pom: Spring-boot-starter-web-2.1.1.release.pom: Spring-boot-starter-web-2.1.1.release.pom: Spring-boot-starter-web-2.1.1.release.pom:

Spring Boot provides us with a starter POM that simplifies enterprise development for most scenarios. Once a starter POM is introduced for that scenario, most of the configuration of the relevant technology is eliminated (i.e., automatic configuration), simplifying our development. In many business scenarios, we will use beans that Spring Boot automatically configures for us. Meanwhile, Spring Boot has done strict testing and version control on the JARS that these scenarios depend on, so we don’t have to worry about the adaptation of jar versions.

There are many other such initiators in Spring Boot, and we can open the official documentation to see a description of the initiator:

Spring Boot extracts all of the functional scenarios into one specific starter, simply by introducing all of the dependencies related to those starter scenarios into the project. Import the scenario initiator for whatever functionality you want to use. Our general development also revolves around these starters.

2, Main program class (main entry class)

/ * * *@SpringBootApplicationTo annotate a main program class, indicating that this is a Spring Boot application and the project cannot start without this annotation */
@SpringBootApplication
public class HelloWorldMainApplication {

    public static void main(String[] args) {

        // The Spring application startsSpringApplication.run(HelloWorldMainApplication.class, args); }}Copy the code

1. @ SpringBootApplication

@SpringBootApplication: The SpringBoot application annotation indicates on a class that this class is the main configuration class of SpringBoot. SpringBoot runs the main method of this class to start the SpringBoot application.

Inside the @SpringBootApplication annotation, you can see that it is actually a composite annotation:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
Copy the code

2, @ SpringBootConfiguration

@springBootConfiguration: SpringBoot configuration class;

Function: marked on a class, indicating that this is a Spring Boot configuration class;

If you look inside @SpringBootConfiguration, it is annotated by Spring’s @Configuration annotation:

@Configuration
public @interface SpringBootConfiguration {
Copy the code

@configuration: The Configuration class annotates this annotation; Config class === config file;

Look inside @Configuration, which is annotated by Spring’s @Component annotation; The configuration class is actually a component in the container.

@Component
public @interface Configuration {
Copy the code

3, @ EnableAutoConfiguration

@enableAutoConfiguration: Enables the automatic configuration function

Spring Boot will automatically configure things that we used to configure in Spring. @enableAutoConfiguration tells SpringBoot to enable automatic configuration so that the automatic configuration takes effect.

Enter @enableAutoConfiguration and you will see the following code:

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
Copy the code

@autoConfigurationPackage: An automatic configurationpackage that scans the main configurationPackage (annotated by @SpringBootApplication) and all components in the following subpackages into the Spring container

If you go inside @Configuration, you can see that it is annotated by the @import annotation. Spring’s underlying annotation @import imports a component into the container; The imported component is specified by registrer.class;

@Import({Registrar.class})
public @interface AutoConfigurationPackage {
Copy the code

Registrar Static inner class The Registrar static inner class

static class Registrar implements ImportBeanDefinitionRegistrar.DeterminableImports {
    Registrar() {
    }
	// Register some Bean definition information for component import; Metadata: Annotated meta-information
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
    }

    public Set<Object> determineImports(AnnotationMetadata metadata) {
        return Collections.singleton(newAutoConfigurationPackages.PackageImport(metadata)); }}Copy the code

Let’s put a breakpoint in the code to see:

@ Import ({AutoConfigurationImportSelector. Class}) : XXX to container Import components

AutoConfigurationImportSelector: import the selector which components;

We entered the AutoConfigurationImportSelector can be seen in the following code:

// Return all components that need to be imported as full class names; These components are then added to the container
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
    if (!this.isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    } else {
        AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
        List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
        configurations = this.removeDuplicates(configurations);
        Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
        this.checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        configurations = this.filter(configurations, autoConfigurationMetadata);
        this.fireAutoConfigurationImportEvents(configurations, exclusions);
        return newAutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions); }}Copy the code

Return all components that need to be imported as full class names; These components are then added to the container. Namely AutoConfigurationImportSelector will give the container import very much in the automatic configuration of class (xxxAutoConfiguration); Import and configure all the components needed for the scenario into the container.

We can see the following result at the break point in the code:

With the auto-configuration class, we eliminate the need to manually write configuration injection components and so on.

Enter the code above the getCandidateConfigurations method, you can see the following code:

// Get the candidate configuration
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
    return configurations;
}
Copy the code

The code above is called SpringFactoriesLoader. LoadFactoryNames EnableAutoConfiguration. Class, this method, we can see in this method into the the following code:

public static List<String> loadFactoryNames(Class
        factoryType, @Nullable ClassLoader classLoader) {
    // Get the factory name
    String factoryTypeName = factoryType.getName();
    return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
    if(result ! =null) {
        return result;
    } else {
        try {
            // Use the classloader to get resources from the classpath "meta-INF /spring.factories"Enumeration<URL> urls = classLoader ! =null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
            LinkedMultiValueMap result = new LinkedMultiValueMap();

            while(urls.hasMoreElements()) {
                URL url = (URL)urls.nextElement();
                UrlResource resource = new UrlResource(url);
                // Take the properties profile from the acquired resource and treat the acquired resource as a properties profile
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                Iterator var6 = properties.entrySet().iterator();

                while(var6.hasNext()) { Entry<? ,? > entry = (Entry)var6.next();// Get factoryTypeName from the Properties file
                    String factoryTypeName = ((String)entry.getKey()).trim();
                    String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                    int var10 = var9.length;

                    for(int var11 = 0; var11 < var10; ++var11) {
                        String factoryImplementationName = var9[var11];
                        result.add(factoryTypeName, factoryImplementationName.trim());
                    }
                }
            }

            cache.put(classLoader, result);
            return result;
        } catch (IOException var13) {
            throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13); }}}Copy the code

Therefore, according to the above analysis, I know: Spring Boot obtains the values specified by EnableAutoConfiguration from the meta-INF/Spring. factories in the classpar. Help us with the automatic configuration. The automatic configuration classes in Spring Boot do all the things we used to configure ourselves in Spring.

Spring-boot-autoconfigure-2.1.1.release.jar (spring-boot-autoconfigure-x.x.x.release.jar) :

6. Use Spring Initializer to quickly create a Spring Boot project

1. IDEA: Use Spring Initializer to quickly create a project

All ides support quick creation of a Spring Boot project using Spring’s project creation wizard. Let’s look at how to quickly create a Spring Boot project in IDEA.

1, select File → New → Project or select the Project name from an existing Project and then New → Module:

2. Fill in basic information GroupID and ArtifactID

3. Select the modules we need to rely on

4. Click Finish, and the wizard will network to create the Spring Boot project

Looking at the Spring Boot project generated by default, we can see:

  • The main program has been generated, we just need to write our own logic
  • resourcesDirectory structure in folder:
    • staticSave all static resources: JS, CSS, images, etc.
    • templates: Save all the template pages (Spring Boot default JAR package uses embedded Tomcat, default does not support JSP pages), you can use the template engine (freemarker,thymeleafEtc.);
    • application.properties: Configuration file of the Spring Boot application. You can modify some default Settings, such as ports

We are com. Demo. Spring. The controller under the package after a HelloController to test our new project

The HelloController code is as follows:

// All methods of this class return data directly to the browser (if the object is converted to JSON data)
//@ResponseBody
//@Controller
// The above two lines are usually used in Spring projects
@RestController // Use this after Spring Boot and Spring4.2.x to simplify development, returning the interface of the RESTAPI specification
public class HelloController {
    @RequestMapping("/hello")
    public String hello(a){
        return "hello world quick!"; }}Copy the code

In the browser to http://localhost:8080/hello can get the following return effect:

2. Use your browser to visit https://start.spring.io/ to quickly create a project

After performing the above operations, the browser will automatically download a created project, which can be opened using IDEA.

That’s all for our Spring Boot quick start. Please check the source code for more details.

The source code:

SpringBoot-In-Action

  • spring-boot-01-helloworld

  • spring-boot-01-helloworld-quick