This is the seventh day of my participation in the August More text Challenge. For details, see:August is more challenging

Introduction to SpringBoot

1.1 Introduction to SpringBoot

SpringBoot is a new framework provided by the Pivotal team that is designed to simplify the initial setup and development of new Spring applications. The framework is configured in a way that eliminates the need for developers to define boilerplate configurations. In this way, Spring Boot is committed to becoming a leader in the burgeoning world of rapid Application Development. SpringBoot enables faster development because configuration files are moved from XML to Java files, reducing configuration file writing.

1.2, JavaConfig

JavaConfig’s technology is designed to replace the current cumbersome configuration of XML files, and its most important alternative is the use of a lot of annotations.

1.2.1 Project preparation

<properties>
        <spring.version>5.0.8. RELEASE</spring.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.22</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>
</dependencies>
Copy the code

1.2.2 Inversion of Control of the configuration file

1.2.2.1 create Bean

public class OneBean {}Copy the code

1.2.2.2 create configuration class

// The configuration class annotation is pasted to indicate that the class is a configuration class
@Configuration
public class AppConfig {
    / / the Bean instance, with the annotation method as an example, on the function is equivalent to: < Bean name = "someBean" class = "cn. Linstudy. Onfig. OmeBean" > < / Bean >
    @Bean
    public OneBean oneBean(a){
        // Note: The return object of the instance method is managed by the Spring container
        return newSomeBean(); }}Copy the code

1.2.2.3, test,

@RunWith(SpringRunner.class)
// Reference the configuration class annotations
@ContextConfiguration(classes = AppConfig.class) 
public class App {
    @Autowired
    private ApplicationContext ctx;
    @Test
    public void testApp(a){
        OmeBean omeBean = ctx.getBean("omeBean", SomeBean.class); System.out.println(omeBean); }}Copy the code

1.2.3 Scanning components for configuration substitutes

1.2.3.1 Scan Bean components

When you learn about the Spring framework, Spring has four version tags (which represent the same meaning, just to mark the different objects represented). When the Spring container scanner detects classes labeled with templates, it automatically creates instance objects for those classes and gives them to the container to manage.

@Controller  // Mark the control layer
public class EmployeeController{}@Service    // Mark the service layer
public class EmployeeServiceImpl{}@Repository  // Mark the persistence layer
public class EmployeeDAOImpl{}@Component   / / other classes
public class EmployeeListener{}Copy the code

In addition to using the above annotations, we also need to configure them in the XML file.

<context:component-scan base-package="Specify the scanned package path"></context:component-scan>
Copy the code

Instead of JavaConfig, we need to post an annotation telling Spring that we need to scan the class and create the object.

@Component  // Type label
public class OmeBean {}Copy the code

The Spring component scans the annotations, scans the basePackages attribute to specify all labeled classes under the package and its subpackages, and creates objects for the Spring container to manage. If basePackages is not specified, all packages and their subpackages of the current class are scanned.

@Configuration
// The component scans the label
@ComponentScan(basePackages ="cn.linstudy.config") 
public class AppConfig {}Copy the code

1.2.4 @bean annotation

Create a OneBean class

@Setter
@Getter
public class OneBean {
    public OneBean(a) {
        System.out.println("OneBean is created");
    }
    public void init(a) {
        System.out.println("OneBean is initialized");
    }
    public void destroy(a) {
        System.out.println("OneBean destroyed"); }}Copy the code

1.2.4.2 Writing configuration class

@Scope("singleton")
@Bean(value = "ob",initMethod = "init", destroyMethod = "destroy")
public OomeBean oomeBean(a){
    return new OomeBean();
}
Copy the code

1.2.4.3,

  1. Name attribute in the bean tag = @Name /value attribute in the bean annotation.
  2. The ID attribute in the bena tag = the method name of the instance method.
  3. InitMethod property in the bean tag init-method = @bean annotation.
  4. Destruct-method in the bean tag = destroyMethod in the @bean annotation.
  5. The scope attribute in the bean tag = @Scope annotation in the instance method

