Springboot 2 initial notes archiving

Posted by dragon_sa on Fri, 11 Feb 2022 17:08:17 +0100

SpringBoot2

1. Introduction to springboot

Spring Boot is a new framework provided by pivot team. It is designed to simplify the initial construction and development process of new spring applications.

The framework uses a specific way to configure, so that developers no longer need to define a templated configuration.

In this way, Spring Boot is committed to becoming a leader in the booming field of rapid application development.

Simply put, spring boot is not a new framework. It configures the use of many frameworks by default. Just like maven integrates all jar packages, spring boot integrates all frameworks.

  • springboot benefits
  1. Create a stand-alone Spring application
  2. Embedded web server
  3. Automatic starter dependency to simplify build configuration
  4. Automatically configure Spring and third-party functions
  5. Provide production level monitoring, health inspection and external configuration
  6. No code generation, no need to write XML
  • Disadvantages of springboot
  1. The iteration is fast and needs to pay attention to changes all the time
  2. The package is too deep, the internal principle is complex, and it is not easy to master
  • Official documents

springBoot2.4.4 Development Manual

  • What is micro service?
  1. Microservice is an architectural style
  2. An application is split into a group of small services
  3. Each service runs in its own process, that is, it can be deployed and upgraded independently
  4. Lightweight HTTP interaction between services
  5. Services are split around business functions
  6. It can be deployed independently by the fully automatic deployment mechanism
  7. Decentralization, service center. Services can use different languages and different storage technologies
  • Pain points of microservices
  1. High operation and maintenance requirements: more services mean more operation and maintenance investment.
  2. **Inherent complexity of distribution: * * using microservices to build distributed systems. For a distributed system, system fault tolerance, network latency and distributed transactions will bring huge problems.
  3. **High cost of interface adjustment: * * micro services communicate through interfaces. If you modify the API of a microservice, you may need to adjust all microservices that use this interface.
  4. Remote call, service discovery, load balancing, service fault tolerance, configuration management, service monitoring, link tracking, log management, task scheduling

2. Getting started with springboot

2.1 environment preparation and maven setting

1. Environmental requirements

  • Java 8 &Compatible with java14
  • Maven 3.3+
  • idea 2019.1.2

1.1 Maven settings

<mirrors>
    <mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>central</mirrorOf>
        <name>Nexus aliyun</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>
    </mirror>
</mirrors>

<profiles>
    <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>
</profiles>

be careful:

I am IDEA2020, and Process terminated appears when packing. After some tossing, delete < Maven compiler. target>1.8</maven. compiler. Target > is enough.

2 HelloWorld

**Requirements: * * browse, send / Hello request, respond to Hello, Spring Boot 2

2.1 create maven project

2.2 introducing dependencies

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

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

2.3 create main program

/**
 * Main program class
 * @SpringBootApplication: This is a SpringBoot application
 *		@SpringBootConfiguration
 *   	@EnableAutoConfiguration
 *   	@ComponentScan("priv.zwh")
 *		@SpringBootApplication Equivalent to these three annotations, @ ComponentScan scans the package directory of MainApplication by default
 *		If other packages are not in the same level directory as MainApplication, @ ComponentScan needs to specify the package path to scan to their common package
 */
@SpringBootApplication
public class MainApplication {

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

2.4 preparation business

Create a new controller package in the same level directory of the main program. It must be in the same level directory, otherwise it will not be recognized

//@Controller -- component declaration
//@ResponseBody --- indicates that the string is passed to the front end
// RestController contains the above two annotations
@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String handle01() {
        return "Hello SpringBoot2  Hello";
    }
}

2.5 testing

Just run the main method, localhost: 8080/hello

2.6 simplified configuration

application.properties (usually placed under resources) is used to modify some components, such as tomcat port number, etc.

server.port=8888

2.7 simplified deployment

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

Print the project into a jar package and execute it directly on the target server.

  1. Select clean and package under maven's Lifecycle to execute
  2. You will get a jar file under the target folder of the project
  3. Find this XXX in the folder Jar file, execute Java - jar xxx from the command line jar
  4. Test the hello connection of port 8080 without running the main program. (normal operation)

be careful:

When the command line is executed and the mouse clicks on the command being executed, it will be particularly slow. The solution is. Cancel the Quick Edit mode of cmd (right mouse button)

2.8 custom banner

  • Go to the resources directory under the project to create a new banner Txt.
  • https://www.bootschool.net/ascii This website is generated and then copied to the file!

2.9 modify dependent version number

springboot has a version arbitration mechanism, and most of the development dependencies are added to the default parent.

Taking MySQL as an example, the default of springboot is mysql8, so the corresponding database must be updated to mysql8 to use!

To solve this problem, we can also manually switch versions!

<!--Manual version switching:  Put on dependencies Outside-->
<properties>
    <mysql.version>5.1.47</mysql.version>
</properties>

<!--Introduce our mysql Driver, check whether the version is: 5.1.47-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-bj1qzqg7-1621126786457) (C: \ users \ 33132 \ appdata \ roaming \ typora user images \ image-20210512125708939. PNG)]

3 understanding of automatic configuration principle

3.1 springboot dependency management features

  • Dependency management of parent project
Rely on management, mainly to manage the resource filtering and plug-ins of the project!  
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.4.RELEASE</version>
</parent>

