springBoot

An overview,

1. What is Spring Boot

Spring Boot is a sub-project of the Spring project, which is part of the same product as the well-known Spring-Framework:

Its primary purpose is to help developers build large Spring projects quickly and with minimal XML configuration, out of the box and up to speed, allowing developers to focus on business rather than configuration.

2. Features of Spring Boot

1. Automatic configuration: There is no need to worry about the integrated configuration of various frameworks, SpringBoot is all configured.

2. Starting dependencies: When we need to use a framework, we can directly add the launcher dependencies of the framework, and do not need to pay attention to the conflict and integration of JAR packages.

3. The purpose of

To simplify the initial setup and development of Spring applications.

  1. Provide a faster and broader entry experience for all Spring development.
  2. Zero configuration. No redundant code generation and XML mandatory configuration, follow “convention over configuration”
  3. Integrating the configuration of a large number of commonly used third-party libraries, Spring Boot applications provide these third-party libraries with almost zero configuration out of the box capabilities.
  4. Provides a range of non-functionality common to large projects, such as embedded servers.

4. Good

Simple, fast and convenient

Advantages of 5.

Using Java development programs, we have been plagued by bloated, troublesome. The process of building a project is quite complicated, and we need to consider many problems. The main problems are as follows:

  1. Complex configuration
  2. Messy dependency management

Spring Boot helps us solve this problem, we use Spring Boot development, do not need to pay attention to a variety of complex integration configuration, also do not need to pay attention to the dependencies and conflicts between the various libraries, Spring Boot has helped us integrate the configuration by default!

Helloworld for SpringBoot

1. The demand

Visit http://localhost:8080/hello outputs “Hello Spring Boot”

Step 3.

  1. Creating a Maven project

  2. Plus dependencies (SpringBoot parent project dependencies, Web launcher dependencies)

    <! -- Spring Boot parent project dependencies -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2. RELEASE</version>
    </parent>
    <! -- Web initiator -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    Copy the code

    Configuring the JDK Version

    <properties>
        <java.version>1.8</java.version>
    </properties>
    Copy the code

    Consider: why does the JDK version of the project change when we configure only one variable here?

    Because the JDK plug-in is already defined in the parent project, the ${java.version} variable value is read by default

  3. Write boot boot classes (the entry point for springBoot projects to run)

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class Application {
        public static void main(String[] args) { SpringApplication.run(Application.class,args); }}Copy the code
  4. Write processor Controller

    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    @RestController
    public class HelloController {
        @RequestMapping("/hello")
        public String sayHello(a){
            return "hello spring boot!!"; }}Copy the code
  5. Start the project

    Run the main method of the startup class

Problem 3.

1. Why do we not need to specify the version in initiator coordinates when adding initiators?

Answer: Because we specified the parent project, in spring-boot-starter-parent we already locked the version of the Jar package through Maven’s version, so we don’t need to specify it anymore.

2. Why do we just add an initiator dependency so that the project can run? Where do the Jar packages needed to run the project come from?

Answer: Because we added a dependency to the launcher, it has integrated the necessary packages it needs to run into the launcher, relying on our project through Maven’s dependency transitivity.

4. Details about the configuration file

Springboot supports two types of configuration files

  • Properties Property configuration file
  • Yaml configuration file

The configuration file must be placed in the project’s classloading directory, and the name must begin with Application

The SpringBoot project automatically loads these configuration files at runtime.

Port can be found in the meta-INF directory of spring-boot-autoconfigure-2.2.2.rellease. The default port is 8080.

Why can I create the application.properties file under Resources?

Let’s look at springBoot’s boot dependencies

Hold down the CTRL key and go spring-boot-starter-parent

You can see this in the parent project

<build>
    <resources>
    	<resource>
            <filtering>true</filtering>
            <directory>${basedir}/src/main/resources</directory>
            <include>**/application*.yml</include>
            <include>**/application*.yaml</include>
            <include>**/application*.properties</include>
        </resource>
    </resources>
</build>
Copy the code

5. How do I proactively read configuration files into class variables

To use @value (“${attribute name}”)

As follows:

Create a new application.properties configuration file under the Resource folder

spring.jdbc.datasource.driverClassName=com.mysql.jdbc.driver
spring.jdbc.datasource.url=jdbc:mysql:///springboot_01
spring.jdbc.datasource.username=root
spring.jdbc.datasource.password=123456
Copy the code

Create the class DataSourceProperties


import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class DataSourceProperties {

    @Value("${spring.jdbc.datasource.driverClassName}")
    private String driverClassName;
    @Value("${spring.jdbc.datasource.url}")
    private String url;
    @Value("${spring.jdbc.datasource.username}")
    private String username;
    @Value("${spring.jdbc.datasource.password}")
    private String password;

    // Generate get set and toString methods
}
Copy the code

YAML configuration file

1. What is YAML?

YAML is a configuration file format

2. Grammar

1. The data structure is presented in a tree structure, and the hierarchy is represented by indenting.

2. Consecutive items are indicated by a minus sign “-“

3. The key/value pairs in the key-value structure are separated by colons (:), followed by a space to match the attribute value.

4. The extension name of the YAML configuration file is YAML or YML

If you want to change the previous properties file to a YAMl file

spring:
  jdbc:
    datasource:
      driverClassName: com.mysql.jdbc.Driver
      url: jdbc:mysql:///springboot_01
      username: root
      password: 123456
Copy the code