1.2.5 Dependency injection for configuration classes instead of configuration files

1.2.5.1 Create a new class

public class TwoBean {}Copy the code
@Setter
@Getter
public class OneBean {
    private Two twoBean;
}
Copy the code

1.2.5.1 Implementation Method 1

We can implement dependency injection by calling instance methods directly.

JavaConfig implements a traditional dependency note:

  1. OmeBean objects can be obtained from containers.
  2. Twobeans can be obtained from the container.
  3. The bean obtained by the omeBean object through the getTwoBean() method should be equal to the twoBean object obtained from the container.
@Configuration
public class AppConfig {
    @Bean
    public OmeBean omeBean(a){
        OmeBean omeBean = new OmeBean();
        OmeBean.setTwoBean(twoBean());
        return someBean;
    }
    @Bean
    public TwoBean twoBean(a){
        return newTwoBean(); }}Copy the code

Points to note:

  1. The twoBean() method is propped up by the Spring container. The twoBean() method is propped up by the Spring container. Before each call, a container bean check is performed, and when one is found in the container, it is taken directly from the container. If not, the method is executed and the return value is placed in the container.

1.2.5.2,Implementation Mode 2

The second way is to inject the instance object to achieve dependency injection.

@Configuration
public class AppConfig {
    @Bean
    public OneBean omeBean(TwoBean twoBean){
        OneBean omeBean = new OneBean();
        omeBean.setTwoBean(twoBean);
        return omeBean;
    }
    @Bean
    public TwoBean twoBean(a){
        return newTwoBean(); }}Copy the code

1.2.6 Importing configuration files

1.2.6.1, @ import

The config class import annotation, attached to the config class, is equivalent to: <import resource=” XXX config.xml “></import> tag This tag is used to import between config classes.

1.2.6.2, @ ImportResource

<import resource=” XXX configuration.xml “></import> tag This tag is used to import between the configuration class and the configuration file.

1.2.7 Loading and Setting configuration Files

1.2.7.1, load,

We can use the @propertysource annotation for the resource configuration file load annotation, pasted on the configuration class, to load the properties type file into the Spring container.

<context:property-placeholder location="classpath:xxx.perperties"/>
Copy the code

1.2.7.2, values

When a configuration file is loaded, we can use the @value annotation to get the configuration data from the Properties configuration if we need a Value.

Create db.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=JDBC: mysql: / / 192.168.126.129:3306 / car_crm
jdbc.username=root
jdbc.password=123456
Copy the code
1.2.7.2.2 define a class
@Setter
@Getter
@ToString
public class MyDataSource {
    private String driverClassName;
    private String url;
    private String username;
    private String password;
}
Copy the code
1.2.7.2.3 Receive value
@PropertySource("classpath:db.properties")
@Configuration
public class AppConfig {


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

    @Bean
    public MyDataSource myDataSource(a){
        MyDataSource source = new MyDataSource();
        source.setDriverClassName(driverClassName);
        source.setUrl(url);
        source.setUsername(username);
        source.setPassword(password);
        returnsource; }}Copy the code

1.3 Principle of SpringBoot automatic assembly

1.3.1 Core SpringBoot annotations

At the heart of SpringBoot is the annotation @SpringBootApplication.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
Copy the code

1.3.2 Principle of SpringBoot Automatic Assembly

1.3.2.1, review

The SpringBoot launch loads a large number of autoconfiguration classes. The @springBootApplication contains the following three annotations:

  1. @SpringBootConfiguration: When we click in, we’ll find that the ground floor isConfigurationComment, to put it bluntly, is supportJavaConfigIs used to configure (Using Configuration to configure a class is equivalent to an XML file).
  2. @EnableAutoConfigurationOpen:Automatic configurationFunction.
  3. @ComponentScanHere it isscanningAnnotation, default is scanUnder the current classThe package. will@Controller/@Service/@Component/@RepositoryEtc. Annotations are loaded into the IOC container.

