博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

springboot基础

Posted on 2024-06-14 23:39  心默默言  阅读(2)  评论(0编辑  收藏  举报

springboot基础

1. 快速入门

https://docs.spring.io/spring-boot/docs/

https://docs.spring.io/spring-boot/docs/2.1.10.RELEASE/reference/html

https://developer.aliyun.com/mirror/mave

image-20240611212531874

<?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>

    <groupId>com.itheima</groupId>
    <artifactId>springboot-helloworld</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- Inherit defaults from Spring Boot -->
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>
package com.itheima.controller;

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

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello(){
        return "hello springboot";
    }
}

package com.itheima;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

2. 配置文件

image-20240611221500418

image-20240611221514074

3. 读取配置文件

image-20240611222602275

image-20240611221813917

package com.itheima.springbootinit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {


    @Value("${name}")
    private String name;

    @Value("${person.name}")
    private String name2;

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


    @Value("${address[0]}")
    private String address1;

    @Value("${msg1}")
    private String msg1;

    @Value("${msg2}")
    private String msg2;


    @Autowired
    private Environment env;

    @Autowired
    private Person person;


    @RequestMapping("/hello2")
    public String hello2() {

        System.out.println(name);
        System.out.println(name2);
        System.out.println(age);
        System.out.println(address1);
        System.out.println(msg1);
        System.out.println(msg2);

        System.out.println("----------------------");

        System.out.println(env.getProperty("person.name"));
        System.out.println(env.getProperty("address[0]"));

        System.out.println("-------------------");

        System.out.println(person);
        String[] address = person.getAddress();
        for (String s : address) {
            System.out.println(s);
        }

        return "hello Spring Boot 222!";
    }


    @RequestMapping("/hello")
    public String hello() {
        return "hello Spring Boot 222!";
    }
}

@ConfigurationProperties(prefix = "person")
@Component
@Data
public class Person {
    private String name;
    private int age;
}
person:
    name: abc
    age: 20
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
package com.itheima.springbootinit;


@RestController
public class HelloController {
    @Autowired
    private Person person;

    @RequestMapping("/hello2")
    public String hello2() {

        System.out.println(person);
        String[] address = person.getAddress();
        for (String s : address) {
            System.out.println(s);
        }
        return "hello Spring Boot 222!";
    }
}

4. profile

image-20240611224118191

image-20240611224132962

5. 内部配置加载顺序

image-20240611224246635

注意:resource路径下为第4个

6. 整合junit

image-20240611225139717

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
package com.itheima.springbootjunit;

import org.springframework.stereotype.Service;

@Service
public class UserService {

    public void show(){
        System.out.println("show....");
    }
}
package com.itheima.test;


import com.itheima.springbootjunit.SpringbootJunitApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * 测试类
 */

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootJunitApplication.class )
public class UserServiceTest {

    @Test
    public void test(){
        System.out.println(111);
    }
}

7.整合mybatis

image-20240611231013065

CREATE DATABASE /*!32312 IF NOT EXISTS*/`springboot` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */;

USE `springboot`;

/*Table structure for table `t_user` */

DROP TABLE IF EXISTS `t_user`;

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `password` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

/*Data for the table `t_user` */

insert  into `t_user`(`id`,`username`,`password`) values (1,'zhangsan','123'),(2,'lisi','234');
package  com.itheima.springbootmybatis.domain;

import lombok.Data;

@Data
public class User {
    private int id;
    private String username;
    private String password;
}

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.itheima</groupId>
    <artifactId>springboot-mybatis</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-mybatis</name>
    <description>Demo project for Spring Boot</description>

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

    <dependencies>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <!--<scope>runtime</scope>-->
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

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

</project>

# datasource
spring:
  datasource:
    url: jdbc:mysql:///springboot?serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

# mybatis
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml # mapper映射文件路径
  type-aliases-package: com.itheima.springbootmybatis.domain

  # config-location:  # 指定mybatis的核心配置文件
package com.itheima.springbootmybatis.mapper;

