Using SLF4J and Logback

The good friends Commons Logging and Log4j are introduced earlier. One of them is responsible for the log API, and the other is responsible for implementing the bottom layer of the log. It is very easy to develop when used together.

Some children’s shoes may also have heard of SLF4J and Logback. These two things also look like logs, what are they?

In fact, SLF4J is similar to Commons Logging and is also a log interface, while Logback is similar to Log4j and is a log implementation.

Why with Commons Logging and Log4j, SLF4J and Logback pop up again? This is because Java has a very long history of open source. Not only is OpenJDK itself open source, but almost all of the third-party libraries we use are open source. A particular feature of the rich open source ecosystem is that for the same function, several competing open source libraries can be found.

Because of dissatisfaction with the interface of Commons Logging, some people engaged in SLF4J. Because of dissatisfaction with the performance of Log4j, some people engaged in Logback.

Let’s first take a look at how SLF4J improves the Commons Logging interface. In Commons Logging, we want to print the log, sometimes we have to write:

Spelling strings is a very troublesome thing, so the log interface of SLF4J has been improved as follows:

We can guess by guessing. The log interface of SLF4J passes in a string with placeholders, and the placeholders are automatically replaced with the following variables, so it looks more natural.

How to use SLF4J? Its interface is actually almost identical to Commons Logging:

Compare the interfaces of Commons Logging and SLF4J:

Commons LoggingSLF4J
org.apache.commons.logging.Logorg.slf4j.Logger
org.apache.commons.logging.LogFactoryorg.slf4j.LoggerFactory

The difference is that Log becomes Logger, and LogFactory becomes LoggerFactory.

Using SLF4J and Logback is similar to using Commons Logging and Log4j as mentioned earlier. First download SLF4J and Logback respectively , and then put the following jar packages on the classpath:

  • slf4j-api-1.7.x.jar
  • logback-classic-1.2.x.jar
  • logback-core-1.2.x.jar

Then use SLF4J’s Logger and LoggerFactory. Similar to Log4j, we still need a Logback configuration file, logback.xmlput it on the classpath, and configure it as follows:

Run it to get output similar to the following:

Judging from the current trend, more and more open source projects have shifted from Commons Logging plus Log4j to SLF4J plus Logback.

practise

According to the configuration file, observe the log files written by Logback.

slf4j+logback

summary

SLF4J and Logback can replace Commons Logging and Log4j;

Always use SLF4J’s interface to write logs. Using Logback only requires configuration and no code modification.

Java NullPointerException

Of all the RuntimeExceptionexceptions, Java programmers are probably most familiar with NullPointerException.

NullPointerException is the null pointer exception, commonly known as NPE. This exception is usually thrown by the JVM if an object is null called, its methods are called or its fields are accessed , for example:NullPointerException

The concept of pointers is actually derived from the C language, and there are no pointers in the Java language. The variables we define are actually references, Null Pointer is more precisely Null Reference, but the difference between the two is not much.

Handling NullPointerException

If encountered NullPointerException, how should we deal with it? First of all, it must be clear that it NullPointerExceptionis a code logic error. When encountered NullPointerException, follow the principle of early exposure and early repair. It is strictly prohibited to use catchto hide such coding errors:

Good coding practices can greatly reduce NullPointerExceptionthe occurrence of, for example:

Member variables are initialized when they are defined:

A lot can be avoided by using an empty string ""instead of the default , and when writing business logic, it is much safer to use an empty string for unfilled .nullNullPointerException""null

Returns an empty string "", an empty array instead of null:

This saves the caller from having to check whether the result is null.

If the caller must make nulljudgments, such as returning to nullindicate that the file does not exist, then consider returning Optional<T>:

In this way, the caller must pass the Optional.isPresent()judgment whether there is a result.

Locating NullPointerException

If generated NullPointerException, for example, a.b.c.x()when called, the NullPointerExceptionreason may be:

  • ayes null;
  • a.byes null;
  • a.b.cyes null;

Determining exactly which object was nullpreviously only able to print logs like this:

Starting from Java 14, if generated NullPointerException, the JVM can give detailed information to tell us nullwho the object is. Let’s look at an example:

You can NullPointerExceptionsee similar in the details of ... because "<local1>.address.city" is null, meaning the cityfield is null, so we can quickly locate the problem.

This enhanced NullPointerExceptiondetail is new in Java 14, but is off by default, we can -XX:+ShowCodeDetailsInExceptionMessagesenable it by adding a parameter to the JVM:

