SpringBoot

SpringBoot

1.基础篇

文件优先级:properties(最高)> yml > yaml(最低)

读取配置注解:@ConfigurationProperties(prefix = "spring") (只能是bean读取)

注:基础篇只需学会使用SpringBoot+Myabtis+Junit实现简单的CRUD即可

2.运维篇

2.1项目打包

打包流程:程序包打好以后,就可以直接执行了。在程序包所在路径下,执行指令。

java -jar 工程包名.jar

2.2高级配置1

  • 打包时临时配置 优先级大于配置文件

java –jar springboot.jar –-server.port=80 --logging.level.root=debug
java –jar springboot.jar –-server.port=80
  • idea中的临时配置 优先级小于配置文件 但是可以选择加载配置文件

  • 四种配置文件

  1. file :config/application.yml 【最高】

  2. file :application.yml

  3. classpath:config/application.yml

  4. classpath:application.yml 【最低】

  • 自定义加载配置文件 通过启动参数设定

//1.配置名不带扩展名 
--spring.config.name=application
//2.全路径名
--spring.confi.location=classpath:/application.yml 
//3.加载多个配置文件
--spring.confi.location=classpath:/application.yml,classpath:/application2.yml

2.3多环境配置

  • 单一yml配置

spring:
    profiles:
        active: pro     # 启动pro
---                      #使用---作为分割线
spring:
    config:
        activate:
            on-profile: pro
server:
    port: 80
---
spring:
    config:
        activate:
            on-profile: dev
server:
    port: 81
  • 多yml配置

application-dev.yml

server:
    port: 81

application-pro.yml

server:
    port: 80

application.yml 主文件

spring:
    profiles:
        active: dev

多yml配置技巧

spring:
    profiles:
        active: dev #属文件优先执行
        group:
            "dev": devDB,devRedis,devMVC
            "pro": proDB,proRedis,proMVC
            "test": testDB,testRedis,testMVC
  • 使用maven中pom文件加载配置文件

<profiles>
    <profile>
        <id>env_dev</id>
        <properties>
            <profile.active>dev</profile.active>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault>     <!--默认启动环境-->
        </activation>
    </profile>
    <profile>
        <id>env_pro</id>
        <properties>
            <profile.active>pro</profile.active>
        </properties>
    </profile>
</profiles>
​
主配置文件读取maven值
spring:
    profiles:
        active: @profile.active@

注:如果在Idea下测试工程时pom.xml每次更新需要手动compile方可生效

2.4日志

  • 设置日志级别

# 开启debug模式,输出调试信息,常用于检查系统运行状况
debug: true
logging:
    # 设置日志组
    group:
        # 自定义组名,设置当前组中所包含的包
        ebank: com.example.controller
    level:
        root: warn
        # 为对应组设置日志级别
        ebank: debug
        # 为对包设置日志级别
        com.example.controller: debug
  • lombok自带日志注解

    private static final Logger log = LoggerFactory.getLogger(BookController.class);
    ​
    @Slf4j  
  • 设置日志输出文件

logging:
  logback:
    rollingpolicy:
      max-file-size: 3KB
      file-name-pattern: server.%d{yyyy-MM-dd}.%i.log #%d标识日期,%i是一个递增变量
  file:
    name: server.log

3.开发篇

3.1热部署

  • 手动热部署

1.导入开发者工具依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

2.快捷键构建项目:**<ctrl>+<F9>

  • 自动热部署

1.设置自动构建项目:Build project automatically

2.允许程序在运行时自动构建项目:快捷键【Ctrl】+【Alt】+【Shit】+【/】打开维护面

注:idea设置当idea工具失去焦点5秒后进行热部署。其实就是你从idea工具中切换到其他工具时进行热部署,比如改完程序需要到浏览器上去调试,这个时候idea就自动进行热部署操作

  • 设置热部署控制文件配置范围或者关闭热部署

配置中默认不参与热部署的目录信息如下

/META-INF/maven
/META-INF/resources
/resources
/static
/public
/templates