import com.itheima.springbootmybatis.domain.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper
@Repository
public interface UserMapper {

    @Select("select * from t_user")
    public List<User> findAll();
}
package com.itheima.springbootmybatis.mapper;

import com.itheima.springbootmybatis.domain.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper
@Repository
public interface UserXmlMapper {
    public List<User> findAll();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.springbootmybatis.mapper.UserXmlMapper">
    <select id="findAll" resultType="user">
        select * from t_user
    </select>
</mapper>
package com.itheima.springbootmybatis;

import com.itheima.springbootmybatis.domain.User;
import com.itheima.springbootmybatis.mapper.UserMapper;
import com.itheima.springbootmybatis.mapper.UserXmlMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootMybatisApplicationTests {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserXmlMapper userXmlMapper;

    @Test
    public void testFindAll() {
        List<User> list = userMapper.findAll();
        System.out.println(list);
    }
    @Test
    public void testFindAll2() {
        List<User> list = userXmlMapper.findAll();
        System.out.println(list);
    }
}

8. 两步实现定时任务

8.1 添加注解@EnableScheduling

@SpringBootApplication
@EnableScheduling
public class springbootApplicationMybatis {

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

8.2 方法上添加注解@Scheduled()

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@SpringBootApplication
@EnableScheduling
public class springbootApplicationMybatis {

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

    //1min 执行一次
    @Scheduled(fixedRate = 1*60*1000)
    public void play(){
        System.out.println("hello sheduled");
    }
    
    //9-22点之间每隔30分钟提醒一次
    @Scheduled(cron = "0 0/30 9-22 * * ?")
    public void play2(){
        System.out.println("hello sheduled");
    }
}

在线生成cron表达式https://cron.qqe2.com/

image-20240613224341991

注意:spring只支持前6个,不支持年

image-20240613230034625

image-20240613230734669

9. 异步实现定时任务

image-20240613231133351

9.1 开启注解@EnableAsync

package com.itheima;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@SpringBootApplication
@EnableScheduling
@EnableAsync
public class springbootApplicationMybatis {

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

    //1min 执行一次
    @Scheduled(fixedRate = 1*60*1000)
    public void play(){
        System.out.println("hello sheduled");
    }
}

9.2 设置异步执行@Async

package com.itheima;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@SpringBootApplication
@EnableScheduling
@EnableAsync
public class springbootApplicationMybatis {

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

    //1min 执行一次
    @Async
    @Scheduled(fixedRate = 1000)
    public void play(){
        try {
            Thread.sleep(2*1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("线程名称:"+Thread.currentThread().getName());
        System.out.println("hello sheduled");
    }

    //9-22点之间每隔半小时提醒一次
    @Async
    @Scheduled(cron = "0 0/30 9-22 * * ?")
    public void play2(){
        System.out.println("hello sheduled");
    }
}

10. 整合redis

10.1 本地redis服务

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

启动本地redis服务

package com.itheima;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.data.redis.core.RedisTemplate;

@RunWith(SpringRunner.class)
@SpringBootTest
public class HelloApplicationTest {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void set(){
        redisTemplate.boundValueOps("name").set("zhangsan");
    }

    @Test
    public void get(){
        Object name = redisTemplate.boundValueOps("name").get();
        System.out.println(name);
    }
}

10.2 非本地redis服务

server:
  port: 8081
  
spring:
  redis:
    host: 127.0.0.1
    port: 6379

其余与上述代码一致

11. springBoot 自动配置

11.1 condition

image-20240615222119111

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

若在maven配置文件中导入了redis的坐标,则下列代码可以正确输出redisTemplate

package com.itheima;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class HelloApplication {
    public static void main(String[] args) {
        //启动springboot应用,并返回spring的IOC容器
        ConfigurableApplicationContext context = SpringApplication.run(HelloApplication.class, args);
        //获取bean,redisTemplate
        Object redisTemplate = context.getBean("redisTemplate");
        System.out.println(redisTemplate);
    }
}

若没导入redis的坐标,则打印报错

image-20240615223953426

package com.itheima.domain;

public class User {
}
package com.itheima.config;

import com.itheima.condition.ClassCondition;
import com.itheima.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class UserConfig {
    @Bean
    @Conditional(ClassCondition.class)
    public User user(){
        return new User();
    }
}
package com.itheima.condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class ClassCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        return true;
    }
}
package com.itheima;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class HelloApplication {
    public static void main(String[] args) {
        //启动springboot应用,并返回spring的IOC容器
        ConfigurableApplicationContext context = SpringApplication.run(HelloApplication.class, args);
        //获取bean,redisTemplate
        Object user = context.getBean("user");
        System.out.println(user); //ClassCondition返回true,可以打印对象;返回false,打印报错
    }
}

完善matches方法逻辑,即可实现上述案例要求

package com.itheima.condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class ClassCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {

        try {
            Class<?> clas = Class.forName("redis.clients.jedis.Jedis");
        } catch (ClassNotFoundException e) {
            return false;
        }
        return true;
    }
}

image-20240615225817378

1)自定义注解的方式实现