Characteristics of yML configuration files:

  1. The configuration items are displayed in a tree hierarchy
  2. If there is a relationship between configuration items, you need a branch, two empty Spaces
  3. If the configuration item has a value, the value of the configuration item must be blank one space after:.

The yamL and Peoperties configuration file handling displays are the same except that they are different.

3. Configure profile switching in multiple environments

In actual development, we need to change the value of a configuration item in the configuration file due to the change of the development environment (for example, switch from himysQL database to Oracle database).

When the project needs to go online after completion of development, some environments need to be changed into formal environments (development, testing, going online, multi-environment switching).

Solution: Use Profiles to split the configuration

Multiple YAML configuration files are allowed in spring Boot projects.

These files must be named **application-***.yml** and active in application.yml.

Specific implementation

Create application-dev.yml file as follows:

spring:
  jdbc:
    datasource:
      driverClassName: com.mysql.jdbc.Driver
      url: jdbc:mysql:///springboot
      username: root
      password: 123456
Copy the code

Create application-pro.yml file as follows:

spring:
  jdbc:
    datasource:
      driverClassName: com.mysql.jdbc.Driver
      url: jdbc:mysql:///business
      username: business
      password: business
Copy the code

Add the following configuration to the application.yml file:

spring:
  profiles:
    active: dev
Copy the code

The file that takes effect is the application-dev.yml configuration file.

Note:

If both properties and YML files exist, there is no spring.profiles. Active setting, and if there are overlapping properties, the properties file takes precedence by default.

If spring.profiles. Active is set and has overlapping properties, the active setting takes precedence.

You can add the server.port property to the two files to specify different ports and start the project to view the console port number for testing.

Automatic configuration principle of Spring Boot

1. @ SpringBootApplication annotation

(1) @ SpringBootConfiguration

This class is a Configuration class, which is essentially an @Configuration annotation

(2) ComponentScan

Component scanning, which by default scans annotations on the package that starts the class and the classes that subpackage it.

(3) EnableAutoConfiguration

Auto-configure annotations, which are added to automatically read auto-configure classes in the Spring.Factories configuration file.

2. @ ConfigurationProperties annotation

An important annotation provided by SpringBoot is @configurationproperties, which enables batch injection of ConfigurationProperties into bean objects.

Inject configuration properties

Method 1: Use @value to inject one by one

This way, if there are too many attributes, one by one injection is very cumbersome.

Method 2: using the @ ConfigurationProperties batch injection and used @ EnableConfigurationProperties 】 【

@Component
@ConfigurationProperties(prefix = "spring.jdbc.datasource")
public class DataSourceProperties2 {

    private String driverClassName;
    private String url;
    private String username;
    private String password;
    
     // omit the getter and setter.....
}    
Copy the code
  1. The @ConfigurationProperties annotation on the class declares that the class reads the property configuration.
  2. Prefix =”spring.jdbc.datasource” Reads the value prefixed with spring.jdbc.datasource in the properties file. The prefix and attribute names must be the same as the key in the configuration file for the injection to succeed
  3. Spring Boot reads the application.properties property file by default

Enable the @ConfigurationProperties annotation

@Controller
@EnableConfigurationProperties(DataSourceProperties2.class)
public class HelloController {
    
    @Autowired
    private DataSourceProperties2 dataSourceProperties2 ;

    @RequestMapping(path = "/hello")
    @ResponseBody
    public String sayHello(a){
        System.out.println(dataSourceProperties2);
        return "hello spring boot"; }} to use@EnableConfi
Copy the code

Using the @ EnableConfigurationProperties (DataSourceProperties2. Class), open DataSoutceProperties2 @ ConfigurationProperties annotations, It’ll be active, and it’ll be able to inject data for us.

Spring Boot Configuration Annotation Processor not found in classpath.

Solutions:

Add dependencies to POM files

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
Copy the code

3. Configure conditional annotations

ConditionalXxx we see ConditionalXxx annotations in the auto-configuration class, which make conditional selection.

Conditional selection means that if the conditions are met, the configuration class takes effect; if not, the configuration class does not take effect.

Commonly used conditional seat selection notes are as follows:

annotations role
@ConditionalOnBean If a Bean exists, the configuration class takes effect
@ConditionalOnMissingBean If a Bean does not exist, the configuration class takes effect
@ConditionalOnClass If a class exists, the configuration class takes effect
@ConditionalOnMissingClass If no class exists, the configuration class takes effect
@ConditionalOnProperty If a property configuration exists, the configuration class takes effect
@ConditionalOnWebApplication If it is a Web application, the configuration class takes effect
@ConditionalOnNotWebApplication If it is not a Web application, the configuration class takes effect

WebMvcAutoConfiguration will take effect because we configured the DispatcherServlet to meet the criteria defined above. So what does WebMvcAutoConfiguration automatically configure for us?

  1. View resolver (triggerpublic InternalResourceViewResolver defaultViewResolver()orpublic BeanNameViewResolver beanNameViewResolver()Methods)
  2. Processor adapter (public RequestMappingHandlerAdapter requestMappingHandlerAdapter()Methods)

These configurations are what we need to configure ourselves when we learn SpringMVC. Now the Spring Boot framework has configured them for us in advance, so we can use them easily.

4. Automatic configuration principle

1. Loading spring. Factories