summary

NullPointerExceptionIt is a common logic error in Java code, which should be exposed and repaired early;

NullPointerExceptionDetailed error information can be viewed by enabling Java 14’s Enhanced Exception Information.

How to use Log4j

Commons Logging was introduced earlier, which can be used as a “log interface”. And the real “logging implementation” can use Log4j.

Log4j is a very popular logging framework, the latest version is 2.x.

Log4j is a component-based log system, and its architecture is roughly as follows:

When we use Log4j to output a log, Log4j automatically outputs the same log to different destinations through different Appenders. E.g:

  • console: output to the screen;
  • file: output to a file;
  • socket: output to a remote computer through the network;
  • jdbc: output to database

In the process of outputting logs, Filter is used to filter which logs need to be output and which logs do not need to be output. For example, only output ERRORlevel logs.

Finally, format the log information through Layout, for example, automatically add information such as date, time, method name, etc.

Although the above structure is complex, when we actually use it, we do not need to care about the API of Log4j, but configure it through the configuration file.

Taking XML configuration as an example, when using Log4j, we can put a log4j2.xmlfile classpathdown to let Log4j read the configuration file and output the log according to our configuration. The following is an example of a configuration file:

Although configuring Log4j is tedious, once configured, it is very convenient to use. For the above configuration file, all INFOlevel logs will be automatically output to the screen, and ERRORlevel logs will not only be output to the screen, but also output to the file at the same time. And, once the log file reaches the specified size (1MB), Log4j will automatically cut the new log file and keep up to 10 copies.

It is not enough to have a configuration file, because Log4j is also a third-party library, we need to download Log4j from here , after decompression, put the following 3 jar packages into classpathit:

  • log4j-api-2.x.jar
  • log4j-core-2.x.jar
  • log4j-jcl-2.x.jar

Because Commons Logging will automatically discover and use Log4j, put the downloaded one in the previous commons-logging-1.2.jarsection classpath.

To print the log, you only need to write it in the way of Commons Logging, without changing any code, you can get the log output of Log4j, similar to:

Best Practices

In the development phase, the Commons Logging interface is always used to write logs, and there is no need to introduce Log4j in the development phase. If you need to write the log to a file, you only need to put the correct configuration file and the jar package related to Log4j classpath, and you can automatically switch the log to use Log4j to write without modifying any code.

practise

According to the configuration file, observe the log file written by Log4j.

commons logging + log4j

summary

Logs are implemented through Commons Logging, and Log4j can be used without modifying the code;

To use Log4j, you only need to put log4j2.xml and related jars into the classpath;

If you want to replace Log4j, you only need to remove log4j2.xml and related jars;

Only when you extend Log4j, you need to refer to the interface of Log4j (for example, the function of encrypting logs and writing them to the database needs to be developed by yourself).

Detailed WebSecurityConfigurerAdapter

This article will detail the WebSecurityConfigurerAdapter in security.

Overview
Today we are going to further learn how to customize Spring Security. We have mentioned WebSecurityConfigurerAdapter many times, and we know that the automatic configuration in Spring Boot is actually the Spring Boot Web Security imported through the SecurityAutoConfiguration general configuration class under the automatic configuration package. Configuration class SpringBootWebSecurityConfiguration to configure.

SpringBootWebSecurityConfiguration source code

Common method
WebSecurityConfigurerAdapter class diagram

Common configuration
Let’s paste the common configuration of WebSecurityConfigurerAdapter in the project

I believe someone has noticed that I have overridden (@Override) three configure methods in the WebSecurityConfigurerAdapter above. We generally customize our security access policy by customizing these three methods.

Authentication Manager Configuration Methods
AuthenticationManagerBuilder (Authentication Manager Builder)

void configure(AuthenticationManagerBuilder auth) is used to configure AuthenticationManager. To put it bluntly, it manages all UserDetails related, including PasswordEncoder passwords, etc. If you are not clear, you can find out through UserDetail in Spring Security. This article does not do a specific analysis and explanation of AuthenticationManager, and there will be a special article about this later.

Common usage

Core filter configuration method
WebSecurity (WEB security)

void configure(WebSecurity web) is used to configure WebSecurity . And WebSecurity is based on Servlet Filter to configure springSecurityFilterChain . The springSecurityFilterChain is delegated to the Spring Security core filter Bean DelegatingFilterProxy . The related logic can be found in WebSecurityConfiguration. We generally don’t customize WebSecurity too much, and use more of its ignoring() method to ignore Spring Security’s control of static resources.