We entered the @ EnableAutoConfiguration, you will find he import @ implort annotations into AutoConfigurationImportSelector configuration class, The class has a getCandidateConfiguration configuration method of the method to get the candidate can read depends on the meta-inf/spring. Factories in a variety of candidate configuration class, introducing the dependence as a condition according to you preset various configurations.

1.3.2.2, AutoConfigurationImportSelector

@ EnableAutoConfiguration annotations to import a AutoConfigurationImportSelector automatic configuration class selectors, the class can implement the configuration class bulk load the spring container. The core method is getCandidateConfigurations purpose is the candidate’s configuration.

protected List<String> getCandidateConfigurations( AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
        getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());
    Assert.notEmpty(configurations, 
                    "No auto configuration classes found in META-INF/spring.factories. If you "
                    + "are using a custom packaging, make sure that file is correct.");
    return configurations;
}
Copy the code

1.3.2.3, SpringFactoriesLoader

Entrusted SpringFactoriesLoader getCandidateConfigurations method is to read the jars in the meta-inf/spring. Factories file, and load the configuration of automatic configuration object inside. This is the heart of auto-assembly. To write initiators, you need to write the meta-INF /spring.factories, which specify the auto-configuration classes of initiators and tell SpringBoot what configurations to place in advance. When the factories meet the requirements, you can directly load them.

1.2.3.4 RedisAutoConfiguration analysis

We configure class analysis with RedisAutoConfiguration.

If we click in to see the source code, we can find four annotations:

  1. @Configuration: indicates that this class is a configuration class.
  2. @ConditionalOnWebApplication(type = Type.SERVLET): indicates that the class that satisfies the project is Type type.servlet.
  3. @ConditionalOnMissingBean({RepositoryRestMvcConfiguration.class}): indicates that no one is in the environmentRepositoryRestMvcConfigurationThe Bean object takes effect. This is the entry point for custom configuration.
  4. @ConditionalOnClass({RepositoryRestMvcConfiguration.class}): indicates that it exists in the containerRepositoryRestMvcConfigurationThe Bean object.
@Configuration( proxyBeanMethods = false )
@ConditionalOnWebApplication( type = Type.SERVLET )
@ConditionalOnMissingBean({RepositoryRestMvcConfiguration.class})
@ConditionalOnClass({RepositoryRestMvcConfiguration.class})
@AutoConfigureAfter({HttpMessageConvertersAutoConfiguration.class, JacksonAutoConfiguration.class})
@EnableConfigurationProperties({RepositoryRestProperties.class})
@Import({RepositoryRestMvcConfiguration.class})
public class RepositoryRestMvcAutoConfiguration {
  public RepositoryRestMvcAutoConfiguration(a) {}@Bean
  public SpringBootRepositoryRestConfigurer springBootRepositoryRestConfigurer(a) {
    return newSpringBootRepositoryRestConfigurer(); }}Copy the code

1.4, pay attention to

1.4.1. Why is a war package not a JAR package

The default package for SpringBoot is a JAR package. In previous development, Tomcat and web projects were separate, and certain rules had to be met before Tomcat could deploy war packages. However, SpringBoot projects are built into Tomcat and can be deployed and run at once, so they are packaged as jars.

1.4.2 Functions of the spring-boot-starter in the POM. XML file

We are creating SpringBoot project, can be found that the introduction of many start, he collected on the market of the commonly used jar dependency, as well as a variety of package and of these rely on version management, avoid a lot of the version of the conflict, greatly simplifies our development, in the subsequent project if we need to introduce a dependent, Just introduce his start, the dependent version does not need to be introduced. Here are some common SpringBoot initiators:

Spring-boot-starter: a core starter that provides automatic configuration, logging, and YAML configuration support for Spring-boot-starter`Spring AOP``AspectJ`Section programming. Spring-boot-starter -freemarker: supports this command`FreeMarker`View Building Web applications spring-boot-starter-test: Supported`JUnit`, the test`Spring Boot`Application spring-boot-starter-web: This application is supported`Spring MVC`Building Web applications, including`RESTful`Application, use`Tomcat`As the default embedded container. Spring-boot-starter - ACTUATOR: Supports the use of Spring Boot actuator to monitor and manage production-level applications. Spring-boot-starter -logging: supports logging. By default, Logback is usedCopy the code