When the SpringApplication class is built, there is an initialization code like this:

    public SpringApplication(ResourceLoader resourceLoader, Class
       ... primarySources) {
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.isCustomEnvironment = false;
        this.lazyInitialization = false;
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }
Copy the code

Pay attention to this. SetInitializers (enclosing getSpringFactoriesInstances (ApplicationContextInitializer. Class)); Click to enter getSpringFactoriesInstances method

    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
        return this.getSpringFactoriesInstances(type, new Class[0]);
    }
Copy the code

Then with the getSpringFactoriesInstances method

    private <T> Collection<T> getSpringFactoriesInstances(Class
       
         type, Class
        [] parameterTypes, Object... args)
        {
        ClassLoader classLoader = this.getClassLoader();
        Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }
Copy the code

You can see the Set < String > names = new LinkedHashSet (SpringFactoriesLoader. LoadFactoryNames (type, this)); This code. Can find loadFactoryNames () attempts to load some FactoryName, then using createSpringFactoriesInstances these loaded into the name of the class to instantiate. Then follow up with the loadFactoryNames method:

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

Observe the loadSpringFactories method called when it returns

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{ 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);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();

                    while(var6.hasNext()) { Entry<? ,? > entry = (Entry)var6.next(); 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

Find that a file is loaded using the class loader: meta-INF/Factories. As we know, ClassLoader reads files from the classpath by default, so SpringBoot loads all classpath: meta-INF/Spring. factories, including jar files, at initialization. Such a file is available in one of Spring’s dependencies, Spring-boot-Autoconfigure.

Any third-party launcher we introduce that implements automatic configuration will also have similar files.

2. Read the automatic configuration class

Open this spring.factories

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer

# Template availability providers
org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider
Copy the code

You can find a series of configurations using the EnableAutoConfigutation interface as the key, and the corresponding value of the key is all the auto-configuration classes, which can be found in the current JAR package:

Covering almost all of today’s major open source frameworks, we can look at SpringMVC’s auto-configuration classes here.

We’ve found the auto-configuration class for SpringMVC

3. Configure default properties

The configuration class is found, so where do these default configuration properties come from?

For example, where are the prefixes and postfixes required to configure the view parser?


        @Bean
        @ConditionalOnMissingBean
        public InternalResourceViewResolver defaultViewResolver(a) {
            InternalResourceViewResolver resolver = new InternalResourceViewResolver();
            resolver.setPrefix(this.mvcProperties.getView().getPrefix());
            resolver.setSuffix(this.mvcProperties.getView().getSuffix());
            return resolver;
        }
Copy the code

Through this period of source, found that the configuration is this. MvcProperties. GetView (). Look at this method.

public WebMvcProperties.View getView() {
    return this.view;
}
Copy the code

I found that I was reading a class variable

    private final WebMvcProperties.View view;
Copy the code

This View type encapsulates a prefix and a suffix

public static class View { private String prefix; private String suffix; public View() { } public String getPrefix() { return this.prefix; } public void setPrefix(String prefix) { this.prefix = prefix; } public String getSuffix() { return this.suffix; } public void setSuffix(String suffix) { this.suffix = suffix; }}Copy the code

As you can see, the prefix and postfix variables default to null.

4. Override the default Settings

What if we want to specify our own view prefix and suffix?

We can see WebMvcAutoConfiguration WebMvcAutoConfigurationAdapter static inner class of this class on a statement, Found this class with such an annotation @ EnableConfigurationProperties ({WebMvcProperties. Class, the ResourceProperties class}).

@Configuration( proxyBeanMethods = false )
    @Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
    @EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class})
    @Order(0)
    public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
        private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class);
        private final ResourceProperties resourceProperties;
        private final WebMvcProperties mvcProperties;
        private final ListableBeanFactory beanFactory;
        private final ObjectProvider<HttpMessageConverters> messageConvertersProvider;
        final WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;

        public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider) {
            this.resourceProperties = resourceProperties;
            this.mvcProperties = mvcProperties;
            this.beanFactory = beanFactory;
            this.messageConvertersProvider = messageConvertersProvider;
            this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvaila ble(); }public void configureMessageConverters(List
       
        > converters)
       > {
            this.messageConvertersProvider.ifAvailable((customConverters) -> {
                converters.addAll(customConverters.getConverters());
            });
        }

        public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
            if (this.beanFactory.containsBean("applicationTaskExecutor")) {
                Object taskExecutor = this.beanFactory.getBean("applicationTaskExecutor");
                if (taskExecutor instanceof AsyncTaskExecutor) {
                    configurer.setTaskExecutor((AsyncTaskExecutor)taskExecutor);
                }
            }

            Duration timeout = this.mvcProperties.getAsync().getRequestTimeout();
            if(timeout ! =null) { configurer.setDefaultTimeout(timeout.toMillis()); }}public void configurePathMatch(PathMatchConfigurer configurer) {
            configurer.setUseSuffixPatternMatch(this.mvcProperties.getPathmatch().isUseSuffixPattern());
            configurer.setUseRegisteredSuffixPatternMatch(this.mvcProperties.getPathmatch().isUseRegisteredSuffixPattern());
        }

        public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
            Contentnegotiation contentnegotiation = this.mvcProperties.getContentnegotiation();
            configurer.favorPathExtension(contentnegotiation.isFavorPathExtension());
            configurer.favorParameter(contentnegotiation.isFavorParameter());
            if(contentnegotiation.getParameterName() ! =null) {
                configurer.parameterName(contentnegotiation.getParameterName());
            }

            Map<String, MediaType> mediaTypes = this.mvcProperties.getContentnegotiation().getMediaTypes();
            mediaTypes.forEach(configurer::mediaType);
        }

        @Bean
        @ConditionalOnMissingBean
        public InternalResourceViewResolver defaultViewResolver(a) {
            InternalResourceViewResolver resolver = new InternalResourceViewResolver();
            resolver.setPrefix(this.mvcProperties.getView().getPrefix());
            resolver.setSuffix(this.mvcProperties.getView().getSuffix());
            return resolver;
        }

        @Bean
        @ConditionalOnBean({View.class})
        @ConditionalOnMissingBean
        public BeanNameViewResolver beanNameViewResolver(a) {
            BeanNameViewResolver resolver = new BeanNameViewResolver();
            resolver.setOrder(2147483637);
            return resolver;
        }

        @Bean
        @ConditionalOnBean({ViewResolver.class})
        @ConditionalOnMissingBean( name = {"viewResolver"}, value = {ContentNegotiatingViewResolver.class} )
        public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
            ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
            resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
            resolver.setOrder(-2147483648);
            return resolver;
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnProperty( prefix = "spring.mvc", name = {"locale"} )
        public LocaleResolver localeResolver(a) {
            if (this.mvcProperties.getLocaleResolver() == org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties.LocaleResolver.FIXED) {
                return new FixedLocaleResolver(this.mvcProperties.getLocale());
            } else {
                AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
                localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
                returnlocaleResolver; }}public MessageCodesResolver getMessageCodesResolver(a) {
            if (this.mvcProperties.getMessageCodesResolverFormat() ! =null) {
                DefaultMessageCodesResolver resolver = new DefaultMessageCodesResolver();
                resolver.setMessageCodeFormatter(this.mvcProperties.getMessageCodesResolverFormat());
                return resolver;
            } else {
                return null; }}public void addFormatters(FormatterRegistry registry) {
            ApplicationConversionService.addBeans(registry, this.beanFactory);
        }

        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)); }}}private Integer getSeconds(Duration cachePeriod) {
            returncachePeriod ! =null ? (int)cachePeriod.getSeconds() : null;
        }

        private void customizeResourceHandlerRegistration(ResourceHandlerRegistration registration) {
            if (this.resourceHandlerRegistrationCustomizer ! =null) {
                this.resourceHandlerRegistrationCustomizer.customize(registration); }}@Bean
        @ConditionalOnMissingBean({RequestContextListener.class, RequestContextFilter.class})
        @ConditionalOnMissingFilterBean({RequestContextFilter.class})
        public static RequestContextFilter requestContextFilter(a) {
            return newOrderedRequestContextFilter(); }}Copy the code

Go back to webmvcProperties.class, which reads the configuration using ConfigurationProperties, prefixed with Spring.mvc

@ConfigurationProperties( prefix = "spring.mvc" )
public class WebMvcProperties {
    / /...
}
Copy the code

The ResourceProperties. Class reads the configuration prefix spring.resources

@ConfigurationProperties( prefix = "spring.resources", ignoreUnknownFields = false )
public class ResourceProperties {
/ /...
}
Copy the code

So if we configure the spring. MVC prefix in the configuration file, we can inject our own configured data into the properties of this object. Note that since @configurationproperties is a batch injection, we need to write the ConfigurationProperties exactly as the prefix + property name of the class, otherwise the injection will fail.

For example,

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

Or change the port number

server:
  port: 10000
Copy the code

5. Customize the initiator

1. Requirements introduction

Define a connection pool initiator that is automatically configured in a project when a user introduces a connection pool startup dependency.

2. Step analysis

  1. Create an initiator project

  2. Add initiator dependencies

  3. Create the property configuration class

  4. Create the auto-configuration class

  5. Write automatic configuration files (spring.Factories)

  6. Use a customized initiator

3. Code implementation

1. Create projects and introduce dependencies

Create a spring-boot-jdbC-starter project

pom.xml

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

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <! -- Introducing spring‐boot‐starter; Basic configuration of all starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
</dependency>

    <! -- Automatic connection pool configuration -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.12</version>
</dependency>

    <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
</dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
Copy the code
2. Create a property configuration class
import org.springframework.boot.context.properties.ConfigurationProperties;

@Component
@ConfigurationProperties(prefix = "spring.jdbc.datasource")
public class DataSourceProperties {
    private String driverClassName ;
    private String url;
    private String username;
    private String password;
    // Generate the set Get toString method
}   
Copy the code
3. Create an automatic configuration class
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;

@SpringBootConfiguration
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {

    @Autowired
    private DataSourceProperties dataSourceProperties ;

    @Bean
    public DataSource createDataSource(a){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
        dataSource.setUrl(dataSourceProperties.getUrl());
        dataSource.setUsername(dataSourceProperties.getUsername());
        dataSource.setPassword(dataSourceProperties.getPassword());
        returndataSource; }}Copy the code
4. Write an automatic configuration property file

Create a new meta-INF/spring.Factories folder under resources

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.dyy.autoconfig.DataSourceAutoConfiguration
Copy the code

When you’re done, be sure to execute Install in Maven to install the project.

5. Use a customized initiator

Introduce our own custom launcher dependencies in the new project

<dependency>
    <groupId>com.dyy</groupId>
    <artifactId>spring-boot-jdbc-starter</artifactId>
    <version>1.0 the SNAPSHOT</version>
