Learning Notes - springboot

Posted by aliasneo86 on Sun, 09 Jan 2022 18:37:29 +0100

Introduction to SpringBoot

Significance

spring integrates multiple frameworks and requires a lot of configuration files. To simplify configuration, the springboot framework has been introduced.

Advantage

Embedded web server

Auto starter dependencies, simplify dependency references - no version issues

Automatically configure spring - you don't need to write a lot of configuration files

Provide production-level monitoring, health testing, and external configuration

shortcoming

The encapsulation is too deep and the internal principle is complex

Faster version iteration

Background of times

Micro-services: divide functionality into modules, deploy on multiple servers, and invoke them through http

Distributed: Micro-services involve distributed issues.

Using springboot+springcloud

To configure

Configuration process

Create a maven empty project

Configure pom.xml file

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://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.4.10-SNAPSHOT</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>
   <groupId>net.xmclass</groupId>
   <artifactId>online_xmclass</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>online_xmclass</name>
   <description>Demo project for Spring Boot</description>
   <properties>
      <java.version>1.8</java.version>
   </properties>
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         <groupId>org.mybatis.spring.boot</groupId>
         <artifactId>mybatis-spring-boot-starter</artifactId>
         <version>2.1.4</version>
      </dependency>

      <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
      </dependency>

      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.apache.commons</groupId>
         <artifactId>commons-lang3</artifactId>
      </dependency>
      <dependency>
         <groupId>io.jsonwebtoken</groupId>
         <artifactId>jjwt</artifactId>
         <version>0.7.0</version>
      </dependency>

      <!--guava Dependent Packages-->
      <dependency>
         <groupId>com.google.guava</groupId>
         <artifactId>guava</artifactId>
         <version>19.0</version>
      </dependency>

      <dependency>
         <groupId>com.google.gcloud</groupId>
         <artifactId>gcloud-java-bigquery</artifactId>
         <version>0.1.7</version>
      </dependency>
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
      </dependency>
   </dependencies>

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

      </plugins>
   </build>
   <repositories>
      <repository>
         <id>spring-milestones</id>
         <name>Spring Milestones</name>
         <url>https://repo.spring.io/milestone</url>
         <snapshots>
            <enabled>false</enabled>
         </snapshots>
      </repository>
      <repository>
         <id>spring-snapshots</id>
         <name>Spring Snapshots</name>
         <url>https://repo.spring.io/snapshot</url>
         <releases>
            <enabled>false</enabled>
         </releases>
      </repository>
   </repositories>
   <pluginRepositories>
      <pluginRepository>
         <id>spring-milestones</id>
         <name>Spring Milestones</name>
         <url>https://repo.spring.io/milestone</url>
         <snapshots>
            <enabled>false</enabled>
         </snapshots>
      </pluginRepository>
      <pluginRepository>
         <id>spring-snapshots</id>
         <name>Spring Snapshots</name>
         <url>https://repo.spring.io/snapshot</url>
         <releases>
            <enabled>false</enabled>
         </releases>
      </pluginRepository>
   </pluginRepositories>
</project>

Main method

@SpringBootApplication
public class OnlineXmclassApplication {

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

}

Simplified configuration

application.properties - Main configuration file, no xml needed. All configurations are in this file

Write Business

test

Simplified deployment

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

Pack into jar packages Note to cancel the cmd Quick Edit mode

Dependency Management

Develop an import starter scene launcher: Scene-related dependencies are automatically introduced whenever a scene is introduced

Introduced dependencies do not require version number attention and have automatic version arbitration

Modify Version Number

Manually controlled version:

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

Or add version number version

Automatic Configuration

Automatic Configuration Features

Automatically Match tomcat

Automatically Match Spring MVC

Automatically pair common web features such as character encoding issues (with interceptors)

Default package structure

The package in which the main program resides and all subpackages below it are scanned. Instead of configuring package scanning, the main program is written at the next level of the project package.

Use @ComponentScan("com.example")

All configurations have default values

Load all the scenarios introduced by automatic configuration on demand before the scene is automatically configured