Click in to find his parent project
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.3.4.RELEASE</version>
</parent>

It declares the dependent version numbers commonly used in almost all development. There is no need to pay attention to the version number and automatic version arbitration

By default, no version can be written for importing dependency. For importing jar s without version arbitration, the version number should be written.

  • Develop and import starter scenario launcher
1,See a lot spring-boot-starter-* :  *Just some kind of scene
2,Just introduce starter,We automatically introduce all the conventional dependencies of this scenario

3,SpringBoot All supported scenarios:
https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter

4,See  *-spring-boot-starter:  The scenario launcher for simplified development provided by the third party.

5,The lowest level dependency of all scenario initiators( spring-boot-starter): 
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.3.4.RELEASE</version>
    <scope>compile</scope>
</dependency>

Springboot boot starter XXX: the scenario initiator of spring boot

Spring boot starter Web: it helps us import the components that the web module depends on for normal operation

***– spring boot starter: * * these are scenario starters provided by third parties to simplify development.

SpringBoot extracts all functional scenarios and makes them into starters. You only need to introduce these starters into the project, and all relevant dependencies will be imported. What should we use

You can import the scene launcher according to the function; We can also customize the starter ourselves in the future;

All scenarios supported by SpringBoot

3.2 container function

Component addition

1,@Configuration

Configuration usage:

  • The @ Bean annotation is used in the configuration class to register components for the container on the method. The default is single instance (@ Configuration(proxyBeanMethods = true))
  • The configuration class itself is also a component
  • Full(proxyBeanMethods = true) [how many times each @ Bean method is called and the returned components are single instance]
  • Lite(proxyBeanMethods = false) [how many times each @ Bean method is called and the returned component is newly created]

Best practice of Full mode and Lite mode:

  • There is no dependency between configuration class components. Use Lite mode to accelerate the container startup process and reduce judgment
  • There are dependencies between configuration class components, and the method will be called to obtain the previous single instance component in Full mode
2,@Import
//  Automatically create these two types of components in the container. The name of the default component is the full class name
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = false) //Tell SpringBoot that this is a configuration class = = configuration file
public class MyConfig {
    
}
3,@Conditional

Conditional assembly: component injection is performed when the conditions specified in conditional are met

4. @ importresource (native profile import)

Is bean configuration based on most companies or xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="haha" class="priv.zwh.boot.bean.Student">
        <property name="name" value="haha"></property>
    </bean>
</beans>

Therefore, springboot can import xml data into the configuration file by using @ ImportResource.

Just add it to your configuration class.

("classpath:bean.xml")
public class MyConfig {
    
}
5. @ ConfigurationProperties (configuration binding)

Suppose the configuration of the configuration file is (how to bind the Car object):

mycar.brand=YD
mycar.price=100000
  • @Component + @ConfigurationProperties
/**
 * Only the components in the container can have the powerful functions provided by SpringBoot
 */
@ToString
@Data
@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {
    private String brand;
    private Integer price;
}

  • @EnableConfigurationProperties + @ConfigurationProperties
@ToString
@Data
@ConfigurationProperties(prefix = "mycar")
public class Car {
    private String brand;
    private Integer price;
}
@EnableConfigurationProperties(Car.class)
//1. Enable Car configuration binding function
//2. Automatically register the Car component into the container
public class MyConfig {
    
}
  • test
@RestController
public class HelloController {
    @Autowired
    Car car;
    @RequestMapping("/car")
    public Car testCar() {
        return car;
    }
}

Summary:

The latter has no @ Component annotation, but needs to add @ EnableConfigurationProperties annotation on the configuration class. The advantage is that I can introduce third-party jar s.

It's impossible for us to get a third-party jar and add it to the container (@ Component)

3.3 introduction to automatic configuration principle

@Detailed explanation of SpringBootApplication

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {}
1,@SpringBootConfiguration

@Configuration. Represents the current configuration class.

2,@ComponentScan

Specify which Spring annotations to scan;

3,@EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
1,@AutoConfigurationPackage

Auto configuration package? The default package rule is specified

@Import(AutoConfigurationPackages.Registrar.class)  //Import a component into the container
public @interface AutoConfigurationPackage {}

//Use the Registrar to import a series of components into the container
//Import all components under a specified package? Under the package of MainApplication.
2,@Import(AutoConfigurationImportSelector.class)
1,utilize getAutoConfigurationEntry(annotationMetadata);Batch import some components into the container
2,call List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)Get all the configuration classes that need to be imported into the container
3,Using factory loading Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);Get all the components
4,from META-INF/spring.factories Location to load a file.
    By default, we can scan all in our current system META-INF/spring.factories Location file
    spring-boot-autoconfigure-2.3.4.RELEASE.jar It's also in the bag META-INF/spring.factories
    

It's written in the document spring-boot As soon as you start, you need to give all the configuration classes loaded in the container
spring-boot-autoconfigure-2.3.4.RELEASE.jar/META-INF/spring.factories
# 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.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
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.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
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.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
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.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
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.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
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.r2dbc.R2dbcAutoConfiguration,\
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

Turn on automatic configuration class on demand

  • Although all the automatic configurations of our 127 scenarios are loaded by default when they are started. xxxxAutoConfiguration
  • According to the Conditional assembly rule (@ Conditional), only when the conditions are met, can it be configured as required.
  • When the corresponding jar is imported, it will be loaded on demand