1.4.3 A powerful feature in MAVE — inheritance

Inheritance is a function of strong in Maven, inheritance can make child POM can get part of the configuration of the parent (groupId, version and dependencies, the build, dependencyManagement, etc.), Unified configuration and dependency management can be performed for sub-POMs.

1.4.4 Difference between DepencyManagement and dependencies

In SpringBoot’s POM file, place dependencies in DepencyManagement. Here’s the difference:

  1. Dependencies: If you do not write the dependency in your child project, the child project will inherit it from its parent project.
  2. DependencyManagement: this section declares dependencies and does not introduce them, so the subproject is required to show the dependencies. If you do not declare dependencies in a child project, they are not inherited from the parent project; The dependency is inherited from the parent project only if it is written in the child project and no version is specified, and both version and scope are read from the parent POM. Also, if a version number is specified in the subproject, the VERSION of the JAR specified in the subproject (partial inheritance) is used.

1.4.5 How to Start SpringBoot without Tomcat

Springboot is implemented programmatically using embedded Tomcat. The default port is 8080, which can be set using server.port in application.properties.

1.4.6 SpringBoot boot class main method springApplication.run (..) Break down

The main method in the bootstrap class has four functions:

  1. Start the SpringBoot program.
  2. Load the user-defined configuration classes to complete the auassemble.
  3. Deploy the current project to the embedded Tomcat.
  4. Start the Tomcat run project.

2. Syntax for SpringBoot configuration files

2.1 Overview of the SpringBoot configuration file

When we build a Spring Boot project using the Spring initializer, we just need to introduce a Web launcher dependency to make it a Web project, and we can access it through localhost:8080 with nothing configured. This is because Spring Boot automatically configures the configuration information for us underneath. So how do we change the default configuration? When we use the Spring initializer to create a Springboot project, we automatically generate an application. Properties file in the Resources directory. This is an empty file that provides an entry point to modify the default configuration information. Spring Boot also provides another style of configuration file, application.yml, which is two different files but essentially the same, with a slightly different syntax.

2.2. Properties syntax

The application. Properties configuration file is simple. It does not require Spaces to distinguish between parent and child properties. To distinguish between.

# key = value
server.port=8080
Copy the code

2.3, YML

It is a new syntax format that is slightly cumbersome to write, but it is the official recommended SpringBoot configuration file format because it can store more complex types than roperties configuration files. His grammar features:

  1. Case sensitive.
  2. K :(space)v: indicates a pair of key and value pairs (Spaces must exist), which are indented with Spaces to control the hierarchy.
  3. As long as a column is left aligned, it means that it is all in the same level.
  4. “#” represents a comment and is ignored by the parser all the way to the end of the line.
server:
port: 8080
Copy the code

3. SpringBoot integration

The most important aspect of SpringBoot is the integration of various frameworks, including the familiar Mybatis, Shiro, etc.

3.1 Connect to the database

3.1.1 Introducing dependencies

<! -- MySQL driver -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<! JDBC - springboot integration -- >
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
Copy the code

3.1.2 Hikari Data source

3.1.2.1 overview,

After springboot2.0, USES the default connection pool is Hikari, so-called “in the history of the fastest connection pool”, so we didn’t add to also can be used directly, springboot DataSourceAutoConfiguration configuration class is contained in the automatic configuration of, It checks to see if the container already has a connection pool object. If not, it uses the default connection pool and automatically configures the connection pool object based on specific properties, using values derived from the DataSourceProperties object.

3.1.2.2 modify application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///ssm_carbusiness? useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456
Copy the code

3.1.3 Druid Data source

3.1.3.1 overview,

Although SpringBoot officially recommends Hikari data sources, if we want to use Druid data sources, it’s easy. You just need to add dependent, at this point the Druid springboot automatic configuration package, containing the DruidDataSourceAutoConfigure automatic configuration class, object will automatically create a Druid connection pool, So If SpringBoot finds that there is already a connection pool object, Hikari will not be used.

3.1.3.2 Importing dependencies

<! -- Druid data source dependencies -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.5</version>
</dependency>

Copy the code

3.1.3.3 modify application.properties

spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.druid.url=jdbc:mysql:///ssm_carbusiness? useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
spring.datasource.druid.username=root
spring.datasource.druid.password=123456
Copy the code

3.1.3.4, pay attention to

If we accidentally introduce the wrong package while writing code and introduce normal dependencies (normal dependencies without start, only Druid’s own dependencies), the package is not automatically configured. Then SpringBoot will not parse it and we need to manually configure it to take effect. We just need to add one configuration line in application.properties.

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
Copy the code

3.2 Integrate MyBatis

3.2.1. Importing dependencies

<! -- MyBatis integrates into SpringBoot dependencies -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.4</version>
</dependency>

Copy the code

3.2.2 Configuring interface scanning

In a traditional SSM project, we could tell Spring the location of my Mapper interface in the configuration file, thus creating a proxy object for the Mapper interface implementation class. Without this configuration file in SpringBoot, we simply add a configuration line in SpringBoot’s boot class.

@SpringBootApplication
// Add a line that tells SpringBoot where my Mapper interface is
@MapperScan("cn.linstudy.mapper")
public class App {
	public static void main(String[] args) { SpringApplication.run(App.class, args); }}Copy the code

3.2.3. Configure attributes

Before, we need to configure some properties in application. XML to better use MyBatis, such as the location of mapper. XML file, whether lazy loading is enabled, alias information and so on, now these information will be configured in application.properties. If the service does not need to use it, you do not need to configure it.

Whether to enable lazy loading
mybatis.configuration.lazy-loading-enabled=true
# Enable lazy loading method
mybatis.configuration.lazy-load-trigger-methods=clone
# mapper.xml file configuration
mybatis.mapper-locations=classpath:cn/wolfcode/*/mapper/*Mapper.xml
# Configure alias
mybatis.type-aliases-package=cn.wolfcode.sb.domain
Print SQL log
logging.level.cn.linstudy.mapper=trace
Copy the code

3.3. Transaction management

3.3.1 Importing dependencies

<! Support for aspect programming using Spring AOP and AspectJ. -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Copy the code

3.3.2 Configuring transactions in XML mode

Using a mixture of configuration classes and XML, we use @ImportResource(“classpath:spring-tx.xml”) on the configuration class, and we write the transaction, aspect, and pointcut expressions in this XML file. Not recommended.

3.3.3 Configuring transactions using annotations

SpringBoot provides TransactionAutoConfiguration transaction annotations in the automatic configuration of automatic configuration class, we, after introducing dependence in the business layer directly on the implementation class or stick @ Transactional annotation directly on its way, it is recommended to use. Be sure to check if the database engine supports transactions before using it. SpringBoot uses the CGLIB dynamic proxy by default, and if you want to use the JDK dynamic proxy, you can simply write a configuration line in application.properties.

Use JDK proxy preferentially
spring.aop.proxy-target-class=false 
Copy the code

3.4 Processing static resources in SpringBoot

3.4.1 Location of static Resources

SpringBoot’s standard directory is different from a traditional SSM maven directory. It also has two directories under resources dedicated to static resources:

  1. Static: used to store CSS, JS and other styles.
  2. Templates: For storing page templates.

SpringBoot also has rules for handling static files:

  1. By default,Springboot comes from the CLASspath/static /public/resources /META-INF/resourcesLoad static resources at four locations in

  1. Can be found in the application. The spring that is configured in the properties. The resources, staticLocations attribute to modify the static resource loading address.

  2. Since SpringBoot maps static resources to/by default, we don’t need to write static when we introduce it.

    3.4.2 Configuring path mapping

In SpringBoot automatic assembly, automatic configuration of WebMvcAutoConfiguration class imported DispatcherServletAutoConfiguration configuration object, automatically created DispatcherServlet front controller, The default < url-pattern > is /.

3.5 Unified Exception handling

3.5.1 Default SpringBoot mode

SpringBoot by default, will give all error BasicErrorController class to complete the processing, the wrong view is oriented to the classpath: / static/error/and classpath: / templates/error / * * On the path, the HTTP status code is the default view name, and if a 404 error occurs, the corresponding template is 404.html. If we want to write our own error page, we can simply create a template file with the same name in the default path.

3.5.2 Controller enhancement Mode

Define a controller enhancer for uniform exception handling, which is generally used for class 5XX errors

@ControllerAdvice // Controller intensifier
public class ExceptionControllerAdvice {
    @ExceptionHandler(RuntimeException.class) // What types of exceptions are handled
    public String handlException(RuntimeException e, Model model) {
        return "errorView"; // Error page view name}}Copy the code

3.6 Filter

3.6.1 overview of filters

Filter is based on Servlet technology to achieve, simply speaking, filter is to play the role of filtering, in the Development of web projects to help us filter some specified URL to do some special processing, its main functions are as follows:

  1. Filter out things you don’t need, such as incorrect requests.
  2. You can modify the request and the corresponding content.
  3. It can be used to filter out unlogged users.

3.6.2 Filter implementation

There are two main implementations:

  1. The first is to use@WebFilter.
  2. The second is to use FilterRegistrationBean.

3.6.3, @ WebFilter

3.6.3.1 overview,

The @webfilter annotation is used to declare a class as a filter. This annotation will be processed by the container at deployment time, and the container will deploy the corresponding class as a filter based on the specific property configuration.

The property name type describe
filterName String Specify the name of the Filter
urlPatterns String String
value String Consistent with the urlPatterns

3.6.3.2 Code implementation

Create a myFilter.java implementation of the Filter interface

import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter(urlPatterns = "/api/*",filterName = "myFilter")
@Order(1)// Specifies the order in which filters are executed
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
	System.out.println("Initialize filter");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
	HttpServletRequest request= (HttpServletRequest) servletRequest;
	String uri=request.getRequestURI();
	String method=request.getMethod();
	System.out.println(uri+""+method+"Haha, I'm in MyFilter."); filterChain.doFilter(servletRequest,servletResponse); }}Copy the code

Start class with @ServletComponentScan annotation

Create a FilterController interface

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class HelloController {
	@GetMapping("/user/filter")
	public String hello(a){
		return "Haha, I passed the filter."; }}Copy the code

3.6.4. FilterRegistrationBean implementation

Create the FilterConfig

import com.yingxue.lesson.filter.MyFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public MyFilter myFilter(a){
return new MyFilter();
}
@Bean
public FilterRegistrationBean getFilterRegistrationBean(MyFilter myFilter){
        FilterRegistrationBean filterRegistrationBean=new FilterRegistrationBean();
        /** * Set filter */
        filterRegistrationBean.setFilter(MyFilter());
        /** * Intercept path */
        filterRegistrationBean.addUrlPatterns("/api/*");
        /** * Set the name */
        filterRegistrationBean.setName("myFilter");
        /** * Sets the lower the access priority value, the higher */
        filterRegistrationBean.setOrder(1);
	returnfilterRegistrationBean; }}Copy the code

Modify MyFilter. Java

//@WebFilter(urlPatterns ={"/api/*"},filterName = "myFilter")
Copy the code

Modify the startup class

//@ServletComponentScan
Copy the code

3.7. Interceptor

3.7.1 overview,

Simply a valve that intercepts a method before it is accessed, and then adds operations before or after it. An interceptor is an AOP implementation strategy whose main function is to intervene in a running process.

3.7.2 Overview of interceptor methods

Interceptors also have three main methods:

  1. PreHandle is called before the request and returns false if the request needs to be intercepted, true otherwise.
  2. PostHandle is called after the request and returns no value.
  3. AfterCompletion is called at the end of the request and returns no value.

3.7.3 Code implementation

Create an interceptor class and implement the HandlerInterceptor interface

public class MyInterceptor implements HandlerInterceptor {
	@Value("${open.url}")
	private String openUrl;
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		System.out.println("MyInterceptor.... Call before the request is processed (before the Controller method call)");
		String requestUrl=request.getRequestURI();
		System.out.println("Filter MyFilter intercepts requests for"+requestUrl);
		return true;
	}
    @Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
		System.out.println("MyInterceptor... Called after the request is processed, but before the view is rendered (after the Controller method is called).");
	}
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
		System.out.println("MyInterceptor.... Called at the end of the entire request, that is, after the DispatcherServlet has rendered the corresponding view (mainly for resource cleanup)."); }}Copy the code

Modify the application. The properties

We need to add a line of code in application.properties to add the wildcard address of the development interface, indicating the code that is allowed

Open.url =/**/open/**Copy the code

Create a Java implementation of WebMvcConfigurer, overriding the addInterceptors method

@Configuration
public class WebAppConfig implements WebMvcConfigurer {
	@Value("${open.url}")
	private String openUrl;
	@Bean
	public MyInterceptor getMyInterceptor(a){
		return new MyInterceptor();
	}
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getMyInterceptor()).addPathPatterns("/api/**").excludePathPatterns(openUrl); }}Copy the code

3.7.4, test,

@RestController
@RequestMapping("/api")
public class InterceptorController {
	@GetMapping("/home/open/info")
	public String home(a){
		return "Welcome to the home page";
	}
	@GetMapping("/user/interceptor")
	public String interceptor(a){
		return "I was intercepted and passed the interceptor."; }}Copy the code

3.8, logs,

Log plays an important role in our System testing and debugging. During System development, we used to use the sentence system.out.print () to output some System information, but in actual work, we don’t use this method to output log, for the following reasons:

  1. The logging framework is more flexible than system.out.println in that it separates the output of the log from the code.
  2. The logging framework can easily define the log output environment, console, file, database.
  3. The logging framework makes it easy to define the log output format and output level.

3.8.1 Log Description

3.8.1.1 This section describes logs in SpringBoot

We can see that logging is enabled by default when SpringBoot is started. From left to right are time, log level thread ID, thread name, log class, and Log Description.

The higher the log level, the smaller the output content. If the log level is set to Info, Trace < debug < info < WARN < error Springboot selects Logback as the logging framework by default. Other logging frameworks can be selected, but it is not necessary

3.8.1.2 Two Methods for Outputting Logs

Define a static Logger object in the class

// The current class is passed so that you can clearly see which class the log information belongs to
private static finalLogger log = loggerFactory.getLogger (current class.class);Copy the code

Use the @slf4j annotations provided by Lombok

@Slf4j
@Service
public class PermissionServiceImpl implements IPermissionService {}
    // The output log has variables that can use {} as placeholders
    log.info(Delete data whose id is {}, id);
    log.debug("Permission inserted successfully :{}",expression);
    log.info("Permission inserted successfully :{}",expression);
    log.warn("Permission inserted successfully :{}",expression);
}
Copy the code

3.8.1.3 Use of the Logback configuration File

By default, the Logback framework automatically loads classpath:logback. XML as a configuration file for the framework. When used in SpringBoot, there is additional support for automatic loading of the classpath:logback-spring.xml. Therefore, logback-spring.xml is recommended, which is more powerful.


      
<! The default value is "true". ScanPeriod: Indicates the frequency of hot deployment. The default value is "60 second DE"bug:Set output frame internal logs, default value false -->
<configuration scan="true" scanPeriod="60 second" debug="false">
    <property name="appName" value="springboot demo" />
    <contextName>${appName}</contextName>
    
    <! - appender: log output object, configure different classes have different function ch. Qos. Logback. Core. ConsoleAppender: log output to the console - >
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd-HH:mm:ss} %level [%thread]-%logger{35} >> %msg %n</pattern>
     </encoder>
   </appender>
    
    <! - ch. Qos. Logback. Core. FileAppender: log output to a file < appender name = "FileAppender" class = "ch. Qos. Logback. Core. FileAppender" > <encoder> <pattern>%-4relative [%thread] %level %logger{35} - % MSG %n</pattern> </encoder> <append>true</append> < file > mylog. Log < / file > < appender > -- >
    
    <! < debug < info < WARN < error --> < debug < info < WARN < error -->
   <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
    
    <! <logger name="cn.wolfcode.crm.mapper" level="trace"> </logger> -->
</configuration>
Copy the code

3.9 Integrated front end

3.9.1 Integrated JSP

Mentioning Java has to say one development scenario is Web development, speaking of Web development around a technology is JSP, Although SpringBoot official has not recommended the use of JSP, but integrated JSP is still very important.

3.9.1.1 Importing a Dependency

<! --JSP standard tag Library -->
<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>jstl</artifactId>
</dependency>
<! -- Built-in Tocat dependency on Jsp support for compiling JSPS -->
<dependencys>
	<groupId>org.apache.tomcat.embed</groupId>
	<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
Copy the code

3.9.1.2 Edit project Structure

3.9.1.3 Spring Mvc View parser configuration

We need to modify the Application. properties to include the Spring Mvc view parser configuration

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

3.9.1.4,

In the future, we will need to first configure the WebApp path, configure the Web, configure the ORM, and finally configure the view resolver. With the required configuration configured, you can copy the code directly to the new project.

3.9.2 Integrate FreeMarker

Integrating FreeMarker in traditional SpringMVC requires both FreeMarkerConfigurer and FreeMarkerViewResolve to be configured into the Spring container. With SpringBoot, we can integrate a FreeMarker very easily with automatic configuration, just by introducing a dependency.

<! -- SpringBoot integrates FreeMarker dependencies -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
Copy the code

3.9.2.1 Underlying Principles

SpringBoot FreeMarkerAutoConfiguration configuration object is contained in automatic configuration, the configuration objects and imported the FreeMarkerReactiveWebConfiguration configuration object, created FreeMarkerConfig inside The Urer and FreeMarkerViewResolve objects are given to Spring management with default property values set from the FreeMarkerProperties object

3.9.2.2 Common Attribute Configuration

Whether to enable freemarker support
spring.freemarker.enabled=true
# Template code
spring.freemarker.charset=UTF-8
# template contenttype
spring.freemarker.content-type=text/html
The default value is false
spring.freemarker.expose-session-attributes = false
# prefixes when loading templates
spring.freemarker.prefix: templates
# template file suffix, springboot2.x defaults to FTLH, sometimes our template suffix is FTL
spring.freemarker.suffix: ftl
# Template loading address
spring.freemarker.template-loader-path=classpath:/templates/
We usually do 3 configurations, the rest are default
Expose the properties of the session object
spring.freemarker.expose-session-attributes=true
Set to traditional mode, null values are handled automatically
spring.freemarker.settings.classic_compatible=true
# Re-specify the template file suffix springboot 2.2.x to.ftlh
spring.freemarker.suffix=.ftl  
Copy the code

3.9.3 Integration of Thymeleaf

Thymeleaf is a template engine for rendering XML/XHTML/HTML5 content. Similar to JSP, FreeMaker, etc., it can also be easily integrated with the Web framework. Template engine for Web applications. Compared to other templating engines, Thymeleaf’s best feature is the ability to open and display the templating page directly in the browser without launching the entire Web application. ThymeLeaf supports the Spring Expression Language Language as a dialect, known as SpEL, which is an EL Expression that can be used in Spring. Unlike JSP we have used, Thymeleaf uses HTML tags to complete the incoming logic and data for rendering. It is possible to completely replace JSP with Thymeleaf.

3.9.3.1 Creating a project

Remember to check these two dependencies when creating the project.

3.9.3.2 Spring Mvc View parser configuration

#spring.thymeleaf.prefix=classpath:/templates/ # spring.thymeleaf.suffix=.html spring.thymeleaf.charset=UTF-8 spring.thymeleaf.servlet.content-type=text/htmlCopy the code

3.9.3.3, test,

To create a hello. HTML under templates, you must add the XMLNS :th=”www.thymeleaf.org” Thymeleaf declaration space.