Spring boot highlights

1. springboot controller singleton
In Spring, the controller is singleton by default, because singleton is not thread safe.

So we need to pay attention to the following points

  1. Do not define member variables in the Controller, which may cause data confusion.
  2. In case it is necessary to define a non static member variable, set it to the multi instance mode through the annotation @ Scope("prototype").
  3. Use ThreadLocal variable in Controller to solve multithreading problem

spring bean scope:

singleton: singleton mode. When spring creates an applicationContext container, spring will want to initialize all instances of the scope. Adding lazy init can avoid preprocessing;

Prototype: prototype mode. Each time the bean is obtained through getBean, a new instance will be generated. After creation, spring will no longer manage it;

2. Springboot environment variable configuration

During the development process, not all configuration files can be written to yaml or properties files. You may need to read them from the container dynamically. Let's see how to configure them

Now let's see if we use environment variables to configure our parameters, as follows:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: ${DEMO_APP_JDBC_URL:jdbc:mysql://127.0.0.1/demo?serverTimezone=Asia/Shanghai}
    username: ${DEMO_APP_JDBC_USERNAME:demo}
    password: ${DEMO_APP_JDBC_PASSWORD:demo}
    hikari:
      maximum-pool-size: ${DEMO_APP_JDBC_POOL_MAX_SIZE:30}
      max-lifetime: ${DEMO_APP_JDBC_POOL_MAX_LIFE_TIME:60000}
      minimum-idle: ${DEMO_APP_JDBC_POOL_MIN_SIZE:5}

The above uses ${ENV:defauleValue} to configure the relevant parameters of our application. If our operating environment is configured with the environment variables used above, the configuration in the environment variables will be used. If there is no configuration, the default will be used. For example, I configured the environment variable demo_ APP_ JDBC_ POOL_ MAX_ If size = 100, the maximum number of connections in the connection pool in the application becomes 100.

It tastes better with docker

3. restful interface

Current applications are basically separated from the front and back ends, so the back-end interfaces are basically restful interfaces. What should I do?

Add the annotation @ RestController on the controller class to generate a restful interface

@The function of RestController is equivalent to @ Controller + @ResponseBody

@RestController
@RequestMapping("/api/v1/h5Adapter")
@Api(description = "server-h5-adapter")
public class BaMessageConverterController {

4. Difference between @ ResponseBody and @ RequestBody

@ResponseBody acts on a method, @ ResponseBody means that the return result of the method is directly written into the HTTP response body. Generally, AJAX is used when asynchronously obtaining data. After using @ RequestMapping, the return value is usually resolved to a jump path, but after adding @ ResponseBody, the return result will not be resolved to a jump path, Instead, it is written directly into the HTTP response body. For example, if you get json data asynchronously and add @ ResponseBody, json data will be returned directly@ RequestBody inserts the HTTP request body into the method and writes the request body to an object using an appropriate HttpMessageConverter.

@RequestBody is used on the formal parameter list to encapsulate the fixed format data [xml format or json, etc.] sent from the foreground into the corresponding JavaBean object. One object used during encapsulation is the HttpMessageConverter configured by default, which is parsed and then encapsulated on the formal parameter.
 

5,@Schedule

Timing tasks are almost standard configuration of the project. SpringBoot has built-in spring schedule timing framework, which adds annotated methods to timing tasks through annotation driven mode, and executes them regularly according to the configured timing information

The main steps are as follows:

1. Turn on the timer

@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
@EnableCircuitBreaker
@EnableCaching
@EnableScheduling
public class Application {
​
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
​

2. Annotate the method

    //Every day at 1 a.m
    @Scheduled(cron = "0 0 1 * * ?")
    public void doTask() {
    
    }

6. async asynchronous call

Asynchronous call mainly handles some tasks that do not require timely return, which is supported by spring boot

async is used to implement asynchronous calls in spring boot

Annotation based usage includes the following three steps:

  1. Add @ EnableAsync to the startup class (you can also add @ EnableAsync to the configuration class)

  2. Complete the import of asynchronous thread pool in the configuration class (this one can be omitted, and the default one is adopted)

  3. Methods that need to be called asynchronously plus @ Async

Define thread pool

package com.aispeech.bj.bams.msproduct.config;
​
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
​
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
​
@Configuration
@EnableAsync(mode = AdviceMode.ASPECTJ)
public class ExecutorConfig {
​
    /** Set the ThreadPoolExecutor's core pool size. */
    private int corePoolSize = 10;
    /** Set the ThreadPoolExecutor's maximum pool size. */
    private int maxPoolSize = 300;
    /** Set the capacity for the ThreadPoolExecutor's BlockingQueue. */
    private int queueCapacity = 10;
​
    @Bean
    public Executor myAsync() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix("MyExecutor-");
        // Rejection policy: how to handle new tasks when the pool has reached max size
        // CALLER_RUNS: the task is not executed in the new thread, but in the thread of the caller
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
​
}
​

Using asynchronous @ Async annotations

  @Async("myAsync")
    void notifyProductInfo(String thirdPartyId, ThirdPartyProductVO thirdPartyProductVO) {}

7. request acquisition method and thread safety

Request is a request from the front end. How can we safely obtain the request and thread safe request can get the correct data? There are mainly the following ways

1. Static class acquisition

HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();

2. Function parameters

After obtaining the request object in the Controller, if you want to use the request object in other methods (such as service method, tool class method, etc.), you need to pass the request object as a parameter when calling these methods

At this time, the request object is a method parameter, equivalent to a local variable, which is undoubtedly thread safe.

@RequestMapping("/test")
    public void test(HttpServletRequest request) {
        ......
    }

3. Automatic injection

    @Autowired
    private HttpServletRequest request; //Auto inject request

The object is a thread local variable, so the request object is also a thread local variable; This ensures the thread safety of the request object.

There is no thread safety problem. In fact, spring injects a proxy class

Tags: Java Spring Spring Boot Back-end

Posted on Wed, 24 Nov 2021 01:36:42 -0500 by Newro