Modify default configuration

    @Bean
    //There are components of this type in the container
    @ConditionalOnBean(MultipartResolver.class)
    //There is no component with this name multipartResolver in the container
    @ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
    public MultipartResolver multipartResolver(MultipartResolver resolver) {
        //If the method labeled @ Bean passes in the object parameter, the value of this parameter will be found from the container.
        //SpringMVC multipartResolver.  Prevent the file upload parser configured by some users from not conforming to the specification
        // Detect if the user has created a MultipartResolver but named it incorrectly
        return resolver;
    }
	Add a file upload parser to the container;

SpringBoot will configure all components at the bottom by default. However, if the user has configured it himself, the user's priority shall prevail.

@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {
        
}

Summary:

  • SpringBoot loads all the autoconfiguration classes xxxxconfiguration first

  • Each automatic configuration class takes effect according to conditions, and will bind the value specified in the configuration file by default. Take it from xxproperties. xxxProperties is bound to the configuration file

  • The effective configuration class will assemble many components in the container

  • As long as these components are in the container, they are equivalent to these functions

  • Customized configuration

    • Users directly replace the underlying components with @ Bean
    • The user can modify the value of the configuration file obtained by this component.

Xxxxxxautoconfiguration - > component - > xxxxproperties - > get the value - > application properties

Turn on auto configuration Report

debug=true in the configuration file. Negative, Positive

3.4 development tips

lombok

Simplify JavaBean development

  1. Search and install lombok plug-in in idea and install
  2. Import dependency
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

Slf4j (comes with lombok)

Simplify log development

@Slf4j
@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String handle01(@RequestParam("name") String name){
        
        log.info("The request came in....");
        
        return "Hello, Spring Boot 2!"+"Hello:"+name;
    }
}

dev-tools

Save real-time operation (hot load, daily update) and just ctrl+F9

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

Spring initailizr (project initialization wizard)

  • Select the scenario we need to develop

  • Automatic dependency injection

  • Automatically create project structure

  • Automatically write the main configuration class

4 yml configuration file

1. File type

1.1,properties

Same as previous application Properties have the same effect.

1.2,yaml

1.2.1 introduction

YAML is a recursive abbreviation for "YAML Ain't Markup Language".

When developing this language, YAML actually means "Yet Another Markup Language".

It is very suitable for data centric configuration files

1.2.2 basic grammar
  • key: value; There is a space between kv
  • Case sensitive
  • Use indents to indicate hierarchical relationships
  • tab is not allowed for indentation, only spaces are allowed
  • The number of indented spaces is not important, as long as the elements of the same level are aligned to the left
  • '#' indicates a comment
  • There is no need to add quotation marks to the string. If you want to add quotation marks, single quotation marks and double quotation marks indicate that the string content will be escaped / not escaped (double quotation marks will not be escaped, and single quotation marks will be escaped).
1.2.3 data type
  • Literal quantity: a single, non separable value. date,boolean,string,number,null
k: v
  • Object: a collection of key value pairs. map,hash,set,object
Inline writing:  k: {k1:v1,k2:v2,k3:v3}
#or
k: 
  k1: v1
  k2: v2
  k3: v3
  • Array: a set of values arranged in order. array,list,queue
Inline writing:  k: [v1,v2,v3]
#perhaps
k:
 - v1
 - v2
 - v3
1.2.4 example
  • object
@Data
public class Person {

    private String userName;
    private Boolean boss;
    private Date birth;
    private Integer age;
    private Pet pet;
    private String[] interests;
    private List<String> animal;
    private Map<String, Object> score;
    private Set<Double> salarys;
    private Map<String, List<Pet>> allPets;
}

@Data
public class Pet {
    private String name;
    private Double weight;
}
  • Assign values to objects using yaml
person:
  userName: zhangsan
  boss: false
  birth: 2019/12/12 20:12:33
  age: 18
  pet: 
    name: tomcat
    weight: 23.4
  interests: [Basketball,Swimming]
  animal: 
    - jerry
    - mario
  score:
    english: 
      first: 30
      second: 40
      third: 50
    math: [131,140,148]
    chinese: {first: 128,second: 136}
  salarys: [3999,4999.98,5999.99]
  allPets:
    sick:
      - {name: tom}
      - {name: jerry,weight: 47}
    health: [{name: mario,weight: 47}]

2. Configuration tips

  • There is no keyword prompt when using yaml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
  • Spring boot configuration processor is not packaged when packaging deployment
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <excludes>
                    <exclude>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-configuration-processor</artifactId>
                    </exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

5 Web Development

5.1 simple function analysis

Static resource access

Static resource directory

springboot static resource contract path (resources /) under class path:

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

Static resource access:

Current project root path / + static resource name. localhost:8080/xxx.jpg

Principle:

Static mapping / * *, the request comes in. First go to the Controller to see if it can be handled. All requests that cannot be processed are handed over to the static resource processor. If the static resource cannot be found, the 404 page will be responded.

Change the default static resource path:

In springboot 2 In version 4.2, this method is removed and marked with a delete line

resources:
    static-locations: [classpath:/others/]

Default access path priority of static resources:

When the file names of each folder are the same, which folder is accessed. (sorted from large to small)

  1. META-INF/resources
  2. resources
  3. static
  4. public
Static resource access prefix

Static resources have no prefix by default. Of course, you can also customize the prefix (under application.yaml).

spring:
  mvc:
    static-path-pattern: /img/**

visit:

Current project + static path pattern + static resource name

webjar

Automatic mapping/ webjars/**

https://www.webjars.org/

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

Access address: http://localhost:8080/webjars/jquery/3.5.1/jquery.js The following address should be based on the package path in the dependency

5.1.2 welcome page support

When we visit localhost: 8080, we can open the welcome page by default.

realization:

  • Static resource path: index html

  • The access prefix of static resources cannot be configured. Otherwise, index HTML cannot be accessed by default

    spring:
    #  mvc:
    #    Static path pattern: / RES / * * this will cause the function of the welcome page to fail
    
      resources:
        static-locations: [classpath:/haha/]
    

5.1.3 customize Favicon

When we visit the page, the icon icon is automatically introduced.

Implementation steps:

  • Put favicon ICO is placed in the static resource directory
  • The access prefix of static resources cannot be configured. Otherwise, index HTML cannot be accessed by default

Note: after we introduce, we should first close the current session and then operate to achieve the effect.

5.1.4 static resource allocation principle

  • SpringBoot starts the default loading of the xxxAutoConfiguration class (autoconfiguration class)

  • The automatic configuration class webmvcoautoconfiguration of spring MVC function takes effect

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
		ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {}
  • What's in the container.
 @Configuration(proxyBeanMethods = false)
    @Import(EnableWebMvcConfiguration.class)
    @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
    @Order(0)
    public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {}
  • The relevant properties of the configuration file are bound with xxx. WebMvcPropertiesspring.mvc,ResourcePropertiesspring.resources
The configuration class has only one constructor with parameters
	//The values of all parameters of the parameterized constructor are determined from the container
//ResourceProperties resourceProperties; Get and spring Resources bind to all the value objects
//WebMvcProperties mvcProperties get and spring MVC binds all the value objects
//Listablebeanfactory beanFactory beanfactory of spring
//HttpMessageConverters find all HttpMessageConverters
//ResourceHandlerRegistrationCustomizer found the customizer for the resource processor=========
//DispatcherServletPath  
//Servlet registrationbean registers servlets and filters for applications
	public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties,
				ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider,
				ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider,
				ObjectProvider<DispatcherServletPath> dispatcherServletPath,
				ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
			this.resourceProperties = resourceProperties;
			this.mvcProperties = mvcProperties;
			this.beanFactory = beanFactory;
			this.messageConvertersProvider = messageConvertersProvider;
			this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
			this.dispatcherServletPath = dispatcherServletPath;
			this.servletRegistrations = servletRegistrations;
		}
Default rules for resource processing
@Override
		public void addResourceHandlers(ResourceHandlerRegistry registry) {
			if (!this.resourceProperties.isAddMappings()) {
				logger.debug("Default resource handling disabled");
				return;
			}
			Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
			CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
			//webjars rules
            if (!registry.hasMappingForPattern("/webjars/**")) {
				customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
						.addResourceLocations("classpath:/META-INF/resources/webjars/")
						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
			}
            
            //
			String staticPathPattern = this.mvcProperties.getStaticPathPattern();
			if (!registry.hasMappingForPattern(staticPathPattern)) {
				customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
						.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
			}
		}

Disable all static resource rules:

spring:
  resources:
    add-mappings: false   Disable all static resource rules
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {

	private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
			"classpath:/resources/", "classpath:/static/", "classpath:/public/" };

	/**
	 * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
	 * /resources/, /static/, /public/].
	 */
	private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
Processing rules of welcome page
	HandlerMapping: Processor mapping. Saved each Handler Which requests can be processed.	

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

	WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,
			ApplicationContext applicationContext, Optional<Resource> welcomePage, String staticPathPattern) {
		if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) {
            //To use the welcome page function, you must be/**
			logger.info("Adding welcome page: " + welcomePage.get());
			setRootViewName("forward:index.html");
		}
		else if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
            // Call controller / index
			logger.info("Adding welcome page template: index");
			setRootViewName("index");
		}
	}
favicon

5.3 request parameter processing

5.3.1 request mapping

Use and principle of rest
  • XXXMapping was used in previous SSM
  • Core Filter; HiddenHttpMethodFilte

Usage:

  • Configure in controller
//    @RequestMapping(value = "/user", method = RequestMethod.GET)
    @GetMapping("/user")
    public String getUser() {
        return "GET-Zhang San";
    }

//    @RequestMapping(value = "/user", method = RequestMethod.POST)
    @PostMapping("/user")
    public String saveUser() {
        return "POST-Zhang San";
    }


//    @RequestMapping(value = "/user", method = RequestMethod.PUT)
    @PutMapping("/user")
    public String putUser() {
        return "PUT-Zhang San";
    }

//    @RequestMapping(value = "/user", method = RequestMethod.DELETE)
    @DeleteMapping(value = "/user")
    public String deleteUser() {
        return "DELETE-Zhang San";
    }
  • Front end binding
<form action="/user" method="get">
    <input type="submit" value="REST-GET Submit">