Security filter chain configuration method
HttpSecurity (HTTP request security processing)

void configure(HttpSecurity http) This is what we use the most to configure HttpSecurity . HttpSecurity is used to build a security filter chain SecurityFilterChain . The SecurityFilterChain is eventually injected into the core filter. HttpSecurity has many configurations that we need. We can use it to customize the security access policy. So we have a separate chapter to explain this stuff.

HttpSecurity configuration
HttpSecurity is the focus of the following articles, and we will actually operate it to achieve some practical functions. So this article will focus on it.

HttpSecurity class diagram

Default Allocation

The above is the default configuration of Spring Security in Spring Boot. Through the above configuration, your application has the following functions:

  • All requested access requires authorization.
  • Use the form form to log in (the default path is /login), which is the login page we saw in the previous articles.
  • Prevent CSRF attack, XSS attack.
  • Enable HTTP Basic Authentication

Summary of this article
This article introduces the knowledge and content related to WebSecurityConfigurerAdapter in detail, and will introduce the knowledge related to HttpSecurity in detail later, which is also the most used place in normal development.

The difference between BIO, NIO, and AIO

Many articles just throw a bunch of definitions and some vivid examples when talking about BIO, NIO, and AIO. Seems to be well understood. However, the most basic essential principles are not revealed. If you do not start from the principle of IO, it is difficult to understand the difference between the three. In this article, you will get: the performance difference between synchronous/asynchronous + blocking/non-blocking; the difference between BIO, NIO, and AIO; understanding and implementing multiplexing when NIO operates Sockets; at the same time, master the bottom and core operation skills of IO.

IO principle in Java

First of all, IO in Java depends on the operating system kernel. The IO reading and writing in our program actually calls the two system calls of read and write in the operating system kernel.

How does the kernel interact with IO?

  1. The network card receives the network data transmitted through the network cable, and writes the network data to the memory.
  2. 2When the network card writes the data into the memory, the network card sends an interrupt signal to the cpu, and the operating system can know that there is new data coming, and then process the data through the network card interrupt program.
  3. Write the network data in the memory to the receive buffer of the corresponding socket.
  4. After the data in the receive buffer is written, the application starts data processing.

A simple example of socket code corresponding to abstraction to java is as follows:

It can be seen that this process is very similar to the network IO of the underlying kernel, which is mainly reflected in accept() waiting for a request from the network, and then the bytes[] array is used as a buffer to wait for the data to be filled before processing. The difference between BIO, NIO, and AIO is whether these operations are synchronous or asynchronous, blocking or non-blocking.

So we introduce the concepts of synchronous and asynchronous, blocking and non-blocking.

Synchronous and Asynchronous

Synchronization and asynchrony: Synchronization means that when the completion of a task needs to depend on another task, the dependent task can be completed only after waiting for the dependent task to complete. This is a reliable task sequence. Either all successes succeed, and all failures fail, and the status of the two tasks can be kept the same. Asynchronous means that there is no need to wait for the dependent task to complete, but only to notify the dependent task of what work to complete, and the dependent task is executed immediately, as long as the entire task is completed by itself. As for whether the dependent task is actually completed in the end, the task that depends on it cannot be determined, so it is an unreliable task sequence. We can use phone calls and text messages to describe synchronous versus asynchronous operations well.

Synchronization and asynchrony refer to whether each method in an execution flow must depend on the completion of the previous method before it can continue to execute. Suppose our execution process is: method one and method two in turn.

Synchronization means that once the call has started, the caller must wait until the method call returns before continuing the subsequent behavior. That is, method 2 must wait until method 1 is executed before it can be executed.

Asynchronous means that the call returns immediately, and the caller can continue the subsequent behavior without waiting for the execution of the code in the method to end. (The code in the specific method may be called back after it is executed by another thread.) That is, when method 1 is executed, it is directly handed over to other threads for execution, and it is not executed by the main thread, so it will not block the main thread, so method 2 does not have to wait until method 1 is completed to start execution.

Synchronization and asynchrony focus on whether the executor of the method is the main thread or another thread. The main thread needs to wait for the method execution to complete, and other threads do not need to wait for the method call to return immediately, and the main thread can directly execute the next code.

Synchronous and asynchronous is to achieve efficiency difference from the coordination between multiple threads.