package com.itheima.condition;

import org.springframework.context.annotation.Conditional;

import java.lang.annotation.*;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ClassCondition.class)
public @interface ConditionOnClass {
    String[] value();
}
package com.itheima.config;

import com.itheima.condition.ClassCondition;
import com.itheima.condition.ConditionOnClass;
import com.itheima.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class UserConfig {
    @Bean
//    @Conditional(ClassCondition.class)
    @ConditionOnClass("redis.clients.jedis.Jedis")
    public User user(){
        return new User();
    }
}
package com.itheima.condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

import java.util.Map;

public class ClassCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {

        Map<String, Object> map = annotatedTypeMetadata.getAnnotationAttributes(ConditionOnClass.class.getName());
        assert map != null;
        String[] value = (String[]) map.get("value");
        try {
            for (String className : value) {
                Class<?> cls = Class.forName(className);
            }
        } catch (ClassNotFoundException e) {
            return false;
        }
        return true;
    }
}

2)springboot提供的注解实现

package com.itheima.config;

import com.itheima.condition.ClassCondition;
import com.itheima.condition.ConditionOnClass;
import com.itheima.domain.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class UserConfig {
    @Bean
    @ConditionalOnProperty(name = "itcast",havingValue = "itheima") // 只有配置文件中有这个键值对,才加载这个bean
    public User user2(){
        return new User();
    }
    
    @Bean
    @ConditionalOnClass(name = "redis.clients.jedis.Jedis") // springboot提供的注解
    public User user3()  {
        return new User();
    }
}

image-20240616212738178

11.2 切换内置web服务器

内置四个web服务器

image-20240616220144435

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!--排除tomcat依赖-->
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!--引入jetty依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

注意:排除依赖,最好clean一下项目,否则可能会导致失效

11.3 @Enable*注解

SpringBoot中提供了很多Enable开头的注解,这些注解都是用于动态启用某些功能的。而其底层原理是使用@Import注
解导入一些配置类,实现Bean的动态加载

spring boot不能直接获取其它工程定义的bean

image-20240620225645431

解决方案1:

image-20240620225823557

解决方案2:

image-20240620230040422

解决方案3:

image-20240620230236202

image-20240620230319763

11.4 @Import注解

@Enable*底层依赖于@Import注解导入一些类,使用@Import导入的类会被Spring加载到IOC容器中。而@Import提供4中用
法:
① 导入Bean

image-20240620230734210② 导入配置类

image-20240620230814465

image-20240620231019114

③ 导入 ImportSelector 实现类。一般用于加载配置文件中的类

image-20240624225217030

image-20240624225259724

④ 导入 ImportBeanDefiniti onRegistrar 实现类。

image-20240624225543948

image-20240624225648236

11.5 EnableAutoConfiguration

image-20240624230834445

11.6 自定义starter实现

image-20240625233647744

1)autoconfigure模块

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <!--引入jedis依赖-->
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
</dependencies>
package com.nbcb.config;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;

@Configuration
@EnableConfigurationProperties(RedisProperties.class)
@ConditionalOnClass(Jedis.class)
public class RedisAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(name = "jedis")
    public Jedis jedis(RedisProperties redisProperties) {
        System.out.println("ConditionalOnMissingBean");
        return new Jedis(redisProperties.getHost(), redisProperties.getPort());
    }
}

package com.nbcb.config;


import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "redis")
public class RedisProperties {
    private String host = "localhost";
    private int port = 6379;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }
}

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com/nbcb/config/RedisAutoConfiguration

2)starter模块

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <!--引入自定义的configure-->
    <dependency>
        <groupId>com.nbcb</groupId>
        <artifactId>redis-spring-boot-autoconfigure</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

3)测试模块

<dependency>
    <groupId>com.nbcb</groupId>
    <artifactId>redis-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
@SpringBootApplication
public class HelloApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(HelloApplication.class, args);
        Jedis jedis = context.getBean(Jedis.class);
        System.out.println(jedis);
        String name = jedis.get("name");
        System.out.println(name);
    }

//    @Bean
//    public Jedis jedis(){
//        return new Jedis("localhost",6379);
//    }
}
redis:
  port:
    6666

12.springBoot 监听机制

12.1 事件监听

image-20240626224346298

image-20240626224417190

package com.nbcb.listener;

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;


//可以在项目启动前做一些资源检查
@Component
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        System.out.println("ApplicationContextInitializer....initialize");
    }
}
package com.nbcb.listener;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;


//当项目启动后执行run方法,可以在项目启动后加载一些redis缓存
@Component
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("ApplicationRunner... run");
    }
}
package com.nbcb.listener;

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

//当项目启动后执行run方法,可以在项目启动后加载一些redis缓存
@Component
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("CommandLineRunner....run");
    }
}
package com.nbcb.listener;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.stereotype.Component;

//@Component
public class MySpringApplicationRunListener implements SpringApplicationRunListener {

    public MySpringApplicationRunListener(SpringApplication application, String[] args) {
    }

    @Override
    public void starting() {
        System.out.println("starting...项目启动中");
    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        System.out.println("environmentPrepared....环境对象开始准备");
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        System.out.println("contextPrepared....上下文对象开始准备");
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        System.out.println("contextLoaded....上下文对象开始加载");

    }

    @Override
    public void started(ConfigurableApplicationContext context) {
        System.out.println("started....上下文对象加载完成");
    }

    @Override
    public void running(ConfigurableApplicationContext context) {
        System.out.println("running....项目启动完成,开始运行");
    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        System.out.println("failed....项目启动失败");

    }
}
org.springframework.context.ApplicationContextInitializer=com.nbcb.listener.MyApplicationContextInitializer

org.springframework.boot.SpringApplicationRunListener=com.nbcb.listener.MySpringApplicationRunListener

image-20240626234157683

13.springBoot监控

image-20240627210925649

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

http://localhost:8080/actuator

https://www.json.cn/

info.name=zhangsan

management.endpoint.health.show-details=always

14. springBoot项目部署

image-20240627225048915

<groupId>com.nbcb</groupId>
<artifactId>springboot-listener</artifactId>
<packaging>war</packaging>
package com.nbcb.controller;

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

@RequestMapping("/hello")
@RestController
public class HelloSpringBoot {
    @RequestMapping("/findAll")
    public String findAll(){
        return "success";
    }
}
package com.nbcb;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class HelloApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(HelloApplication.class);
    }
}

注:使用maven打包,然后将打包的war包放入外部的tomcat的webapp路径下即可

15. springboot构建多个modules

<?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>

    <groupId>org.springframework.boot</groupId>
    <artifactId>springboot-modules</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>module-common</module>
        <module>test1</module>
    </modules>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.boot.verison>2.1.8.RELEASE</spring.boot.verison>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.verison}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>

        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring.boot.verison}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>

    </build>

</project>
<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>springboot-modules</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath/>
    </parent>

    <artifactId>module-common</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

</project>

16. 数据库密码加密

16.1 导包

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>

16.2 使用测试类生成密钥