</form>

<form action="/user" method="post">
    <input type="submit" value="REST-POST Submit">
</form>

<form action="/user" method="post">
    <input type="hidden" name="_method" value="DELETE">
    <input type="submit" value="REST-DELETE Submit">
</form>

<form action="/user" method="post">
    <input type="hidden" name="_m" value="PUT">
    <input type="submit" value="REST-PUT Submit">
</form>
  • Manually turn on the rest style in the configuration file
spring:
  mvc:
    hiddenmethod:
      filter:
        enabled: true   #Enable the Rest function of page form
  • Extension: how to_ Change the name of method to one we like.
//Custom filter
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
        HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
        methodFilter.setMethodParam("_m");
        return methodFilter;
    }

Rest principle (when the form submission needs to use rest)

  • The form will be submitted with**_ method=PUT**

  • The request was intercepted by HiddenHttpMethodFilter

    • Is the request normal and POST
      • Get**_ method * *.
      • Compatible with the following requests; PUT.DELETE.PATCH
      • Native request (post). The wrapping pattern requestwrapper overrides the getMethod method method and returns the passed in value.
      • The wrapper is used when the filter chain is released. Later method calls getMethod by calling * * * * requestwrapper.
Request mapping principle

Spring MVC function analysis is from org springframework. web. servlet. DispatcherServlet->doDispatch()

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        boolean multipartRequestParsed = false;

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        try {
            ModelAndView mv = null;
            Exception dispatchException = null;

            try {
                processedRequest = checkMultipart(request);
                multipartRequestParsed = (processedRequest != request);

                // Find out which Handler (Controller's method) is used to process the current request
                mappedHandler = getHandler(processedRequest);
                
                //Handler mapping: processor mapping/ xxx->>xxxx

RequestMappingHandlerMapping: saves the mapping rules of all @ RequestMapping and handlers.

All request mappings are in HandlerMapping.

  • SpringBoot automatically configures the welcome pagehandlermapping of the welcome page. Access / be able to access index html;

  • SpringBoot automatically configures the default RequestMappingHandlerMapping

  • Request to come in and try all HandlerMapping one by one to see if there is any request information.

    • If so, find the handler corresponding to the request
    • If not, it is the next HandlerMapping
  • We need some custom mapping processing. We can also put HandlerMapping in the container ourselves. Custom HandlerMapping

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            for (HandlerMapping mapping : this.handlerMappings) {
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }

5.3.2 general parameters and basic notes

@PathVariable: get the value of path variable dynamically / car/${id}/owner/${name}

@RequestHeader: get request header information

@RequestAttribute: get the request domain attribute

@MatrixVariable: gets the value of the matrix variable

@RestController
public class ParameterTestController {
    @GetMapping("/car/{id}/owner/{username}")
    public Map<String, Object> getCar(@PathVariable("id") Integer id,
                                      @PathVariable("username") String name,
                                      @PathVariable Map<String, Object> pv,
                                      @RequestHeader("User-Agent") String userAgent,
                                      @RequestHeader Map<String, Object> header,
                                      @RequestParam("age") Integer age,
                                      @RequestParam("sex") String sex,
                                      @RequestParam Map<String, Object> params
    ) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", id);
        map.put("name", name);
        map.put("pv", pv);
//        map.put("userAgent", userAgent);
//        map.put("header", header);
        map.put("age", age);
        map.put("sex", sex);
        map.put("params", params);
//        map.put("cookie", cookie);
        return map;
    }
    @PostMapping("/save")
    public Map postMethod(@RequestBody String context) {
        Map<String, Object> map = new HashMap<>();
        map.put("context", context);
        return map;
    }

    //1. Syntax: / cars/sell;low=34;brand=byd,audi,yd
    //2. springboot disables the function of matrix variables by default,
    // Manual opening: principle. Processing of paths. UrlPathHelper for parsing.
    // removeSemicolonContent supports the of matrix variables
    // 3. The matrix variable must have a url path variable to be resolved
    @GetMapping("/cars/{path}")
    public Map carsSell(@MatrixVariable("low") Integer low,
                        @MatrixVariable("brand") List<String> brand,
                        @PathVariable("path") String path) {
        Map<String, Object> map = new HashMap<>();
        map.put("low", low);
        map.put("brand", brand);
        map.put("path", path);
        return map;
    }
    
    // /boss/1;age=20/2;age=10
    @GetMapping("/boss/{bossId}/{empId}")
    public Map boss(@MatrixVariable(value = "age", pathVar = "bossId") Integer bossAge,
                    @MatrixVariable(value = "age", pathVar = "empId") Integer empAge) {
        Map<String, Object> map = new HashMap<>();

        map.put("bossAge", bossAge);
        map.put("empAge", empAge);
        return map;
    }
}

5.4 data response and content negotiation

What return values does spring MVC support

ModelAndView
Model
View
ResponseEntity 
ResponseBodyEmitter
StreamingResponseBody
HttpEntity
HttpHeaders
Callable
DeferredResult
ListenableFuture
CompletionStage
WebAsyncTask
 have @ModelAttribute The object type is
@ResponseBody annotation ---> RequestResponseBodyMethodProcessor;

5.5 view parsing and template engine

View parsing: SpringBoot does not support JSP by default. It needs to introduce third-party template engine technology to realize page rendering.

1. Principle and process of view analysis

1. During the processing of the target method, all data will be placed in the ModelAndViewContainer. Include data and view addresses

2. The parameter of the method is a custom type object (determined from the request parameter), and put it back in the ModelAndViewContainer

3. ModelAndView (data and view address) will be returned after the execution of any target method.

4. processDispatchResult process the dispatch result (how to respond to page changes)

  • 1,render(mv, request, response); Page rendering logic

    • 1. Return the value to the View object according to the String of the method [defines the rendering logic of the page]
      • 1. All View parsers try to find the View object based on the current return value
      • 2. Got redirect: / main html --> Thymeleaf new RedirectView()
      • 3. The content negotiation viewresolver contains all of the following view parsers. Internally, it uses all of the following view parsers to get the view object.
      • 4,view.render(mv.getModelInternal(), request, response); Call render to render the working object of the custom page
        • How to render RedirectView [redirect to a page]
        • 1. Get destination url address
        • 2,response.sendRedirect(encodedURL);

View resolution:

    • The return value starts with forward: new internalresourceview (forwardurl); -- > Forward request getRequestDispatcher(path). forward(request, response);
    • The return value starts with redirect: new RedirectView() -- "render" is redirection
    • The return value is an ordinary string: new ThymeleafView() - >

2 template engine Thymeleaf

Thymeleaf is a modern server-side Java template engine for both web and standalone environments,

capable of processing HTML, XML, JavaScript, CSS and even plain text.

Modern, server-side Java template engine

1. Expression
Expression namegrammarpurpose
Variable value${...}Get request domain, session domain, object equivalent
Select variable*{...}Get context object value
news#{...}Obtain international equivalence
link@{...}Generate link
Fragment Expression~{...}jsp:include function to introduce public page fragments
2. Literal quantity

Text values: 'one text', 'Another one!' * *** Numbers: 0, 34, 3.0, 12.3 * *, * * Boolean values: true, false

Null value: null

Variables: one, two,... Variables cannot have spaces

3. Text operation

String splicing:+

Variable replacement: | The name is ${name}|

4. Mathematical operation

Operators: +, -, *, /,%

5. Boolean operation

Operator: and, or

Unary operation:, not

6. Comparison operation

Comparison: >, <, > =, < = (GT, lt, Ge, le * *) * equation: = == ( eq , ne )

7. Conditional operation

If-then: (if) ? (then)

If-then-else: (if) ? (then) : (else)

Default: (value) ?: (defaultvalue)

8. Special operation

No operation:_

9. Set attribute value - th:attr

Set a single value

<form action="subscribe.html" th:attr="action=@{/subscribe}">
  <fieldset>
    <input type="text" name="email" />
    <input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/>
  </fieldset>
</form>

Set multiple values

<img src="../../images/gtvglogo.png"  th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

Alternative writing of the above two th:xxxx

<input type="submit" value="Subscribe!" th:value="#{subscribe.submit}"/>
<form action="subscribe.html" th:action="@{/subscribe}">

All h5 compatible label writing

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#setting-value-to-specific-attributes

10. Iteration
<tr th:each="prod : ${prods}">
        <td th:text="${prod.name}">Onions</td>
        <td th:text="${prod.price}">2.41</td>
        <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>
<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">
  <td th:text="${prod.name}">Onions</td>
  <td th:text="${prod.price}">2.41</td>
  <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>
11. Conditional operation
<a href="comments.html"
th:href="@{/product/comments(prodId=${prod.id})}"
th:if="${not #lists.isEmpty(prod.comments)}">view</a>
<div th:switch="${user.role}">
  <p th:case="'admin'">User is an administrator</p>
  <p th:case="#{roles.manager}">User is a manager</p>
  <p th:case="*">User is some other thing</p>
</div>
12. Attribute priority

3. thymeleaf use

1. Introducing Starter
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2. thymeleaf is automatically configured
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
public class ThymeleafAutoConfiguration { }

Automatically configured strategy

  • 1. All thymeleaf configuration values are in thymeleaf properties
  • 2. Spring template engine is configured
  • 3. With ThymeleafViewResolver
  • 4. We just need to develop the page directly
public static final String DEFAULT_PREFIX = "classpath:/templates/";

public static final String DEFAULT_SUFFIX = ".html";  //xxx.html
3. Page development
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1 th:text="${msg}">ha-ha</h1>
        <h2>
            <a href="www.atguigu.com" th:href="${link}">Go to Baidu</a>  <br/>
            <a href="www.atguigu.com" th:href="@{link}">Go to Baidu 2</a>
        </h2>
    </body>
</html>

5.6 interceptor

5.6.1 implementation of HandlerInterceptor interface

/**
 * Login check
 * 1,What requests should the interceptor be configured to intercept
 * 2,Put these configurations in containers
 */
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * Before the target method is executed
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String requestURI = request.getRequestURI();
        log.info("preHandle The intercepted request path is{}",requestURI);

        //Login check logic
        HttpSession session = request.getSession();

        Object loginUser = session.getAttribute("loginUser");

        if(loginUser != null){
            //Release
            return true;
        }

        //Stop. Not logged in. Jump to login page
        request.setAttribute("msg","Please login first");
        //        re.sendRedirect("/");
        request.getRequestDispatcher("/").forward(request,response);
        return false;
    }

    /**
     * After the target method is executed
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("postHandle implement{}",modelAndView);
    }

    /**
     * After page rendering
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("afterCompletion Execution exception{}",ex);
    }
}

5.6.2 configure interceptors

/**
 * 1,Write an interceptor to implement the HandlerInterceptor interface
 * 2,Register the interceptor in the container (implement addInterceptors of WebMvcConfigurer)
 * 3,Specify interception rules [if all static resources are intercepted, they will also be intercepted]
 */
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
            .addPathPatterns("/**")  //All requests are intercepted, including static resources
            .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); //Request for release
    }
}

5.7 file upload

5.7.1 form specification

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

Upload file code

/**
     * MultipartFile Automatically encapsulate uploaded files
     * @param email
     * @param username
     * @param headerImg
     * @param photos
     * @return
     */
@PostMapping("/upload")
public String upload(@RequestParam("email") String email,
                     @RequestParam("username") String username,
                     @RequestPart("headerImg") MultipartFile headerImg,
                     @RequestPart("photos") MultipartFile[] photos) throws IOException {

    log.info("Uploaded information: email={},username={},headerImg={},photos={}",
             email,username,headerImg.getSize(),photos.length);

    if(!headerImg.isEmpty()){
        //Save to file server, OSS server
        String originalFilename = headerImg.getOriginalFilename();
        headerImg.transferTo(new File("H:\\cache\\"+originalFilename));
    }

    if(photos.length > 0){
        for (MultipartFile photo : photos) {
            if(!photo.isEmpty()){
                String originalFilename = photo.getOriginalFilename();
                photo.transferTo(new File("H:\\cache\\"+originalFilename));
            }
        }
    }
    return "main";
}

5.8 exception handling

5.8.1 default rules

  • By default, Spring Boot provides / error mapping to handle all errors
  • For the machine client, it generates a JSON response that contains details of the error, HTTP status, and exception messages.

  • For the browser client, respond to a "whitelabel" error view and render the same data in HTML format