Why do you need asynchrony? The author believes that the essence of asynchrony is to solve the blocking of the main thread, so many discussions on the Internet have made four combinations of synchronous asynchronous and blocking non-blocking. One of them has the situation of asynchronous blocking. If asynchronous is also blocking? So why do you want to perform asynchronous operations specifically?

Blocking and Non-Blocking
Blocking and non-blocking: Blocking and non-blocking are mainly in terms of CPU consumption. Blocking means that the CPU stops and waits for a slow operation to complete the CPU before completing other things. Non-blocking means that the CPU does other things while the slow operation is executing, and when the slow operation is completed, the CPU then completes the subsequent operations. Although the non-blocking method on the surface can significantly improve the utilization of the CPU, it also brings another consequence that the thread switching of the system increases. Whether the increased CPU usage time can compensate for the switching cost of the system needs to be carefully evaluated.

Blocking and non-blocking refer to whether to do nothing in place when a single thread encounters a synchronous wait.

Blocking means that after encountering a synchronization wait, it has been waiting for the synchronization method to complete the processing in place.

Non-blocking refers to encountering synchronous waiting, not waiting in place, do other operations first, and then observe whether the synchronization method is completed after a time interval.

Blocking and non-blocking concern whether the thread is waiting in place.

The author believes that blocking and non-blocking can only be combined with synchronization. Asynchronous is naturally non-blocking, and this non-blocking is for the main thread. (Some people may think that putting a blocking operation in an asynchronous method is asynchronous blocking, but think about it, it is precisely because it is a blocking operation that it is put into an asynchronous method, do not block the main thread)

Example to explain
Haidilao is delicious, but there are often queues. Let’s take this example from life to explain.

Customer A went to eat Haidilao and just sat and waited for an hour before eating hot pot. (BIO)
Customer B went to eat Haidilao. He saw that he had to wait for a long time, so he went to the mall, and every time he went shopping for a while, he ran back to see if he was in line. So he ended up shopping and eating Haidilao. (NIO)
Customer C went to eat Haidilao. Since he is a senior member, the store manager said, you can go to the mall to play casually, and I will call you immediately when there is a seat. So customer C doesn’t have to sit and wait, and don’t have to run back every once in a while to see if they can wait, and finally eat Haidilao (AIO)
Which way is more efficient? Is it obvious at a glance?

BIO
BIO is a traditional java.io package. It is implemented based on the stream model. The interaction method is synchronous and blocking. That is to say, when reading the input stream or output stream, the thread will be blocked until the read and write actions are completed. There, calls between them are in a reliable linear order. Its advantage is that the code is relatively simple and intuitive; the disadvantage is that the efficiency and scalability of IO is very low, and it is easy to become an application performance bottleneck.

The full name of BIO is Blocking IO, which is the traditional IO model before JDK1.4, and itself is a synchronous blocking mode. After the thread initiates an IO request, it keeps blocking the IO until the buffer data is ready, and then goes to the next step. For network communication, it is a request-response method. Although the upper-layer application development is simplified, there is a huge bottleneck in terms of performance and reliability. Imagine if each request needs to create a new thread for special processing, then in high In a concurrent scenario, machine resources are quickly exhausted.

NIO
NIO is the java.nio package introduced in Java 1.4. It provides new abstractions such as Channel, Selector, Buffer, etc. It can build multiplexed, synchronous non-blocking IO programs, and at the same time provides high-performance data operations that are closer to the underlying operating system. Way.

NIO, also called Non-Blocking IO, is a synchronous non-blocking IO model. After the thread initiates an io request, it returns immediately (non-blocking io). Synchronization means that you must wait for the data in the IO buffer to be ready. Non-blocking means that the user thread does not wait for the IO buffer in place. You can do some other operations first, but you need to poll regularly to check whether the IO buffer data is ready. .

NIO in Java means new IO. In fact, it is NIO plus IO multiplexing technology. Ordinary NIO is thread polling to see if an IO buffer is ready, while new IO in Java refers to threads polling to see which ones are ready in a bunch of IO buffers, which is an idea of ​​IO multiplexing . In the IO multiplexing model, the task of checking whether the IO data is ready is handed over to the system-level select or epoll model, which is monitored by the system to reduce the burden on user threads.

NIO mainly integrates three technologies: buffer, channel, and selector. Data is obtained through zero-copy buffer, and each client registers on the selector (multiplexer) through channel. The server continuously polls the channel to obtain information about the client. There are four status flags on the channel: connect, accept (blocking), read (readable), and write (writable). Follow up with the identification. So a server can receive an infinite number of channels. No need to open a new thread. Greatly improved performance.