@Test
public void druidEncrypt() throws Exception {
    //密码明文
    String password = "root";
    System.out.println("明文密码: " + password);
    String[] keyPair = ConfigTools.genKeyPair(512);
    //私钥
    String privateKey = keyPair[0];
    //公钥
    String publicKey = keyPair[1];

    //用私钥加密后的密文
    password = ConfigTools.encrypt(privateKey, password);

    System.out.println("privateKey:" + privateKey);
    System.out.println("publicKey:" + publicKey);

    System.out.println("加密password:" + password);

    String decryptPassword = ConfigTools.decrypt(publicKey, password);
    System.out.println("解密后:" + decryptPassword);
}

生成公钥和私钥,还可使用命令生成:java -cp druid-1.1.10.jar com.alibaba.druid.filter.config.ConfigTools you_password

注意:加密password和密钥,每次加密都会变,需要成对使用

16.3 数据库配置

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ66HTZjbCuDU+Fymehr9lqBIjx0ojdt99LorR3pn6hyTy/nmnrGCO3fY2F3MgErluehKgjZGin9FnXO9M6xiU0CAwEAAQ==
    druid:
      url: jdbc:mysql:///springboot?serverTimezone=UTC
      username: root
      password: CsyerNasXVUJ5zoBXWjJ/gp/ylEUF2m22RmMivye/Z8wLYQBEdNxNfcLKP2NRUFYcVPSXYftJ2oEB0wkszEx9A==
      filter:
        config:
          enabled: true
      connection-properties: config.decrypt=true;config.decrypt.key=${spring.datasource.publicKey}

17. 文件上传与下载

17.1 依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20210307</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.8.1</version>
    </dependency>
</dependencies>

17.2 application.properties

# 默认开启
pring.servlet.multipart.enabled=true
spring.servlet.multipart.file-size-threshold=20MB
spring.servlet.multipart.max-request-size=20MB

file.upload.path=d:/test
file.upload.type=dll,exe

17.3 Controller

package com.nbcb.controller;

import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;

@Controller
@RequestMapping("file")
@Slf4j
public class FileController {
    @Value("${file.upload.path}")
    private String uploadFilePath;

    @RequestMapping(value = {"", "/", "/index"})
    public String index() {
        return "upload";
    }

    @ResponseBody
    @PostMapping("/uploadFile")
    public String fileUpload(@RequestParam("file") MultipartFile file) {
        JSONObject result = new JSONObject();
        if (file.isEmpty()) {
            result.put("error", "文件上传失败");
            return result.toString();
        }

        String fileName = file.getOriginalFilename();
        assert fileName != null;
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        log.info("上传文件名称为{},后缀名为{}", fileName, suffixName);

        File fileTempObj = new File(uploadFilePath + File.separator + fileName);
        if (!fileTempObj.getParentFile().exists()) {
            fileTempObj.getParentFile().mkdirs();
        }
        if (fileTempObj.exists()) {
            result.put("error", "文件已经存在");
            return result.toString();
        }
        try {
            // 写入文件方式1:
//            file.transferTo(fileTempObj);
            //写入方式2:
            FileUtil.writeBytes(file.getBytes(), fileTempObj);

        } catch (IOException e) {
            log.error("发生错误{}", e.getMessage());
            result.put("error", e.getMessage());
            return result.toString();
        }
        result.put("success", "文件上传成功");
        return result.toString();
    }

    @ResponseBody
    @RequestMapping("/downloadFile")
    public String fileDownload(HttpServletResponse response, @RequestParam("fileName") String fileName) throws IOException {
        JSONObject result = new JSONObject();
        File file = new File(uploadFilePath + File.separator + fileName);
        if (!file.exists()) {
            result.put("error", "文件不存在");
            return result.toString();
        }
        response.reset();
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        //方式1
//        byte[] bytes = FileCopyUtils.copyToByteArray(file);
        //方式2
        byte[] bytes = FileUtil.readBytes(file);
        response.getOutputStream().write(bytes);
        result.put("success","文件下载成功");
        return result.toString();
    }
}