修改配置,增加不参与热部署文件

  devtools:
    restart:
      exclude: static/**,templates/**,config/application.yml #设置文件不进行热部署
      enabled: false #关闭热部署
​
//系统参数关闭热部署,优先级大于配置文件但小于命令行参数
@SpringBootApplication
public class SSMPApplication {
    public static void main(String[] args) {
        System.setProperty("spring.devtools.restart.enabled","false");
        SpringApplication.run(SSMPApplication.class);
    }
}
  • 热部署原理:

重启与重载

​一个springboot项目在运行时实际上是分两个过程进行的,根据加载的东西不同,划分成base类加载器与restart类加载器。

  • base类加载器:用来加载jar包中的类,jar包中的类和配置文件由于不会发生变化,因此不管加载多少次,加载的内容不会发生变化

  • restart类加载器:用来加载开发者自己开发的类、配置文件、页面等信息,这一类文件受开发者影响

    当springboot项目启动时,base类加载器执行,加载jar包中的信息后,restart类加载器执行,加载开发者制作的内容。当执行构建项目后,由于jar中的信息不会变化,因此base类加载器无需再次执行,所以仅仅运行restart类加载即可,也就是将开发者自己制作的内容重新加载就行了,这就完成了一次热部署的过程,也可以说热部署的过程实际上是重新加载restart类加载器中的信息。

3.2高级配置2

  • 使用@ConfigurationProperties为第三方bean加载属性

@Bean
@ConfigurationProperties(prefix = "datasource")
public DruidDataSource datasource(){
    DruidDataSource ds = new DruidDataSource();
    return ds;
}
​
datasource:
  driverClassName: com.mysql.jdbc.Driver
  • 使用@EnableConfigurationProperties注解标注那些bean进行了属性绑定

    @SpringBootApplication
    @EnableConfigurationProperties(ServerConfig.class)
    public class Springboot13ConfigurationApplication {
    }
  • 计量单位配置

配置文件:

servers:
  ip-address: 192.168.0.1 
  port: 2345
  timeout: -1

绑定bean:

@Component
@Data
@ConfigurationProperties(prefix = "servers")
public class ServerConfig {
    @DurationUnit(ChronoUnit.HOURS)
    private Duration timeout;
    @DataSizeUnit(DataUnit.MEGABYTES)
    private DataSize dataSize;
}
​

Duration:表示时间间隔,可以通过@DurationUnit注解描述时间单位,例如上例中描述的单位为小时(ChronoUnit.HOURS)

DataSize:表示存储空间,可以通过@DataSizeUnit注解描述存储空间单位,例如上例中描述的单位为MB(DataUnit.MEGABYTES)

  • 配置校验

1.引入校验框架

<!--1.导入JSR303规范-->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
</dependency>
<!--使用hibernate框架提供的校验器做实现-->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>

2.添加校验注解@Validated,并设置属性值范围

@Component
@Data
@ConfigurationProperties(prefix = "servers")
//开启对当前bean的属性注入校验
@Validated
public class ServerConfig {
    //设置具体的规则
    @Max(value = 8888,message = "最大值不能超过8888")
    @Min(value = 202,message = "最小值不能低于202")
    private int port;
}

3.3测试

  • 添加测试临时属性

//properties属性可以为当前测试用例添加临时的属性配置
@SpringBootTest(properties = {"test.prop=testValue1"})
public class PropertiesAndArgsTest {
​
    @Value("${test.prop}")
    private String msg;
    
    @Test
    void testProperties(){
        System.out.println(msg);
    }
}
​
//args属性可以为当前测试用例添加临时的命令行参数
@SpringBootTest(args={"--test.prop=testValue2"})
public class PropertiesAndArgsTest {
    
    @Value("${test.prop}")
    private String msg;
    
    @Test
    void testProperties(){
        System.out.println(msg);
    }
}
//注:此设定应用范围仅适用于当前测试用例
  • 加载专用配置

@SpringBootTest
@Import({MsgConfig.class}) 
public class ConfigurationTest {
​
    @Autowired
    private String msg;
​
    @Test
    void testConfiguration(){
        System.out.println(msg);
    }
}
  • 模拟Web环境测试

基础:必须启动web环境

能力:测试程序中具备发送web请求的能力

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)  //启动web环境,采用随机端口
@AutoConfigureMockMvc //开启虚拟MVC调用
class JavaSpringbootApplicationTests {
​
    //定义发起虚拟调用的对象MockMVC
    @Autowired
    private MockMvc mvc;
​
    @Test
    void testWeb() throws Exception {
        //创建虚拟请求,当前访问/books(仅指定请求的具体路径即可)
        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/book");
        //执行对应的请求
        ResultActions result = mvc.perform(builder);
​
        //状态结果匹配器
        StatusResultMatchers status = MockMvcResultMatchers.status();
        //预计结果状态为200
        ResultMatcher resultStatus = status.isOk();
        //匹配状态结果
        result.andExpect(resultStatus);
​
        //响应体匹配
        ContentResultMatchers content = MockMvcResultMatchers.content();
        ResultMatcher resultContent = content.string("ok");
        //匹配响应体结果
        result.andExpect(resultContent);
​
        //响应头匹配
        HeaderResultMatchers header = MockMvcResultMatchers.header();
        ResultMatcher resultHeader = header.string("Content-Type", "application/json");
    }
}
​
  • 数据库事务测试

在原始测试用例中添加注解@Transactional即可实现当前测试用例的事务不提交

再添加一个@RollBack的注解,设置回滚状态为true即可正常提交事务

@SpringBootTest
@Transactional
@Rollback(true)
public class DaoTest {
}
  • 随机用例测试

testcase:
  book:
    id: ${random.int}
    id2: ${random.int(10)}
    type: ${random.int(5,10)}
    name: ${random.value}
    uuid: ${random.uuid}
    publishTime: ${random.long}
    
#注:其中()可以是任意字符,例如[],!!均可   
    
@Component
@Data
@ConfigurationProperties(prefix = "testcase.book")
public class BookCase {
    private int id;
    private int id2;
    private int type;
    private String name;
    private String uuid;
    private long publishTime;
}

3.4整合第三方技术

3.4.1缓存
3.4.2任务
  • Quartz

工作(Job):用于定义具体执行的工作

工作明细(JobDetail):用于描述定时工作相关的信息

触发器(Trigger):描述了工作明细与调度器的对应关系

调度器(Scheduler):用于描述触发工作的执行规则,通常使用cron表达式定义规则

1.引入依赖

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

2.创建任务

@Component
public class MyQuartz extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        System.out.println("quartz task run...");
    }
}

3.创建配置类

@Configuration
public class QuartzConfig {
​
    @Bean
    public JobDetail jobDetail(){
        //绑定具体的定时任务
        return JobBuilder.newJob(MyQuartz.class).storeDurably().build();
    }
​
    @Bean
    public Trigger trigger(){
        //定时
        ScheduleBuilder schedule = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
        //绑定对应的工作明细和定时表达式
        return TriggerBuilder.newTrigger().forJob(jobDetail()).withSchedule(schedule).build();
    }
}

使用newJob()操作传入对应的工作任务类型,使用forJob()操作传入绑定的工作明细对象

  • Task

1.spring自带的定时任务,不需要引入依赖,添加@EnableScheduling注解,开启定时任务功能

@SpringBootApplication
//开启定时任务功能
@EnableScheduling
public class SpringbootTaskApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot22TaskApplication.class, args);
    }
}

2.创建定时任务

@Component
public class MyBean {
    @Scheduled(cron = "0/1 * * * * ?")
    public void print(){
        System.out.println(Thread.currentThread().getName()+" :spring task run...");
    }
}

3.添加配置

spring:
  task:
    scheduling:
      pool:
        size: 1                       # 任务调度线程池大小 默认 1
      thread-name-prefix: ssm_          # 调度线程名称前缀 默认 scheduling-      
        shutdown:
          await-termination: false      # 线程池关闭时等待所有任务完成
          await-termination-period: 10s # 调度线程关闭前最大等待时间,确保最后一定关闭
3.4.3邮件

1.添加springboot整合javamail的starter

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

2.配置登录信息

spring:
  mail:
    host: smtp.qq.com
    username: ******@qq.com
    password: ****** #加密后的密码

password并不是邮箱账号的登录密码,是邮件供应商提供的一个加密后的密码,可以到邮件供应商的设置页面找POP3或IMAP这些关键词找到对应的获取位置

3.创建发送邮件服务

public class SendMailServiceImpl implements SendMailService {
​
    @Autowired
    private JavaMailSender javaMailSender;
​
    //发送人
    private String from = "******@qq.com";
    //接收人
    private String to = "*******@163.com";
    //标题
    private String subject = "测试邮件";
    //正文
    private String context = "测试邮件正文内容";
​
    @Override
    public void sendMail() {
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setFrom(from);
        mailMessage.setTo(to);
        mailMessage.setSubject(subject);
        mailMessage.setText(context);
​
        javaMailSender.send(mailMessage);
    }
}
​

4.发送复杂邮件

//发送网页正文邮件
public class SendMailServiceImpl2 implements SendMailService {
    @Autowired
    private JavaMailSender javaMailSender;
​
    //发送人
    private String from = "test@qq.com";
    //接收人
    private String to = "test@126.com";
    //标题
    private String subject = "测试邮件";
    //正文
    private String context = "<img src='ABC.JPG'/><a href='https://www.***.cn'>点开有惊喜</a>";
​
    public void sendMail() {
        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message);
            helper.setFrom(to);
            helper.setTo(from);
            helper.setSubject(subject);
            helper.setText(context,true);       //此处设置正文支持html解析
​
            javaMailSender.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
​
//发送带附件的邮件
public class SendMailServiceImpl2 implements SendMailService {
    @Autowired
    private JavaMailSender javaMailSender;
​
    //发送人
    private String from = "test@qq.com";
    //接收人
    private String to = "test@126.com";
    //标题
    private String subject = "测试邮件";
    //正文
    private String context = "测试邮件正文";
​
    public void sendMail() {
        try {
            MimeMessage message = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message,true); //此处设置支持附件
            helper.setFrom(to);
            helper.setTo(from);
            helper.setSubject(subject);
            helper.setText(context);
​
            //添加附件
            File f1 = new File("springboot_mail-0.0.1-SNAPSHOT.jar");
            File f2 = new File("resources\\logo.png");
​
            helper.addAttachment(f1.getName(),f1);
            helper.addAttachment("f2.png",f2);
​
            javaMailSender.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
3.4.4消息

3.5监控

采用Spring Boot Admin监控平台,配置流程如下

  1. 引入依赖

    <dependency>
        <groupId>de.codecentric</groupId>
        <artifactId>spring-boot-admin-starter-server</artifactId>
        <version>3.3.1</version>
    </dependency>
    ​
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  2. 添加@EnableAdminServer注解开启监控服务:访问地址:localhost:8080/applications

@SpringBootApplication
@EnableAdminServer
public class SpringbootAdminServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot25AdminServerApplication.class, args);
    }
}
  1. 制作客户端程序

<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.5.4</version>
</dependency>
​
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
​
设置当前客户端将信息上传到哪个服务器上
spring:
  boot:
    admin:
      client:
        url: http://localhost:8080
  1. 开放端点,开启http请求

一组是endpoints开头的,对所有端点进行配置,一组是endpoint开头的,对具体端点进行配置

management:
  endpoint:
    health: #端点名称
      show-details: always #显示客户信息
    info:
      enabled: true
  endpoints:
    web:
      exposure:
        include: "*" #使用“*”可以简化配置成开放所有端点的WEB端HTTP请求权限
    enabled-by-default: true    #是否开启默认端点,默认值true
​
  1. 自动定义端点:通过配置bean的方式为info端点添加信息

@Component
public class InfoConfig implements InfoContributor {
    @Override
    public void contribute(Info.Builder builder) {
        builder.withDetail("runTime",System.currentTimeMillis());       //添加单个信息
        Map infoMap = new HashMap();        
        infoMap.put("buildTime","2006");
        builder.withDetails(infoMap);                                   //添加一组信息
    }
}
​
@Component
public class HealthConfig extends AbstractHealthIndicator {
    @Override
    protected void doHealthCheck(Health.Builder builder) throws Exception {
        boolean condition = true;
        if(condition) {
            builder.status(Status.UP);                  //设置运行状态为启动状态
            builder.withDetail("runTime", System.currentTimeMillis());
            Map infoMap = new HashMap();
            infoMap.put("buildTime", "2006");
            builder.withDetails(infoMap);
        }else{
            builder.status(Status.OUT_OF_SERVICE);      //设置运行状态为不在服务状态
            builder.withDetail("上线了吗?","你做梦");
        }
    }
}
​
//自定义性能指标
@Service
public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {
    @Autowired
    private BookDao bookDao;
    private Counter counter;
​
    public BookServiceImpl(MeterRegistry meterRegistry){
        counter = meterRegistry.counter("用户付费操作次数:");
    }
​
    @Override
    public boolean delete(Integer id) {
        //每次执行删除业务等同于执行了付费业务
        counter.increment();
        return bookDao.deleteById(id) > 0;
    }
}
​
//自定义端点
@Component
@Endpoint(id="pay",enableByDefault = true)
public class PayEndpoint {
    @ReadOperation
    public Object getPay(){
        Map payMap = new HashMap();
        payMap.put("level 1","300");
        payMap.put("level 2","291");
        payMap.put("level 3","666");
        return payMap;
    }
}
注:此端点数据spirng boot admin无法预知该如何展示,所以通过界面无法看到此数据,通过HTTP请求路径可以获取到当前端点的信息,但是需要先开启当前端点对外功能,或者设置当前端点为默认开发的端点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值