5.8.2 custom error handling

  • 4xx and 5xx pages under error / under templates will be automatically parsed;

5.9 web native component injection

5.9.1 using Servlet API

  • Add @ ServletComponentScan(basePackages = "pri.zwh.admin") to the main program entry
// filter
@WebFilter(urlPatterns = {"/css/*", "/images/*"})
public class MyFilter implements Filter {
    
}

// servlet
@WebServlet(urlPatterns = "/my")
public class MyServlet extends HttpServlet {
    
}

// monitor
@WebListener
public class MySwervletContextListener implements ServletContextListener {
    
}

5.9.2 using RegistrationBean

@Configuration(proxyBeanMethods = true)// Ensure that all objects are single instance objects
public class MyRegistConfig {
    @Bean
    public ServletRegistrationBean myServlet() {
        MyServlet myServlet = new MyServlet();

        return new ServletRegistrationBean(myServlet, "/my01", "/my02");
    }


    @Bean
    public FilterRegistrationBean myFilter() {

        MyFilter myFilter = new MyFilter();
        //        return new FilterRegistrationBean(myFilter,myServlet());
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/my01", "/css/*"));
        return filterRegistrationBean;
    }

    @Bean
    public ServletListenerRegistrationBean myListener() {
        MySwervletContextListener mySwervletContextListener = new MySwervletContextListener();
        return new ServletListenerRegistrationBean(mySwervletContextListener);
    }
}

6 data access

6.1 SQL

  • Scene import
// Note that the default supported version is mysql8. If you want to modify it, add the version manually
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>

Want to modify the version
1,Import specific version directly( maven (principle of proximity)
2,Redeclare version( maven (principle of proximity priority of attributes)
<properties>
    <java.version>1.8</java.version>
    <mysql.version>5.1.49</mysql.version>
</properties>

6.1.1 jdbcTemplate

  • Modify configuration item
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db_account
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  • test
@Slf4j
@SpringBootTest
class Boot05WebAdminApplicationTests {
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Test
    void contextLoads() {
        Long aLong = jdbcTemplate.queryForObject("select count(*) from account_tbl", Long.class);
        log.info("Total records:{}",aLong);
    }
}

6.1.2 Druid data source s tarter integration

  • Introducing Druid sstarter
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.17</version>
</dependency>
  • Configuration example
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db_account
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

    druid:
      aop-patterns: com.atguigu.admin.*  #Monitoring springbeans
      filters: stat,wall     # Bottom open function, stat (sql monitoring), wall (firewall)

      stat-view-servlet:   # Configure monitoring page function
        enabled: true
        login-username: admin
        login-password: admin
        resetEnable: false

      web-stat-filter:  # Monitoring web
        enabled: true
        urlPattern: /*
        exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'


      filter:
        stat:    # Detailed configuration of stat in the above filters
          slow-sql-millis: 1000
          logSlowSql: true
          enabled: true
        wall:
          enabled: true
          config:
            drop-table-allow: false

SpringBoot configuration example

Configuration item list

6.1.3 integrating mybatis

  • Introduction of mybatis starter
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.4</version>
</dependency>
  • yml
# Configure mybatis rules
mybatis:
#  config-location: classpath:mybatis/mybatis-config.xml #For the previous writing method of mybatis, you also need to write mybatis config xml
  mapper-locations: classpath:mybatis/mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true 
    
 # You can not write global; Configuration file. The configuration of all global configuration files can be placed in the configuration item

**Note: * * when writing Mapper interface, mark @ Mapper annotation and pay attention to namespace binding

Best practice:

  • Introducing mybatis starter
  • Configure application In yaml, specify the mapper location
  • Write Mapper interface and mark @ Mapper annotation
  • Simple method direct annotation method
  • Write mapper with complex method XML binding mapping
  • @MapperScan("pri.zwh.admin.mapper") is simplified, and other interfaces do not need to be annotated with @ mapper annotation

6.1.4 integrating mybatis plus

  • starter introduction
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.1</version>
</dependency>
  • Automatic configuration analysis

SqlSessionFactory is automatically configured. The bottom layer is the default data source in the container

Maperlocations are automatically configured and have default values, * classpath \ *: / mapper / \ * / \ * All xml files in the mapper folder under the classpath of any xml package are sql mapping files. It is recommended to put the sql mapping file under mapper in the future

@The interface marked by mapper will also be automatically scanned; It is recommended to directly scan @ MapperScan("com.zwh.admin.mapper") in batches

As long as our Mapper inherits BaseMapper, we can have crud capability

  • CRUD
@GetMapping("/user/delete/{id}")
public String deleteUser(@PathVariable("id") Long id,
                         @RequestParam(value = "pn",defaultValue = "1")Integer pn,
                         RedirectAttributes ra){

    userService.removeById(id);

    ra.addAttribute("pn",pn);
    return "redirect:/dynamic_table";
}


@GetMapping("/dynamic_table")
public String dynamic_table(@RequestParam(value="pn",defaultValue = "1") Integer pn,Model model){
    //Traversal of table contents
    //        response.sendError
    //     List<User> users = Arrays.asList(new User("zhangsan", "123456"),
    //                new User("lisi", "123444"),
    //                new User("haha", "aaaaa"),
    //                new User("hehe ", "aaddd"));
    //        model.addAttribute("users",users);
    //
    //        if(users.size()>3){
    //            throw new UserTooManyException();
    //        }
    //Find out the users in the user table from the database for display

    //Construct paging parameters
    Page<User> page = new Page<>(pn, 2);
    //Call page for paging
    Page<User> userPage = userService.page(page, null);


    //        userPage.getRecords()
    //        userPage.getCurrent()
    //        userPage.getPages()


    model.addAttribute("users",userPage);

    return "table/dynamic_table";
}

6.2 NoSQL

  • redis-starter
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  • RedisTemplate and lattice
@Test
void testRedis(){
    ValueOperations<String, String> operations = redisTemplate.opsForValue();

    operations.set("hello","world");

    String hello = operations.get("hello");
    System.out.println(hello);
}
  • Switch to jedis
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!--        Import jedis-->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
  • yml
spring:
  redis:
      host: r-bp1nc7reqesxisgxpipd.redis.rds.aliyuncs.com
      port: 6379
      password: zwh:123456
      client-type: jedis
      jedis:
        pool:
          max-active: 10

7 unit test

7.1 Junit5 changes

Spring boot version 2.2.0 began to introduce JUnit 5 as the default library for unit testing.

JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

JUnit Platform: Junit Platform is the basis for starting the test framework on the JVM. It supports not only Junit's self-made test engine, but also other test engines.

JUnit Jupiter: JUnit Jupiter provides a new programming model of JUnit 5 and is the core of JUnit 5's new features. A test engine is included to run on Junit Platform.

JUnit Vintage: since JUint has been developed for many years, in order to take care of old projects, JUnit Vintage provides JUnit 4.0 compatible services x,Junit3. X test engine.

Springboot versions above 2.4 remove the default dependency on Vintage. If you need to be compatible with junit4, you need to introduce it yourself (you can't use the function @ Test of junit4)

JUnit 5's vintage engine removed from spring boot starter test. If you need to continue to be compatible with junit4, you need to introduce vintage by yourself

<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

7.2 Junit5 common notes

JUnit 5 annotations are different from JUnit 4 annotations

**@Test 😗* The representation method is a test method. However, unlike JUnit4's @ test, it has a very single responsibility and cannot declare any attributes. Jupiter will provide additional tests for expanded tests

**@ParameterizedTest 😗* The representation method is parametric test, which will be described in detail below

**@RepeatedTest 😗* The representation method can be executed repeatedly, which will be described in detail below

**@DisplayName 😗* Set the display name for the test class or test method

**@BeforeEach 😗* Indicates execution before each unit test

**@AfterEach 😗* Indicates execution after each unit test

**@BeforeAll 😗* Indicates execution before all unit tests

**@AfterAll 😗* Indicates execution after all unit tests

**@Tag 😗* Represents the unit test category, similar to @ Categories in JUnit4

**@Disabled 😗* Indicates that the test class or test method is not executed, which is similar to @ Ignore in JUnit4

**@Timeout 😗* Indicates that the test method will return an error if it runs beyond the specified time

**@ExtendWith 😗* Provide extended class references for test classes or test methods

Raytheon springboot2 documentation

Lunatic springboot2 documentation

Topics: Spring Boot