AIO
AIO is a package introduced after Java 1.7. It is an upgraded version of NIO. It provides an asynchronous non-blocking IO operation mode, so people call it AIO (Asynchronous IO). Asynchronous IO is implemented based on events and callback mechanisms, that is, application operations. After that, it will return directly and will not be blocked there. When the background processing is completed, the operating system will notify the corresponding thread to perform subsequent operations.

AIO is a true asynchronous non-blocking IO model. In the above NIO implementation, the user thread needs to poll regularly to check whether the IO buffer data is ready, which occupies the application thread resources. In fact, polling is equivalent to blocking, and does not really liberate the current thread, because it still needs to query which IO ready. The real ideal asynchronous non-blocking IO should let the kernel system complete, and the user thread only needs to tell the kernel that when the buffer is ready, notify me or execute the callback function I handed you.

AIO can perform real asynchronous operations, but it is more complicated to implement. There are very few operating systems that support pure asynchronous IO. Currently, windows are implemented by IOCP technology, while on Linux, the bottom layer is still implemented by epoll.

Implementing Permission Management System Based On Spring Security

Slightly more complex background systems will involve user rights management. What are user rights? My understanding is that permission is the centralized management of data (the entity class of the system) and the operations that can be performed on the data (addition, deletion, search, and modification). To build a usable permission management system, three core classes are involved: one is the user User, the other is the role, and the last is the permission Permission. Next, this article will introduce how to build an interface-level permission management system step by step based on Spring Security 4.0.

  1. Related concepts
    Permission = Resource + Privilege
    Role = a set of low-level permissions
    User = collection of roles (high-level roles)
  2. Spring Security’s maven dependencies
    Although the Spring Boot version has reached 2.0, some pits were found when it was used before, so it is recommended to use the relatively stable version 1.5 for the time being.
  1. Define the permission set of the system
    Permissions are a collection of resources and the operations that can be performed on them. For our system, almost all entity classes can be regarded as a resource, and the common operations are adding, deleting, checking, and modifying four categories. Of course, according to our actual business needs, there may be other special operations, such as ours here Added an action to import users. Here is a brief list of two basic permission sets:

In the definition of permissions, the key is the key of resourceId and privileges, and the combination of the two will be used to judge the user’s permissions later. I use the form of resourceId-privilege here to uniquely represent an operation on a resource.

  1. Role-related operations
    The resource and operation permission collection class defines JsonPermissions:

The role class defines Role:

  1. Assign roles to users
    The Spring Security framework provides a basic user interface UserDetails, which provides basic user-related operations, such as obtaining username/password, whether the user account has expired, and whether user authentication has expired, etc. We need to implement this when we define our own User class. interface.
  1. Create initial roles and super administrators for the system
    If we impose access restrictions on all interfaces of the system, who will log in to the system as the initial user and create other users? Therefore, we need to define the initial role and initial user of the system, and automatically enter the initial role and initial user into the system when the system starts, and then use the initial user to log in to the system to create other business-related users. Define the super administrator role of the system: roles.json

Defines the initial admin user for the system: users.json

  1. Load system initialization role and user data
    When the system is deployed, the initialization roles and users of the system need to be automatically loaded into the database, so that they can be used for normal login. Use the @Component and @PostConstruct annotations to automatically import initial roles and users at system startup.
  1. Implement your own UserDetailsService
    Customize user information in UserDetailService, and set all Permissions related to user role role to Authorities of Authentication for PermissionEvaluator to judge user permissions. Note that the form of resourceId-privilege is used here for splicing and storage. My user information here is stored in the MongoDB database, or it can be replaced with other databases.

9.Config UserDetailsService

  1. The back-end interface implements access restrictions based on permissions
    Add the PreAuthorize annotation to the interface method that requires access restrictions. In this annotation, we can use a variety of verification methods, the more common ones are hasPermisson and hasRole. Similar to PreAuthorize, there is the PostAuthorize annotation. It is also better to understand from the literal meaning that PreAuthorize performs verification before accessing the interface, and PostAuthorize performs verification when the result is returned after accessing the interface.