Principle of automatic configuration
Boot Load Automatic Configuration Class
@SpringBootApplication
@MapperScan("net.xmclass.online_xmclass.mapper")
@EnableTransactionManagement
public class OnlineXmclassApplication {

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

@SpringBootApplication - Configuration Class

@EnableAutoConfiguration

1. Use getAutoConfiguration Entry (annotation Metadata); Batch import some components into the container
2. Call List configurations = getCandidateConfigurations (annotation Metadata, attributes) to get all the configuration classes that need to be imported into the container
3. Load Map <String, List > Load SpringFactories (@Nullable ClassLoader classLoader) using the factory; Get all the components
4. From META-INF/spring.factories location to load a file.
Default scan all META-INF/spring in our current system. Files in factories location
Spring-boot-autoconfigure-2.3.4. RELEASE. The jar package also contains META-INF/spring.factories

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

Include AutoConfiguration Package

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

//Import a series of components into a container using Registrar
//Imports all components under a specified package, under which MainApplication resides.

Include @Import(AutoConfigurationImportSelector.class)

1,2,3,4 Nested Models
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,Use 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.
	Default scan all in our current system META-INF/spring.factories Location file
    spring-boot-autoconfigure-2.3.4.RELEASE.jar There are also packages META-INF/spring.factories
    

Container function

@Configuration

1. Register bean instance with @bean in configuration class, default single instance

2. The configuration class itself is also a bean instance

3. Method of proxyBeanMethods proxy bean s

Full:true guarantees that the component returned by how many times the bean object has been called is a single instance, and each call will look in the IOC container for existence

Lite:false does not check whether it has been created, how many times each bean object has been called and the components returned are newly created, multi-instance

@Configuration(proxyBeanMethods = false) //Tell SpringBoot that this is a configuration class==configuration file
public class MyConfig {

    /**
     * Full:Externally, regardless of how many times this component registration method is invoked in the configuration class to obtain a single instance object from a previously registered container
     * @return
     */
    @Bean //Add components to the container. The id of the component is the method name. The return type is the component type. The value returned is the instance of the component in the container
    public User user01(){
        User zhangsan = new User("zhangsan", 18);
        //user components depend on Pet components
        zhangsan.setPet(tomcatPet());
        return zhangsan;
    }

    @Bean("tom")
    public Pet tomcatPet(){
        return new Pet("tomcat");
    }
}
Other

@Controller @Service @Component @Respository

@Import

import(User.class,DBHelper.class)

Create bean instances of these two classes in a container

@Conditional - Conditional Assembly

Property Configuration

We know that in a project, a lot of time we need to use some configuration information, which may have different configurations in test and production environments, and may be modified later according to actual business conditions. In this case, we can not write these configurations to death in code, preferably in the configuration file.

Scenarios with a small amount of configuration information

For example, in a microservice architecture, the most common scenario is that a service needs to call another service to get information it provides. In the configuration file of the service, the address of the called service needs to be configured. For example, in the current service, we need to call an order microservice to get information about the order, assuming the port number of the order service is 8002. Then we can configure it as follows:

server:
  port: 8001

# Configure the address of a microservice
url:
  # Address of order micro-service
  orderUrl: http://localhost:8002

How do I get this configured order service address in the business code? We can solve this with the @Value annotation. Add an attribute to the corresponding class and use the @Value annotation on the attribute to get the configuration information in the configuration file as follows:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class ConfigController {

    private static final Logger LOGGER = LoggerFactory.getLogger(ConfigController.class);

    @Value("${url.orderUrl}")
    private String orderUrl;
    
    @RequestMapping("/config")
    public String testConfig() {
        LOGGER.info("=====The order service address obtained is:{}", orderUrl);
        return "success";
    }
}

The @Value annotation gives you the value corresponding to the key in the configuration file via ${key}. Let's start the project and when you type localhost:8080/test/config in your browser to request service, you can see that the console prints out the address of the order service:

Scenarios with multiple configuration information

One more problem is that as business complexity increases, there may be more and more micro-services in a project, and a module may need to call more than one micro-service to get different information, so you need to configure the addresses of multiple micro-services in a configuration file. However, in the code that calls these microservices, it would be too cumbersome and unscientific for such a microservice address to be introduced using the @Value annotation.

Therefore, in a real project, when the business is tedious and the logic is complex, you need to consider encapsulating one or more configuration classes. For example, if in the current service, a business needs to call order micro-service, user micro-service and shopping cart micro-service at the same time, get information about order, user and shopping cart respectively, and then do some logical processing on the information. Then in the configuration file, we need to configure the addresses of these microservices:

# Configure addresses for multiple microservices
url:
  # Address of order micro-service
  orderUrl: http://localhost:8002
  # Address of user microservice
  userUrl: http://localhost:8003
  # Address of Shopping Cart Micro Service
  shoppingUrl: http://localhost:8004

@Component
@ConfigurationProperties(prefix = "url")
public class MicroServiceUrl {

    private String orderUrl;
    private String userUrl;
    private String shoppingUrl;
    // Omit get and set methods
}

Use the @ConfigurationProperties annotation and prefix to specify a prefix, then the attribute names in this class are those in the configuration after the prefix is removed, one-to-one. That is, the prefix name + attribute name is the key defined in the configuration file. At the same time, this class needs to be annotated with @Component, put this class as a component in the Spring container, let Spring manage it, and inject it directly when we use it.

Note that using the @ConfigurationProperties annotation requires importing its dependencies

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

Interceptor

Content of Spring MVC

Processor interceptors for SpringMVC are similar to Filter filters in Servlet development for preprocessing and postprocessing processors. Developers can define some interceptors themselves to implement specific functions.

The difference between a filter and an interceptor:

Interceptor is a specific application of AOP thought.

Filter

Part of the servlet specification that any java web project can use

After configuring /* in url-pattern, all resources to be accessed can be intercepted

Interceptor

Interceptors are the Spring MVC framework itself, and can only be used by projects that use the Spring MVC framework

Interceptors will only intercept access to the controller methods, and will not intercept access to jsp/html/css/image/js

Interceptors in springboot are placed in ioc containers

Understand

aop proxy, with additional processing before and after the controller method, preHandle returns true as release and false as intercept

Example

Write an interceptor

package com.kuang.interceptor;
 
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
public class MyInterceptor implements HandlerInterceptor {
 
    //Execute before method of request processing
    //If true is returned to execute the next interceptor
    //Do not execute the next interceptor if false is returned
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("------------Pre-processing------------");
        return true;
    }
 
    //Execute after request handling method execution
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("------------After treatment------------");
    }
 
    //Perform cleanup after dispatcher Servlet processing.
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("------------Clear------------");
    }
}

Write a Controller to receive requests

package com.kuang.controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
 
//Test interceptor controller
@Controller
public class InterceptorController {
 
    @RequestMapping("/interceptor")
    @ResponseBody
    public String testFunction() {
        System.out.println("The method in the controller executed");
        return "hello";
    }
}

Interceptor Configuration

@Configuration
public class IntercepterConfig implements WebMvcConfigurer {

    //This is equivalent to configuring bean s in a configuration file, essentially injecting LoginIntercepter objects through IOC only once
    @Bean
    LoginIntercepter loginIntercepter(){
        return new LoginIntercepter();
    }

    @Bean
    CorsIntercepter corsIntercepter() {return new CorsIntercepter();}

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        //Intercept all paths, this cross-domain configuration is on top
        registry.addInterceptor(corsIntercepter()).addPathPatterns("/**");

        registry.addInterceptor(loginIntercepter()).addPathPatterns("/api/v1/pri/*/*/**")
                //Do not block which paths, note to start with/
                .excludePathPatterns("/api/v1/pri/user/login","/api/v1/pri/user/register");
        WebMvcConfigurer.super.addInterceptors(registry);
    }
}

excludePathPatterns Unblocked Path (controller s method)

Path intercepted by addPathPatterns (controller s method)

Topics: Java Spring Spring Boot