</dependency>

Copy the code

Configure connection pool information.

New application – a datasource. Yml

spring:
  jdbc:
    datasource:
      driverClassName: com.mysql.jdbc.Driver
      url: jdbc:mysql:///springboot_01
      username: root
      password: 123456
Copy the code

Activate the configuration file application.yml

spring:
  profiles:
    active: datasource
Copy the code

Access the connection pool and view the connection pool properties


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.sql.DataSource;

@RestController
public class HelloController { 
    @Autowired
    private DataSource dataSource ;

    @RequestMapping(path = "/hello")
    public String sayHello(a) {
        System.out.println(dataSource.getClass());// Prints the DruidDataSource data source
        return "Hello Spring Boot ! "; }}Copy the code
6. Multiple data sources

If we want our launcher to support multiple data sources. For example, C3P0 and Druid can be implemented using conditional selection by selecting based on configuration. Druid = C3p0; Druid = C3p0; Druid = C3p0;

Modify the application-datasource. Yml configuration file

spring: jdbc: datasource: driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql:///springboot_01 username: Root password: root type: druid # Data source typeCopy the code
  • If the configuration file is configured with spring.. JDBC datasource. Type = c3p0 use c3p0 data source
  • If the configuration file is configured with spring.. JDBC datasource. Type = druid use druid data source.

In the spring-boot-jdbC-starter project, add the create C3P0 method

package com.dyy.autoconfig;

import com.alibaba.druid.pool.DruidDataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;

@Configuration
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguratioin {

    @Autowired
    private DataSourceProperties dataSourceProperties ;

@Bean
    @ConditionalOnProperty(value = "spring.jdbc.datasource.type",havingValue = "druid")
    public DataSource createDataSource(a){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
        dataSource.setUrl(dataSourceProperties.getUrl());
        dataSource.setUsername(dataSourceProperties.getUsername());
        dataSource.setPassword(dataSourceProperties.getPassword());
        return dataSource;
    }

@Bean
    @ConditionalOnProperty(value = "spring.jdbc.datasource.type",havingValue = "c3p0")
    public DataSource createC3P0DataSource(a) throws Exception{
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(dataSourceProperties.getDriverClassName());
        dataSource.setJdbcUrl(dataSourceProperties.getUrl());
        dataSource.setUser(dataSourceProperties.getUsername());
        dataSource.setPassword(dataSourceProperties.getPassword());
        returndataSource; }}Copy the code

We can use a conditional selection implementation, as shown in the figure below

@ ConditionalOnProperty (value = “. Spring. JDBC datasource. Type “, havingValue = “druid) install to install the spring – the boot – JDBC – the starter, Run springboot_01

Modify the configuration file, re-install, and request again.

5. Spring Boot Common initiator

1. MVC SpringBoot integration

Create the project springbooT_02_MVC

1. Rely on

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

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

Copy the code

2. Create an entry program class

package com.dyy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class,args); }}Copy the code

3. New javabean

public class User {
    private String username ;
    private String password ;
    private Integer age ;
privateString sex ; ... }Copy the code

4. New UserController

import com.dyy.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.List;

@Controller
@RequestMapping(path = "/user")
public class UserController {

    @RequestMapping(path = "/findAll")
    @ResponseBody
    public List<User> findAll(a){
        // Query all
        List<User> users = new ArrayList<User>();

        User user1 = new User();
        user1.setUsername("Yang guo");
        user1.setPassword("123456");
        user1.setAge(18);
        user1.setSex("Male");

        User user2 = new User();
        user2.setUsername("Yang guo");
        user2.setPassword("123456");
        user2.setAge(18);
        user2.setSex("Male");

        User user3 = new User();
        user3.setUsername("Yang guo");
        user3.setPassword("123456");
        user3.setAge(18);
        user3.setSex("Male");

        users.add(user1);
        users.add(user2);
        users.add(user3);

        returnusers ; }}Copy the code

Run the program.

2. Static resource directory

Before developing web projects, if it is a common project jintai resources can be placed in the project webApp directory.

Now we are using Spring Boot for development, there is no WebApp directory in the project, our project is a JAR project, so there is no WebApp, where should we put our static resources?

There is a class in SpringBoot called ResourceProperties that defines the default lookup path for static resources.

@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/"};
    private String[] staticLocations;
    private boolean addMappings;
    private final ResourceProperties.Chain chain;
    private final ResourceProperties.Cache cache;

    public ResourceProperties(a) {
        this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
        this.addMappings = true;
        this.chain = new ResourceProperties.Chain();
        this.cache = new ResourceProperties.Cache();
    }
    / /...
    }
Copy the code

You can see that the default static resource path is:

  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/
  • classpath:/public

As long as static resources are in any of these directories, SpringMVC takes care of it for us. We tend to place static resources in the classpath:/static/ directory. Create the index.html file in the Resources directory.

Open a browser and enter: http://localhost:8080/index.html

If you want to change the default static resource path, you need to add it in application.yml

spring:
  resources:
    static-locations: classpath:/webapp/
Copy the code

The installation takes effect after the restart.

3. Custom interceptors

Web development interceptor is also a component we often need to use, can help us complete some logging, data filtering, request filtering and so on many functions, so how to configure in SpringBoot?

Steps to configure interceptors in SpringMVC:

  1. Write an interceptor (need to implement the HandlerInterceptor interface)

  2. Register interceptors (XML configuration MVC: Interceptors)

    ml
       <! -- Configure interceptor -->
       <mvc:interceptors>
           <mvc:interceptor>
               <! -- Configure interception path -->
               <mvc:mapping path="/user/**"/>
               <! -- Configure not blocking path: not blocking path means excluded from blocking path -->
               <mvc:exclude-mapping path="/user/sayByby"></mvc:exclude-mapping>
               <! Configure interceptor beans -->
               <bean class="com.dyy.interceptor.LogInterceptor2"></bean>
           </mvc:interceptor>
       </mvc:interceptors>
    Copy the code

Since SpringBoot does not have an XML configuration file, the way to register interceptors in SpringBoot is different. We need to use a WebMvcConfigurer class to register interceptors.

  1. Write an interceptor (implementing the HandlerInterceptor interface)
  2. Register interceptors with WebMvcConfigurer (custom classes are implemented in the WebMvcConfigurer interfacepublic void addInterceptors(InterceptorRegistry registry)Methods)

The steps are as follows

1. Write interceptors


import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("The MyInterceptor preHandle method executes....");
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor's postHandle method executes....");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor's afterCompletion method executes...."); }}Copy the code

2. Register interceptors