By analogy, corresponding access restrictions can be added to the interfaces that need to restrict user access.

  1. Implement your own PermissionEvaluator
    After adding the PreAuthorize annotation to the interface method, you also need to implement your own PermissionEvaluator. Spring Security will verify the validity of the resource that the currently logged-in user is accessing and the operations performed on the resource in the hasPermission() method.
    Note that the targetDomainObject here is the resourceId we defined before, and the permission is the privilege. When verifying, it should be combined into a format consistent with the format stored in the UserDetailsService. Here we use – dash to connect.
  1. Annotation support
    After implementing PermissionEvaluator, the annotation of globalMethodSecurity must be added, otherwise the permission judgment added on the interface will not take effect. Add this annotation to the inherited class of SpringBootServletInitializer to enable method security.
  1. Access test: 403
    Since the user I am currently logged in has not set the role and access rights for it, I do not have access to the list interface, and the following 403 error occurs when I forcibly access it.
  1. Front-end pages implement personalized pages according to permissions
    It doesn’t end when the backend implements interface-level access restrictions. For the part of the user-visible interface, users with different roles should see different interfaces according to their roles when they log in to the system. Our current experience is that after the user logs in successfully, the user’s permission list is returned to the front-end, and then the front-end judges the permissions. If there is no permission, the corresponding button or function module is hidden. Through the combination of front and back ends, users can only see the operation interface and data within the scope of their permissions. At the same time, even if some users directly modify the interface parameters to obtain data, they will be judged twice at the back end. Make sure that users can see their own data and can only perform operations within the scope of their authority!

Java Several Methods Of Converting Between Map and Object

Java Json And Object Conversion

1.Java object to JSON object

2.Java object to JSON string

3.JSON object to JSON string

4.JSON object to java object

5.json string to JSON object

6.JSON string to Java object

7.JSON string to list

Interview Question About Spring Cloud Context, You Can Answer Like This

Spring cloud, I believe everyone is familiar with it. Spring cloud is a cloud application development tool based on Spring boot; Spring boot focuses on a single individual that is fast and easy to integrate.

So the question is, what is the context in the Spring cloud monomer?

First of all, let’s recall the application context of Spring. What is the application context? It can be simply understood that it is a container object that puts the objects you need Spring to manage for you into the container. The application context is an abstract representation of the Spring container, and our common ApplicationContext is essentially a powerful interface that maintains the bean definition and the cooperative relationship between objects. The core of Spring is the container, and the container is not unique. The framework itself provides many container implementations, which are roughly divided into two types: one is the less commonly used BeanFactory, which is the simplest container and can only provide basic DI function; another is the application context derived from inheriting the BeanFactory, and its abstract interface is the ApplicationContext we mentioned above, which can provide more enterprise-level services, such as parsing configuration files, etc., which is also the application context. The most common use case for instance objects. With the context object, we can register objects that need to be managed by Spring with the container. For the context abstract interface, Spring also provides us with multiple types of container implementations, which can be selected in different application scenarios:

  • AnnotationConfigApplicationContext: Load context definitions from one or more java-based configuration classes, suitable for java annotations
  • ClassPathXmlApplicationContext: Load context definitions from one or more xml configuration files under the classpath, suitable for xml configuration
  • XmlWebApplicationContext: Load context definitions from one or more xml configuration files under the web application, suitable for xml configuration
  • FileSystemXmlApplicationContext: Load context definitions from one or more xml configuration files under the file system, that is, load xml configuration files in the system disk
  • AnnotationConfigWebApplicationContext: specially prepared for web applications, suitable for annotation methods

In this way, we only need to configure the managed objects (we call them beans in Spring) and the collaboration relationship between beans, load the configuration into the IOC container through the application context, and let Spring manage the objects for us. When the time comes, you can get the bean from the container, because the container can provide the object management service you want for your program.

So in fact, there is a concept of “bootstrap context” in a Spring cloud application, which is the parent context of the main application. The bootstrap context is responsible for loading configuration properties from the configuration server, as well as decrypting properties in external configuration files. Unlike the main application, which loads properties in the application, the bootstrap context loads properties in the bootstrap. Properties configured in bootstrap have higher priority, so they cannot be overridden by local configuration by default.

If you want to disable the bootstrap process, set spring.cloud.bootstrap.enabled=false.

Application scenarios of bootstrap configuration files:

  • When using the Spring Cloud Config configuration center, you need to add configuration properties connected to the configuration center in the bootstrap configuration file to load the configuration information of the external configuration center
  • Some fixed properties that cannot be overridden
  • Some encryption/decryption scenarios

The application configuration file is mainly used for automatic configuration of Spring Boot projects

OK, the context is over.

Spring Boot gets the file under java resources

Spring Boot gets the files under java resources Springboot gets the directories under the resources directory (for example: get the template directory under the resources directory):
method 1:

Method 2: