spring-boot rapid construction, hot deployment, automatic configuration principle, configuration file, integration of SpringMVC, redis, junit, mybatis, package deployment

Article Directory

spring-boot

The benefits of spring-boot:

  • Automatic configuration (Which function you want to use, the required configuration is done for you)
  • Start-up dependency (which function you want to use, just add a dependency)
  • Accessibility (eg embedded server)

Quickly build spring-boot

pom-maven

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!--1、指定父工程-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>

    <groupId>cn.itcast</groupId>
    <artifactId>springboot-demo1</artifactId>
    <version>1.0-SNAPSHOT</version>


    <dependencies>
        <!--web启动器,将项目变成web项目,集成了springMVC、tomcat、json-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

Startup class (spring-boot has a built-in server)

The startup class SpringBootApplication scans the package of the current class and its sub-packages by default. (As long as it is in the current package, it will run in the server, and it will not run if it is not in this package)
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        // 参数1-启动类的class,参数2-jvm运行参数
        SpringApplication.run(DemoApplication.class, args);
    }
}
@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String test(){
        return "hello";
    }
}

SpringBoot hot deployment

The role of SpringBoot hot deployment

Function: When the project is running, there is no need to manually restart the service if the code is modified. It can monitor the changes of the class file and automatically restart the service (applicable to the development environment)
<!-- 热部署配置-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>

Analysis of SpringBoot automatic configuration principle

During the startup process of the springboot project, all the META-INF/Spring.factories files in the project will be loaded. The files contain many auto-configuration classes written in advance. The auto-configuration classes may not all take effect because there is also a conditional comment above. , The relevant conditions must be met before it can take effect. We only need to add a relevant launcher dependency to make the condition annotations take effect, and the configuration classes take effect.
Insert picture description here
spring.factories, the full path of a lot of classes are listed under this file, all of which are configuration classes provided by SpringBoot for various integrated frameworks/components (such as Reids, ElasticSearch)
Insert picture description here

Open RedisAutoConfiguration

Insert picture description here
If we want Redis-related configurations to take effect, we need to add Redis's launcher dependency (pluggable thinking).
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

SpringBoot configuration file

1. Configuration file classification:

SpringBoot is based on conventions, so many configurations have default values, but if you want to replace the default configuration with your own configuration, you can use application.properties or application.yml (application.yaml) for configuration.
The priority under the same level directory is: properties> yml> yaml, the
same attribute takes the value in the file with higher priority, and the different attribute takes the union (generally only one type of file is used in the project).

2. YAML

The full name of YAML is YAML Ain't Markup Language.
Insert picture description here

YAML basic syntax

  • Case Sensitive
  • 数据值前边必须有空格,作为分隔符
  • Use indentation to indicate hierarchical relationships
  • 缩进时不允许使用Tab键,只允许使用空格(The number of spaces corresponding to the Tab of each system may be different, leading to confusion in the hierarchy).
  • The number of indented spaces is not important, as long as the elements of the same level are aligned to the left
  • # Indicates a comment, from this character to the end of the line, it will be ignored by the parser.

YAML data format

Scalar:

Insert picture description here

map:

Insert picture description here


array|list:

Insert picture description here

Parameter reference:

Insert picture description here

3. Read the content of the configuration file

application.yml

name: 张三
age: 18

(1)@Value

@RestController
public class YmalController {
    @Value("${name}")
    private String name;

    @Value("${age}")
    private int age;

    @RequestMapping("/yml")
    public String test(){
        System.out.println("name = " + name);
        System.out.println("age = " + age);

        return "yml";

    }
}
Note: 1. Must be used in Bean; 2. Only scalar type can be read

(2)Environment

@RestController
public class YmalController2 {
    @Autowired
    private Environment environment;

    @RequestMapping("/ymal2")
    public String test(){
        String name = environment.getProperty("name");
        System.out.println(name);
        String age = environment.getProperty("age");
        System.out.println(age);
        return "ymal2";
    }
}
Note: 1. Must be used in Bean; 2. Only scalar type can be read

(3)@ConfigurationProperties

person:
  name: 张三
  age: 18
@RestController
@ConfigurationProperties(prefix = "person")
public class PersonController {

    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @RequestMapping("/person")
    public String test(){
        System.out.println("name = " + name);
        System.out.println("age = " + age);

        return "person";
    }

}
1. Must be used in Bean; 2. Set method must be provided for attribute

(4) @ConfigurationProperties + @EnableConfigurationProperties

@ConfigurationProperties(prefix = "person")
public class PersonProperties {
    private String name;
    private int age;

    public PersonProperties() {
    }

    public PersonProperties(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Person{name = " + name + ", age = " + age + "}";
    }
}
@RestController
@EnableConfigurationProperties(PersonProperties.class)
public class PersonController2 {

    @Autowired
    private PersonProperties personProperties;

    @RequestMapping("/person2")
    public String test(){
        int age = personProperties.getAge();
        String name = personProperties.getName();
        System.out.println("age = " + age);
        System.out.println("name = " + name);
        return "person2";

    }
}

4. Use of configuration files

Multiple profile mode

application-dev.yml (development environment), application-test.yml (test environment), application-test.yml (production environment), set different port numbers to run in different operating environments
Insert picture description here

Profile activation:

The first way: (not commonly used, because the packaging needs to be rewritten)

Insert picture description here

The second way: virtual machine parameters (commonly used)

Virtual machine parameters (-Dspring.profiles.active=XXX)
Insert picture description here

The third way: command line parameters

Command line parameters (–spring.profiles.active=XXX)
Insert picture description here

SpringBoot integrates SpringMVC

There are four default static resource access paths:
  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/ (commonly used)
  • classpath:/public (commonly used)

Interceptor

  • Custom interceptor class to implement the HandlerInterceptor interface
  • Create a configuration class, implement the WebMvcConfigurer interface, and add the interceptor to the existing SpringMVC configuration
public class LoginInterceptor implements HandlerInterceptor {

    @Override
    // 前置处理,返回true代表放行,false代表拦截
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("前置处理");
        return true;
    }

    @Override
    // 后置处理
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("后置处理");
    }

    @Override
    // 渲染后处理
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("渲染后处理");
    }
}
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {

    /**
     * 重写接口中的addInterceptors方法,添加自定义拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加拦截器,通过addPathPatterns来添加拦截路径
        // **代表拦截多层,*代表只拦截一层
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**");
    }
}
** stands for intercepting multiple layers, * stands for intercepting only one layer

SpringBoot integrates Mybatis

        <!--mybatis启动器-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>

        <!--mysql驱动包,在父工程已经指定版本号了,但是是8.0.16,我们安装的是5.7的数据库,因此需要覆盖版本号-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

application.yml

spring:
  # 指定数据库连接池信息
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springboot_db
    username: root
    password: 123456
    
mybatis:
  # 配置类型别名包扫描
  type-aliases-package: cn.itcast.pojo
  # sql语句映射文件路径,注意冒号后面没有空格,代表是一个整体
  mapper-locations:
    - classpath:mappers/*.xml
  # 字段返回值使用驼峰映射
  configuration:
    map-underscore-to-camel-case: true

# SpringBoot配置控制,指定日志输出级别,可以打印mybatis的sql语句
logging:
  level:
    cn.itcast: debug # 键值对,key一般使用最外层的包名

Base package scan dao layer

@SpringBootApplication
@MapperScan(basePackages = "com.halulu.dao")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class,args);
    }
}
Insert picture description here

Springboot integrates Junit

<!-- 配置test启动器(自动整合spring-test、junit) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
// 指定运行环境是Spring环境
@RunWith(SpringRunner.class)
// 如果测试类所在目录是启动类所在目录的同级子级下可以省略启动类
// @SpringBootTest(classes = {DemoApplication.class})
@SpringBootTest
public class SickerServiceTest {

    @Autowired
    private SickerService sickerService;
    @Test
    public void test(){
        List<Sicker> sickerList = sickerService.findAll();
        System.out.println(sickerList);
    }
}

SpringBoot integrates Redis

<!-- 配置redis启动器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
# 配置Redis
spring:
  redis:
    host: localhost # 主机
    port: 6379      # 端口在这里插入代码片

@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTemplateTest {
    
    @Autowired
    private RedisTemplate redisTemplate;
    
    @Test
    public void redisTest(){
        // 设置值
        redisTemplate.opsForValue().set("name", "admin");
        
        // 获取值
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println("name = " + name);
        
        // 删除值
        redisTemplate.delete("name");
    }
}

SpringBoot packaged deployment

1. Tie into a Jar package

<build>
    <plugins>
        <!-- 配置spring-boot的maven插件
                1. 用它可以运行spring-boot项目
                2. 需要用它构建打jar、war资料
             -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
# 清理、打包
mvn clean package
# 清理、打包 跳过测试
mvn clean package -Dmaven.test.skip=true

Execute jar package from the command line

java -jar xxx.jar

2. Make a war package

<!-- 打包方式(默认为jar) -->
<packaging>war</packaging>


<!-- 指定scope为provided: 代表打包时,不需要它的依赖jar包(我们有自己的tomcat) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>
Custom web application entry class, inherit SpringBootServletInitializer (equivalent to web.xml)
// web.xml
public class WebServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        builder.sources(DemoApplication.class);
        return builder;
    }
}

Execute packaging commands

# 清理、打包
mvn clean package

# 清理、打包 跳过测试
mvn clean package -Dmaven.test.skip=true
Deploy the project xxx.war, place it under tomcat's webapps, and start tomcat