import com.dyy.interceptor.MyInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Autowired
    private MyInterceptor myInterceptor ;

    /** * /findAll /user/** /user/findAll /user/order/findAll * /* /findAll /user/* /user/findAll *@param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(myInterceptor).addPathPatterns("/ * *"); }}Copy the code

Open the browser console enter http://localhost:8888/user/findAll observation.

4. Integrate Spring Data JPA

1. Create a projectspringboot_jpa

2. Add Spring Data JPA starter dependencies

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

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

        <! -- springBoot JPA startup dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <! MySQL connection driver -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <! Redis initiator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

    </dependencies>

Copy the code

3. Configure the database and JPA properties in application.yml

logging:
  level:
    com.dyy.dao: debug # config log
spring:
  datasource:
    username: root
    password: 123456
    url: JDBC: mysql: / / 127.0.0.1:3306 / springboot? useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    database: mysql
    show-sql: true
    generate-ddl: true
    hibernate:
      ddl-auto: update
      naming_strategy: org.hibernate.cfg.ImprovedNamingStrategy
server:
  port: 18081

Copy the code

Note: in mysql8.x, the url needs to specify the time zone when connecting, and the driver class package name has changed.

4. Create entity class configuration properties


import javax.persistence.*;

@Entity
@Table(name = "user")
public class User{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    @Column(name = "username")
    private String username;
    @Column(name = "password")
    private String password;
    @Column(name = "name")
    private String name;
 
    // omit the setter and getter methods here... .
}

Copy the code

5. Write UserRepository

import com.dyy.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserDao extends JpaRepository<User.Integer> {}Copy the code

6. Write the Service class


import com.dyy.domain.User;
import java.util.List;

public interface UserService {
    List<User> findUsers(a);

    User findUserById(Integer id);

    void saveUser(User user);

    void updateUser(User user);

    void deleteUserById(Integer id);
}

Copy the code

7. The service implementation class


import com.dyy.dao.UserDao;
import com.dyy.domain.User;
import com.dyy.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    /** * query all *@return* /
    @Override
    public List<User> findUsers(a) {
        return userDao.findAll();
    }
    /** * query * by id@return* /
    @Override
    public User findUserById(Integer id) {
        return userDao.findById(id).get();
    }
    /** * save *@return* /
    @Override
    public void saveUser(User user) {
        userDao.save(user);
    }
    /** * update *@return* /
    @Override
    public void updateUser(User user) {
        userDao.save(user);
    }
    /** * delete * based on id@return* /
    @Override
    public void deleteUserById(Integer id) { userDao.deleteById(id); }}Copy the code

8. Write the Controller class


import com.dyy.domain.User;
import com.dyy.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/findAll")
    public List<User> findAll(a){
        returnuserService.findUsers(); }}Copy the code

SpringBoot application

1. Environment construction

1. Prepare the database

create database springboot character set utf8 ;

use springboot ; 

CREATE TABLE `tb_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `gender` varchar(5) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `address` varchar(32) DEFAULT NULL,
  `qq` varchar(20) DEFAULT NULL,
  `email` varchar(50) DEFAULT NULL,
  `username` varchar(20) NOT NULL,
  `phone` varchar(11) DEFAULT NULL.PRIMARY KEY (`id`),
  UNIQUE KEY `user_username_uindex` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

INSERT INTO `tb_user` VALUES (1.'huang2 rong2'.'woman'.38.Peach Blossom Island.'212223390222'.'[email protected]'.'huangrong'.'15600003333'), (2.'Huang Lao Xie'.'male'.58.Wuhan city, Hubei Province.'212223390'.'[email protected]'.'huanglaoxie'.'15872320405'), (3.'Little Dragon Lady'.'male'.18.Jingmen city, Hubei Province.'212223390'.'[email protected]'.'xiaolongnv'.'15600004444'), (7.'John Steinbeck'.'male'.30.'yangzhou'.'212223390'.'[email protected]'.'yangguo'.'15600005555');

Copy the code

2. Create the project and package structure

Create the project SpringbooT_Case

3. Import dependencies


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

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

    <dependencies>
        <! -- Unit test initiator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <! -- Mapper initiator dependencies -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>
        <! --JDBC initiator dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <! - mysql driver - >
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <! --druid initiator dependencies -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <! -- Web initiator dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <! -- Spring boot actuator dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <! -- Coding kit -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency><! -- Hot deployment --><dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <! -- Spring Boot Maven plugin, can run the project dependent JAR package into our project -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    
</project>

Copy the code

4. Create a startup class


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;

@SpringBootApplication
@MapperScan(basePackages = "com.dyy.dao")
@EnableTransactionManagement
public class Application {
    public static void main(String[] args) { SpringApplication.run(Application.class,args); }}Copy the code

2. Data access layer

1. Compile the configuration file application.yml

server:
  port: 10001
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///springboot
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource
mybatis:
  type-aliases-package: com.dyy.pojo

Copy the code

2. Write the entity class User


import java.io.Serializable;

@Entity
@Table(name = "tb_user")
public class User implements Serializable {
    private Integer id;
    private String name;
    private String gender;
    private Integer age;
    private String address;
    private String qq;
    private String email;
    private String username;
    private String phone;
Getter/setter toString...
}
Copy the code

3. Configure the mapper interface and mapping


import tk.mybatis.mapper.common.Mapper;
import java.util.List;

public interface UserMapper extends Mapper<User> {}Copy the code

4. Write test code

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {

    @Autowired
    private UserMapper userMapper ;

    @Test
    public void findAll(a) { List<User> users = userMapper.selectAll(); System.out.println(users); }}Copy the code

3. The business layer

1. Write interfaces

public interface UserService {

    /** * Query all user information *@return* /
    public List<User> findAll(a);
}

Copy the code

2. Write implementation classes


import com.dyy.dao.UserMapper;
import com.dyy.pojo.User;
import com.dyy.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
private UserMapper userMapper;

@Override
@Transactional(readOnly = true ,propagation = Propagation.SUPPORTS)
    public List<User> findAll(a) {
        returnuserMapper.selectAll(); }}Copy the code

3. Write test code

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @Test
    public void findAll(a) { List<User> users = userService.findAll(); System.out.println(users); }}Copy the code

note

Spring Boot integrates unit tests by adding two annotations to the test class:

  1. @runwith (springrunner.class) specifies the Junit core runtime class
  2. SpringBootTest specifies that this is a SpringBoot test class that automatically loads the SpringBoot runtime environment when it is run

4. The presentation layer

1. Introduce dependencies

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

<! -- Coding kit -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
</dependency>

Copy the code

2. Create a tool class


import java.io.Serializable;

public class Result implements Serializable {
    private boolean status ; // Response status true false
    private String msg ;  // Response information
    private Object data ;  // Process successful response data

    public static Result ok(Object data){
        Result result = new Result();
        result.setStatus(true);
        result.setData(data);
        return  result ;
    }

    public static Result error(String msg){
        Result result = new Result();
        result.setStatus(false);
        result.setMsg(msg);
        return  result ;
    }
    
    // Generate the set Get toString method
    
}  

Copy the code

3. Write presentation code

@Controller
@RequestMapping(path = "/user")
public class UserController {

    @Autowired
    private UserService userService;

    /** * Query all user information *@return* /
    @RequestMapping(path = "/findAll")
    @ResponseBody
    public Result findAll(a) {
        List<User> users = userService.findAll();
        returnResult.ok(users); }}Copy the code

4. Code testing

Use Postman for testing

5. Page display

Create a static directory in the Resources directory and create a page display, list.html:

  • The page asynchronous request port is the same as the server port
  • Page asynchronous request access path and the corresponding presentation layer control method path
  • The page asynchronous request parameter name is consistent with the corresponding presentation layer control method parameter

Modified, access page: localhost: 10001 / list. HTML

6. Cache optimization

1. Cache requirements

Problem: User data is infrequently changed data. If these data are queried in the database every time, the efficiency is relatively low, causing great pressure on the database.

Solution: cache, when users query data for the first time, Beijing data is stored in the cache, and then query data directly from the cache can be obtained, no need to query the database. [Redis cache database is used here to store data]

2. Rely on

<! -- SpringBoot -- redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Copy the code

3. Write a configuration file

spring:
  redis: # configuration redis
    host: localhost
    port: 6379
Copy the code

4. Modify the implementation code of the service layer


import com.dyy.mapper.UserMapper;
import com.dyy.pojo.User;
import com.dyy.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper ;
    @Autowired
    private RedisTemplate redisTemplate ;

    @Override
    @Transactional(readOnly = true ,propagation = Propagation.SUPPORTS)
    public List<User> findAll(a) {
        // Retrieving data from the cache specifies that user information is stored as a string, and the stored key is userList
        List<User> userList = (List<User>) redisTemplate.boundValueOps("userList").get();
        // If there is no data in the cache, query the database and put the queried data into the cache
        if(userList==null){
            userList = userMapper.findAll();
            redisTemplate.boundValueOps("userList").set(userList);
            System.out.println("Query from database...");
        }else {
            System.out.println("Query from cache.....");
        }

        // If there is data in the cache, return it directly
        returnuserList ; }}Copy the code

Other components of SpringBoot

1. SpringBoot physical components

role

SpringBoot Actuator is an embedded component of SpringBoot that helps us monitor and manage SpringBoot applications, such as health checks, auditing, statistics, and HTTP tracking.

How to use

1. Introduce SpringBoot Actuator starter dependence
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Copy the code
2. Configure SpringBoot Actuator parameters
management:
  endpoints:
    web:
      exposure:
        include: The '*'  /health /info
      base-path: /monitor # The default is skeletonoid
  endpoint:
    health:
      show-details: ALWAYS	Display all health status
  server:
    port: 9999

Copy the code
3. Start the project to obtain system information

After the orders can be sent through the HTTP request data acquisition system health, for example: http://localhost:9999/monitor/health, return the data as follows:

{
    "status": "UP"."details": {
        "db": {
            "status": "UP"."details": {
                "database": "MySQL"."hello": 1}},"diskSpace": {
            "status": "UP"."details": {
                "total": 355816562688."free": 129251151872."threshold": 10485760}},"redis": {
            "status": "UP"."details": {
                "version": "2.8.9"}}}}Copy the code

Common access paths

HTTP method The path describe
GET /autoconfig An auto-configuration report is provided to record which auto-configuration criteria passed and which did not
GET /configprops Describes how configuration properties (including default values) are injected into beans
GET /beans Describes all beans in the application context and their relationships
GET /dump Gets a snapshot of thread activity
GET /env Gets all environment properties
GET /env/{name} Gets a specific environment attribute value based on the name
GET /health Reports the application’s health metrics, which are provided by the HealthIndicator implementation class
GET /info Gets the customization information for the application, provided by an attribute that starts with info
GET /mappings Describes all URI paths and their mapping to controllers (including Actuator endpoints)
GET /metrics Reports various application metrics, such as memory usage and HTTP request counts
GET /metrics/{name} Reports application metrics for the specified name
POST /shutdown Close the application to endpoints. Shutdown. Enabled is set to true
GET /trace Provide basic HTTP request tracing information (timestamp, HTTP, etc.)

We can get system status information by sending these requests.

2. SpringBoot Admin components

Spring Boot Actuator can obtain system status information through HTTP protocol, but it returns DATA in JSON format, which doesn’t look very good and also needs to remember the path, which is quite troublesome. Spring Boot Admin gives us a more user-friendly visual interface to view this information!

SpringBoot Admin is an open source community project for managing and monitoring SpringBoot applications. An application program registers with the Spring Boot Admin Server as a Spring Boot Admin Client. The Client periodically sends data to the Server. The Server displays data on a friendly interface.

1.SpringBoot Admin server

1. Create the springboot-admin-server project
2. Rely on

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

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

    <groupId>com.dyy</groupId>
    <artifactId>springboot-admin-server</artifactId>
    <version>1.0 the SNAPSHOT</version>

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

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-server</artifactId>
            <version>2.2.0</version>
        </dependency>
    </dependencies>
</project>

Copy the code
3. The configuration application. Yml
spring:
  application:
    name: admin-server
server:
  port: 8769

Copy the code

We set the Spring Boot Admin port number to 8769.

4. Start the class
@SpringBootApplication
@EnableAdminServer
public class Application {
    public static void main(String[] args) { SpringApplication.run(Application.class,args); }}Copy the code

The @enableadminServer function enables the management service.

2.SpringBoot Admin client

1. Create springboot – admin – client
2. Rely on
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.2.0</version>
</dependency>

Copy the code
Configuration of 3.

The IP address that registers with the admin-server is http://localhost:8769, and all the ports in the actuator are exposed. The configurations are as follows:

server:
  port: 9999
spring:
  application:
    name: admin-client
  boot:
    admin:
      client:
        url: http://localhost:8769   Spring Boot Admin Server address
management:
  endpoints:
    web:
      exposure:
        include: The '*' 
  endpoint:
    health:
      show-details: ALWAYS
Copy the code

The registered address must match the SpringBoot Admin Server address.

4. Start the test

Open the client (application) and the server, respectively, and visit http://localhost:8769 to see this interface.

Eight, The Spring Boot project package deployment

1. Project packaging

1. Configure the Maven plug-in for the Spring Boot project in the POM

<build>
    <plugins>
        <! If you do not configure this plugin, the jar package will not have the manifest file.
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Copy the code

2. Run the maven package command

3. We need to skip the tests before packing

If we don’t skip the tests, all the test classes we write will be executed automatically by Maven, and errors may occur, resulting in unsuccessful packaging.

4. After the command is executed, you can view the packaged log information on the console, which contains the location of the generated package

If you open the specified directory, you will find that there is one JAR package. If you look carefully, you will find that there are two jars in the target directory. Springboot_02-1.0-snapshot.jar; springboot_02-1.0-snapshot.jar. Original; springboot_02-1.0-snapshot.jar. Original; springboot_02-1.0-snapshot.jar.

If we package a normal project, we will only get a JAR package, which does not contain the dependent JAR packages of the project

But now we are a Spring Boot project, and we want the finished package to be able to run directly, so the project must include its dependent JAR package, We previously configured a Maven plug-in for Spring Boot in POm. XML, which can insert some operation and dependency information of our project into JAR package based on ordinary package. After completing the package, we renamed the original ordinary package as XXX.jar.

That is to say,

  1. .jar.originalIs a normal JAR package that does not contain dependencies
  2. .jarIs an executable JAR package that contains all the dependencies in the POM and can be used directlyjava -jarCommand execution
  3. If deployed, use it.jarIf it’s for another project, give it.jar.originalThis package

2. Project operation

Open the command line to run the typed package: use the command: java-jar package full name

Java jar springboot_02-1.0 - the SNAPSHOT. The jarCopy the code