SpringBoot2概览-开发实用篇

news2024/11/20 14:33:55

知识点


热部署

  • 概念:项目刚启动时需要完成重启+重载,而热部署只要重启即可(即仅加载当前开发者自定义开发的资源,不加载jar资源)

    • 重启:加载自定义开发代码,包含类、页面、配置文件等,加载位置在restart类加载器
    • 重载:加载jar包(后续不需要再重复加载),加载位置在base类加载器
  • 手动启动热部署:

    • 添加依赖包:
    <dependency>
    	<groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
    
    • 激活热部署:每次修改代码后,点击build project(快捷键为Ctrl + F9)
  • 自动启动热部署:每次修改代码后并且编辑器失去焦点后便会自动进行热部署

    • 设置自动构建项目:

    在这里插入图片描述

    • 设置自动构建项目:打开全局搜索(Ctrl+N),在Actions中搜索Registry

    在这里插入图片描述

  • 自定义不参与重启(热部署)的文件/文件夹:不想每次修改某文件的代码后去就自动重启进行热部署,可以进行相应配置

# 写在application.yml中即可
devtools:
  restart:
    exclude: public/**,static/**
  • 关闭热部署:热部署只需要在开发环境中有效,所以需要能随时关闭热部署。热部署的关闭可以在配置文件中进行,但该操作并不是优先级最高的方式,因此有可能会被其他方式的配置覆盖导致热部署又开启,所以需要进行最高优先级的配置
public static void main(String[] args) {
    System.setProperty("spring.devtools.restart.enabled", "false");
    SpringApplication.run(SSMPApplication.class);
}

配置高级

  • 第三方bean绑定属性:假设引入了DruidDataSource后需要设置数据库连接信息。此时使用@ConfigurationProperties接口,该注解除了可以为自定义的属性进行属性绑定(可参考01-基础篇/获取yml配置文件中的属性值),还可以进行第三方bean的属性绑定
// 不使用@ConfigurationProperties
@Bean
public DruidDataSource dataSource(){
    DruidDataSource ds = new DruidDataSource();
    ds.setDriverClassName("test1");
    return ds;
}
// 使用@ConfigurationProperties
@Bean
@ConfigurationProperties(prefix = "datasource")
public DruidDataSource dataSource(){
    DruidDataSource ds = new DruidDataSource();
    return ds;
}

// 测试代码
public static void main(String[] agrs){
    ConfigurableApplicationContext ctx = SpringApplication.run(
        SpringbootLearnApplication.class, args
    );
    DruidDataSource ds = ctx.getBean(DruidDataSource.class);
    System.out.println(ds.getDriverClassName());
}
datasource:
  driverClassName: test2
  • 宽松绑定:

    • @ConfigurationProperties绑定属性支持属性名宽松绑定,比如下面配置均能匹配上属性ipAddress
    servers:
      ipAddress: 192.168.1.1
      # 下面三种均可
      # ip_address: 192.168.1.2
      # IP_ADDRESS: 192.168.1.4
      # ip-address: 192.168.1.3  # 主流模式
      port: 2345
      timeout: -1
    
    @Data
    @ConfigurationProperties(prefix="servers")
    public class ServerConfig {
        private String ipAddress;
        private int port;
        private long timeout;
    }
    // 测试代码
    public static void main(String[] agrs){
        ConfigurableApplicationContext ctx = SpringApplication.run(
            SpringbootLearnApplication.class, args
        );
        ServerConfig bean = ctx.getBean(ServerConfig.class);
        System.out.println(bean);
    }
    
    • 不支持注解@Value引用单个属性的方式:即在yml配置文件中使用的名称必须和类中属性名一致
    @Value("${servers.ipAddress}") 
    private String msg;
    
    // 测试代码
    @Test
    void contextLoads(){
        // 如果在配置文件中不是以下写法则会报错
        // servers:
        //   ipAddress: 192.168.1.1
        System.out.println(msg);
    }
    
    • @ConfigurationProperties绑定仅能使用纯小写字母、数字、下划线作为合法的字符
    @Bean
    // "datasource"必须全部为小写,即使在配置文件中写的是dataSource:xxx
    @ConfigurationProperties(prefix = "datasource")
    public DruidDataSource datasource(){
        DruidDataSource ds = new DruidDataSource();
        return ds;
    }
    
  • 数据校验:在yml配置文件中定义的值可能与类中属性类型不匹配,需要先进行校验

    • 添加JSR303规范坐标与Hibernate校验框架对应坐标:
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
    </dependency>
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
    </dependency>
    
    • Bean开启校验功能并设置具体规则:
    @Component
    @Data
    @ConfigurationProperties(prefix = "servers")
    @Validated  // 开启校验
    public class ServerConfig {
        @Max(value = 400,message = "最大值不能超过400")  // 设置具体规则
        private int port;
    }
    

测试


  • 加载测试专用属性:该属性仅对当前测试类有效,缩小作用范围,降低冲突

    • 在启动测试环境时可以通过properties参数设置测试环境专用的属性
    // 在yml配置文件中不配置test.prop属性也会生效,如果都配置了则该处配置的优先级大于配置文件中的
    @SpringBootTest(properties = {"test.prop=testValue1"})
    public class PropertiesAndArgsTest {
        @Value("${test.prop}")
        private String msg;
    
        @Test
        void testProperties(){
            System.out.println(msg);  // 输出testValue1
        }
    }
    
    • 在启动测试环境时可以通过args参数设置测试环境专用的命令行参数
    // 相当于之前在命令行中添加属性(所以是--xxx.xxx的形式),如果在yml配置文件和properties中都配置了相同属性,该处的优先级最高(命令行的设置优先级高)
    @SpringBootTest(args = {"--test.arg=testValue2"})
    public class PropertiesAndArgsTest {
        @Value("${test.arg}")
        private String msg;
    
        @Test
        void testArgs(){
            System.out.println(msg);  // 输出testValue2
        }
    }
    
    • 使用@Import注解加载当前测试类专用的配置
    // 因为该类只需要在测试环境生效,所以不能定义在src目录下,应该定义在test目录下
    @Configuration
    public class MsgConfig {
        @Bean
        public String msg(){
            return "bean msg";
        }
    }
    
    @SpringBootTest
    @Import(MsgConfig.class)
    public class ConfigurationTest {
        @Autowired
        private String msg;
    
        @Test
        void testConfiguration(){
            System.out.println(msg);  // 输出bean msg
        }
    }
    
  • Web环境模拟测试:之前在测试类对数据层和业务层进行了测试,并未涉及到表现层的测试,测试表现层使用的是Postman

// 以下测试通过后没有提示信息,只有未通过才会有信息
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)  // 模拟端口
@AutoConfigureMockMvc  //开启虚拟MVC调用
public class WebTest {
    @Test
    void testGetById(@Autowired MockMvc mvc) throws Exception {
        // 1.创建虚拟请求,访问/books
        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/books");
        // 执行对应的请求
        ResultActions action = mvc.perform(builder);

        // 2.测试状态是否匹配
        // 定义本次调用的预期值(下面同理)
        StatusResultMatchers status = MockMvcResultMatchers.status();
        ResultMatcher ok = status.isOk();
        // 添加预计值到本次调用过程中进行匹配(下面同理)
        action.andExpect(ok);

        // 3.测试响应头是否匹配
        HeaderResultMatchers header = MockMvcResultMatchers.header();
        ResultMatcher contentType = header.string("Content-Type", "application/json");
        action.andExpect(contentType);

        // 4.测试响应体(json格式)是否匹配
        ContentResultMatchers content = MockMvcResultMatchers.content();
        ResultMatcher result = content.json("{\"id\":1,\"name\":\"springboot\",\"type\":\"springboot\",\"description\":\"springboot\"}");
        action.andExpect(result);
    }
}
  • 业务层测试事务回滚:每次执行测试只是想测试功能的运行情况,并不想在数据库中留下测试的数据
@SpringBootTest
@Transactional  // 为测试用例添加事务,执行了测试代码后数据库不会存在测试数据,但是id会加1,下次插入数据时id比上一条数据的大2
// @Rollback(false)  // 如果想留下测试数据,则在使用了@Transactional的前提下添加上该注解并设置为false
public class DaoTest {
    @Autowired
    private BookService bookService;
    
    // 具体操作数据库的代码
    ...
}
  • 测试用例数据设定:测试用例数据通常采用随机值进行测试,使用SpringBoot提供的随机数为其赋值
# 其中()可以是任意字符,例如[],!!均可
# 测试的设定代码写在测试环境的配置文件中
testcast:
  book:
    id: ${random.int}           # 随机整数
    id2: ${random.int(10)}      # 10以内随机数
    type: ${random.int(10,20)}  # 10到20随机数
    uuid: ${random.uuid}        # 随机uuid
    name: ${random.value}       # 随机字符串,MD5字符串,32位
    publishTime: ${random.long} # 随机整数(long范围)

数据层解决方案-SQL

现有数据层解决方案技术选型:数据源DruidDataSource + 持久化技术:MyBatis-Plus/MyBatis + 数据库MySQL

  • 数据源配置:假设不在配置文件中声明使用Druid数据源,并且不导入Druid的依赖包,则会使用SpringBoot内置数据源
    • HikariCP:默认内置数据源对象
    • Tomcat提供DataSourceHikariCP不可用的情况下,且在web环境中,将使用tomcat服务器配置的数据源对象
    • Commons DBCPHikari不可用,tomcat数据源也不可用,将使用dbcp数据源
spring:
  datasource:
    druid:  # 把该行删除,使用内置数据源
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/xxxx?serverTimezone=UTC
      username: xxxx
      password: xxxx

# 通用配置无法设置具体的数据源配置信息,仅提供基本的连接相关配置,如需配置,在下一级配置中设置具体设定
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/xxxx
    username: xxxx
    password: xxxx
    hikari:
      maximum-pool-size: 50
  • 内置持久化解决方案-JdbcTemplate:现在不使用MyBatis的依赖,并且导入spring-boot-starter-jdbc的依赖
@SpringBootTest
class SpringBootApplicationTest{
    @Autowired
	private JdbcTemplate jdbcTemplate;

    @Test
    void testJdbc(){
        String sql "select from tbl_book where id 1";
        List<Book>query jdbcTemplate.query(sql,new RowMapper<Book>(){
            @Override
            public Book mapRow(ResultSet rs,int rowNum) throws SQLException{
                Book temp new Book();
                temp.setId(rs.getInt("id"));
                temp.setName(rs.getstring("name"));
                temp.setType(rs.getstring("type"));
                temp.setDescription(rs.getstring("description"));
                return temp;
        	}
        });
        System.out.println(query);
    }
}
  • 内嵌数据库:SpringBoot提供了三种内嵌数据库(导入对应的依赖包就并且配置连接信息就能使用)供开发者选择,都在内存运行,运行速度快,提高开发测试效率
    • H2
    • HSQL
    • Derby

tips:

  • 即使不在配置文件声明使用DruidSpringBoot的自动装配也会找到依赖的包并且使用对应的数据源,就和导入web依赖包就能注解使用内置的Tomcat服务器一个道理
  • H2数据库控制台仅用于开发阶段,线上项目请务必关闭控制台功能,要不然会存在安全隐患
spring:
  h2:
  console:
    path: /h2
    enabled: false
  • SpringBoot可以根据url地址自动识别数据库种类,所以在保障驱动类存在的情况下可以省略配置(即省略driver-class-name)

数据层解决方案-NoSQL

上述的数据层解决方案是基于SQL的,现在介绍三种基于NoSQL

  • Redis

    • 概念:Redis是一款key-value存储结构的内存级NoSQL数据库

      • 支持多种数据存储格式
      • 支持持久化
      • 支持集群
    • 下载与安装(以Windows为例):

      • 下载(https://github.com/tporadowski/redis/releases)后在Windows解压安装或一键式安装
      • 服务端启动命令:redis-server.exe redis.windows.conf
      • 客户端启动命令:redis-cli.exe
    • SpringBoot整合Redis

      • 导入SpringBoot整合Redis的依赖包:
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-redis</artifactId>
      </dependency>
      
      • 配置Redis
      spring:
        redis:
          host: localhost # 127.0.0.1
          port: 6379
      
      • 使用RedisTemplate/StringRedisTemplate操作Redis
        • RedisTemplate以对象作为keyvalue,内部对数据进行序列化
        • **StringRedisTemplate**以字符串作为keyvalue,与Redis客户端操作等效(常用)
      @SpringBootTest
      class NosqlApplicationTests{
          @Autowired
          StringRedisTemplate redisTemplate;
      
          @Test
          void set(){
              ValueOperations ops = redisTemplate.opsForValue();
              ops.set("testKey","testvalue");
          }
      }
      
    • 客户端选择:可以选择使用lettcus(默认)与jedis。如果要切换为jedis则需要先导入jedis的依赖包,然后在配置文件中声明client-type: lettuce

      • jedis连接Redis服务器是直连模式,当多线程模式下使用jedis会存在线程安全问题,解决方案可以通过配置连接池使每个连接专用,但这样整体性能受影响
      • lettcus是基于Netty框架进行与Redis服务器连接,底层设计中采用StatefulRedisConnection,它自身是线程安全的,可以保障并发访问安全问题,所以一个连接可以被多线程复用。lettcus也支持多连接实例一起工作
  • Mongo

    • 概念:MongoDB是一个开源、高性能、无模式的文档型数据库,是最像关系型数据库的非关系型数据库,它可以存储游戏装备数据、直播数据、物联网数据等临时存储且修改频度高的数据

    • 下载与安装(以Windows为例):

      • 下载(https://www.mongodb.com/try/download)后在Windows解压并设置数据目录
      • 服务端启动命令:mongod --dbpath=..\data\db
      • 客户端启动命令:mongo --host=127.0.0.1 --port=27017
    • SpringBoot整合Mongo

      • 导入Mongodb驱动:
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-mongodb</artifactId>
      </dependency>
      
      • 配置客户端:
      spring:
        data:
          mongodb:
          uri: mongodb://localhost/xxxx
      
      • 客户端读写Mongodb
      @Test
      void testSave(@Autowired MongoTemplate mongoTemplate){
          Book book = new Book();
          book.setId(1);
          book.setType("springboot");
          book.setName("springboot");
          book.setDescription("springboot");
          mongoTemplate.save(book);
      }
      
  • ES

    • 概念:Elasticsearch是一个分布式全文搜索引擎

    • 下载与安装(以Windows为例):

      • 下载(https://www.elastic.co/cn/downloads/elasticsearch)后在Windows解压
      • 运行bin/elasticsearch.bat
    • SpringBoot整合ES

      • 导入坐标:SpringBoot平台并没有跟随ES的更新速度进行同步更新,所以不使用spring-boot-starter-data-elasticsearch
      <dependency>
          <groupId>org.elasticsearch.client</groupId>
          <artifactId>elasticsearch-rest-high-level-client</artifactId>
      </dependency>
      
      • 客户端代码:
      @Test
      void test() throws IOException {
          HttpHost host = HttpHost.create("http://localhost:9200");
          RestClientBuilder builder = RestClient.builder(host);
          RestHighLevelClient client = new RestHighLevelClient(builder);
          // 客户端操作
          CreateIndexRequest request = new CreateIndexRequest("books");
          // 获取操作索引的客户端对象,调用创建索引操作
          client.indices().create(request, RequestOptions.DEFAULT);
          // 关闭客户端
          client.close();
      }
      

tips:

  • 如果启动不了Redis的服务端,则需要先启动客户端,然后执行shutdown退出客户端,再去启动服务端即可
  • 在安装Mongo时可能会报找不到某个dll文件,则需要:
    • 下载对应的dll文件
    • 拷贝到windows安装路径下的system32目录中
    • 执行命令注册对应dll文件:regsvr32 xxxx.dll

整合第三方技术

  • 缓存:

    • 概念:

      • 缓存是一种介于数据永久存储介质与数据应用之间的数据临时存储介质
      • 使用缓存可以有效的减少低速数据读取过程的次数(例如磁盘IO),提高系统性能
      • 缓存不仅可以用于提高永久性存储介质的数据读取效率,还可以提供临时的数据存储空间(即存储代码运行过程中生成的数据)
    • 使用:以默认的缓存方案为例(还有RedisEhcachememcached等其他缓存技术,但是接口是统一的)

      • 导入缓存技术对应的starter
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-cache</artifactId>
      </dependency>
      
      • 启用缓存:
      @SpringBootApplication
      @EnableCaching  // 开启缓存
      public class CacheApplication {
          public static void main(String[] args) {
              SpringApplication.run(CacheApplication.class, args);
          }
      }
      
      • 设置当前操作的结果数据进入缓存:
      // value指定缓存放在哪里,key表示下次用什么去找该缓存好的数据
      @Cacheable(value="cacheSpace", key="#id")  
      public Book getById(Integer id) {  // 初次执行会去数据库中查,后面不会,直接从缓存中取
          return bookDao.selectById(id);
      }
      
  • 任务:

    • 概念:

      • 定时任务是企业级应用中的常见操作,比如制作年度报表、缓存统计报告等

      • 市面上流行的定时任务技术有QuartzSpring Task

      • 相关词汇:

        • 工作(Job):用于定义具体执行的工作
        • 工作明细(JobDetail):用于描述定时工作相关的信息
        • 触发器(Trigger):用于描述触发工作的规则,通常使用cron表达式定义调度规则
        • 调度器(Scheduler):描述了工作明细与触发器的对应关系
    • 使用:

      • SpringBoot整合Quartz

        • 导入SpringBoot整合quartz的坐标:
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>
        
        • 定义具体要执行的任务,继承QuartzJobBean
        // 具体的工作,只需要声明为普通的类,不需要给Spring管理
        public class QuartzTaskBean extends QuartzJobBean {
            @Override
            protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
                System.out.println(“quartz job run... ");
            }
        }
        
        • 定义工作明细与触发器,并绑定对应关系:
        @Configuration
        public class QuartzConfig {
            @Bean
            public JobDetail printJobDetail(){
                // 绑定具体的工作
                return JobBuilder.newJob(QuartzTaskBean.class).storeDurably().build();
            }
        
            @Bean
            public Trigger printJobTrigger() {
                CronScheduleBuilder cronScheduleBuilder = 
                    CronScheduleBuilder.cronSchedule("0/3 * * * * ?");
                return TriggerBuilder
                    .newTrigger()
                    .forJob(printJobDetail())
                    .withSchedule(cronScheduleBuilder).build();
            }
        }
        
      • Spring Task

        • 开启定时任务功能:
        @SpringBootApplication
        @EnableScheduling
        public class TaskApplication {
            public static void main(String[] args) {
                SpringApplication.run(TaskApplication.class, args);
            }
        }
        
        • 设置定时执行的任务,并设定执行周期:
        @Component
        public class ScheduledBean {
            @Scheduled(cron = "0/5 * * * * ?")
            public void printLog(){
                System.out.println(Thread.currentThread().getName()+":run...");
            }
        }
        
        • 定时任务相关配置:
        spring:
          task:
            scheduling:
            #任务凋度线程池大小,默认为1
            pool:
              size: 1
            #调度线程名称前缀,默认为scheduling-
            thread-name-prefix: xxx_
            shutdown:
              # 线程池关闭时等待所有任务完成
              await-termination: false
              # 调度线程关闭前最大等待时间,确保最后一定关闭
              await-termination-period: 10s
        
  • 消息:

    • 概念:

      • 处理消息的双方:分为消息发送方(生产者)和消息接收方(消费者)
      • 消息分类:异步(不需要对方进行确认后也能接着发)和同步(需要对方进行确认后才能接着发)消息
      • 消息队列:单个业务系统处理所有请求的压力太大,所以将每个请求转换为一个个的消息并存储在消息队列(MQ)中,而子业务系统则从中获取消息去处理。其中所有MQ技术均需要遵循JMSAMQPMQTT中的规范或协议

      在这里插入图片描述

    • JMS(Java Message Service):一个规范,等同于JDBC规范,提供了与消息服务相关的API接口

      • JMS消息模型:
        • peer-2-peer:点对点模型,消息发送到一个队列中后队列保存消息。队列的消息只能被一个消费者消费,或超时
        • publish-subscribe:发布订阅模型,消息可以被多个消费者消费,生产者和消费者完全独立,不需要感知对方的存在
      • JMS消息种类:
        • extMessage
        • MapMessage
        • BytesMessage
        • StreamMessage
        • ObjectMessage
        • Message (只有消息头和属性)
      • JMS实现:ActiveMQRedisHornetMQRabbitMQRocketMQ(没有完全遵守JMS规范)
    • AMQP(advanced message queuing protocol):一种协议,规范了网络交换的数据格式,兼容JMS具有跨平台性,服务器供应商、生产者和消费者可以使用不同的语言来实现

      • AMQP消息模型:
        • direct exchange
        • fanout exchange
        • topic exchange
        • headers exchange
        • system exchange
      • AMQP消息种类:byte[]
      • AMQP实现:RabbitMQStormMQRocketMQ
    • MQTT(Message Queueing Telemetry Transport):消息队列遥测传输,专为小设备设计,是物联网生态系统中主要成分

  • 监控:

    • 意义:
      • 监控服务状态是否宕机
      • 监控服务运行指标(内存、虚拟机、线程、请求等)
      • 监控日志
      • 管理服务(服务下线)
    • 实施方式:
      • 显示监控信息的服务器:用于获取服务信息(可以主动拉取,也可以被动获取),并显示对应的信息
      • 运行的服务:启动时主动上报,告知监控服务器自己需要受到监控(告知服务器自己是否需要被监控,哪些部分被监控)
    • 原理:
      • Actuator提供了SpringBoot生产就绪功能,通过端点(其实就是请求,每个请求可以获取到不同的监控信息)的配置与访问,获取端点信息
      • 端点描述了一组监控信息,SpringBoot提供了多个内置端点,也可以根据需要自定义端点信息
      • 访问当前应用所有端点信息:/actuator;访问端点详细信息:/actuator/端点名称(比如访问/actuator/health获取到应用程序的健康信息)

注意事项


  • @EnableConfigurationProperties可将使用@ConfigurationProperties对应的类加入Spring容器,所以@EnableConfigurationProperties@Component不能同时使用
// 之所以将@Component注释是因为在主程序中用@EnableConfigurationProperties将ServerConfig类完成了注入,再加会报错
// @Component
@Data
@ConfigurationProperties(prefix = "servers")
public class ServerConfig {...}

// 主程序
@SpringBootApplication
@EnableConfigurationProperties(ServerConfig.class)
public class DemoApplication {}
  • IDEA有时会报识别不了@ConfigurationProperties注解,可添加下面依赖接触警告:
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
  • yml文件中对于数字的定义支持进制书写格式,如需使用字符串请使用引号明确标注,要不然会出现以下情况:
# 配置文件
dataSource:
password: 0127  # 需要写为"0127"
@Value("${dataSource.password}") 
private String password;

// 测试代码
@Test
void contextLoads(){
  System.out.println(password);  // 输出87: 因为0127会被识别为二进制,然后转换为十进制输出
}

资料

视频参考黑马程序员SpringBoot2全套视频教程 P70-P142


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/686327.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot项目如何将配置文件外挂

为什么要将配置文件外挂 因为springboot项目一般打出来的是jar包&#xff0c;如果要对里面的配置做修改&#xff0c;会比较麻烦&#xff0c;所以需要将配置文件外挂&#xff0c;方便操作哦 怎么做呢 我们先看一个常见的springboot项目的配置文件结构&#xff1a; 分为四个配…

InnoDB的三种行锁(提供具体sql执行案例分析)

InnoDB存储引擎有3种行锁的算法&#xff0c;其分别是&#xff1a; Record Lock&#xff08;记录锁&#xff09;&#xff1a;单个行记录上的范围 (锁住某一行记录)Gap Lock&#xff08;间隙锁&#xff09;&#xff1a;间隙锁&#xff0c;锁定一个范围&#xff0c;但不包含记录本…

十大公认音质好的骨传导耳机,几款音质排行靠前的骨传导耳机

骨传导耳机是通过头部骨迷路传递声音&#xff0c;而不是直接通过耳膜的振动来传递声音。与传统的入耳式耳机相比&#xff0c;骨传导耳机不会堵耳朵&#xff0c;在跑步、骑车等运动时可以更好的接收外界环境音&#xff0c;保护听力&#xff0c;提升安全性。此外&#xff0c;骨传…

Canvas基本使用

1.canvas基本使用 1.1.说明&#xff1a; canvas是双标签,h5中新增的属性默认宽高为300*150浏览器默认canvas展示的是一张图片给canvas添加文字内容是没有任何意义的canvas画布&#xff1a;绘制图形&#xff0c;显示一个文字&#xff0c;必须通过js操作 不要通过样式去设置画…

15.OCR

15.1 OCR流水线及七工作原理 Photo OCR&#xff1a;照片 光学字符识别(photo optical character recognition) Photo OCR注重的问题&#xff1a;如何让计算机都出图片中的文字信息&#xff0c;它有以下步骤&#xff1a; 首先给定某张图片&#xff0c;它将图像扫描一遍&#…

基于小程序的用户服务技术研究

目录 1. 小程序开发技术原理 2. 用户服务设计3. 数据库设计和管理4. 安全和隐私保护5. 性能优化和测试总结 关于基于小程序的用户服务技术研究&#xff0c;这是一个非常广泛和复杂的领域&#xff0c;需要涉及多个方面的知识和技术。一般来说&#xff0c;基于小程序的用户服务技…

零基础想入门网安行业,看这一篇就够了!!!

由于我之前写了不少网络安全技术相关的故事文章&#xff0c;不少读者朋友知道我是从事网络安全相关的工作&#xff0c;于是经常有人在微信里问我&#xff1a; 我刚入门网络安全&#xff0c;该怎么学&#xff1f;要学哪些东西&#xff1f;有哪些方向&#xff1f;怎么选&#xff…

跟着AIGC学Linux:简介(一)

文章目录 1.Linux内核的历史2.基本概念3.发行版4.Linux应用领域5.Linux VS Windows横向对比表格&#xff1a; 1.Linux内核的历史 Linux内核最初由一位名叫Linus Torvalds的芬兰计算机科学家于1991年创建。当时&#xff0c;Torvalds是一名赫尔辛基大学的学生&#xff0c;他在寻…

ROS:话题通信机制详解

目录 ROS&#xff1a;通信机制一、话题通信简介二、话题通信实操&#xff08;C&#xff09;2.1分析2.2发布方代码2.3订阅方代码2.4配置CMakeLists.txt2.5执行2.6注意 三、话题通信实操&#xff08;python&#xff09;3.1分析3.2发布方代码3.3订阅方代码3.4添加可执行权限3.5配置…

Apache Log4j2 漏洞原理

Apache Log4j 远程代码执行漏洞 1.漏洞危害 Apache Log4j被发现存在一处任意代码执行漏洞&#xff0c;由于Apache Log4j2某些功能存在递归解析功能&#xff0c;攻击者可直接构造恶意请求&#xff0c;触发远程代码执行漏洞。经验证&#xff0c;Apache Struts2、Apache Solr、Ap…

Win10控制面板在哪里打开?Win10控制面板打开方式介绍

Win10控制面板在哪里打开&#xff1f;当前很多用户都在使用Win10系统&#xff0c;一些新手用户不清楚在哪里才能打开Win10系统的控制面板&#xff0c;以下给大家介绍三种方式&#xff0c;帮助用户们轻松快速打开Win10控制面板&#xff0c;打开控制面板后用户即可展开不同的设置…

5-1图像信息提取适当剪掉像素点(matlab程序)

代码及运行结果 clear ; close all; gr imread(cameraman.tif); subplot(1,3,1); imshow(gr); subplot(1,3,2); D dct2(gr); F log(abs(D)); imshow(F,[]); subplot(1,3,3); D(abs(D)<200) 0; %会丢掉很多点 &#xff0c;但是原图还可识别&#xff0c;适合做信息提取 M …

这所院校很保护一志愿,学硕爆冷,全部录取,专硕初试第三竟主动放弃录取!

一、学校及专业介绍 广州大学&#xff08;Guangzhou University&#xff09;&#xff0c;简称广大&#xff08;GU&#xff09;&#xff0c;是由广东省广州市人民政府举办的全日制普通高等学校&#xff0c;实行省市共建、以市为主的办学体制&#xff0c;是国家“111计划”建设高…

c语言结构体属性之__attribute__((packed))

c语言结构体属性之__attribute__((packed)) 0. 引出 事情是这样的&#xff0c;最近在做代码移植时见到了这样一段代码 typedef struct {uint16_t len;uint8_t data[PAIRING_MAX_LEN]; } pairing_rx_buffer_t;static pairing_rx_buffer_t pairing_rx_buffer {}; typedef str…

四大世界权威大学排名指标及侧重点

U.S.News、QS、ARWU、THE是公认的四大权威世界大学排名&#xff0c;每个排名的侧重点各有不同&#xff0c;故知识人网小编撰文加以介绍。 很多博士后、访问学者和联合培养博士的申请者会注重学校排名。那么都有哪些排名体系呢&#xff1f;一般来说&#xff0c;国际公认的四大权…

PLC技能在职场中的竞争力如何?

在当前的工作市场上&#xff0c;仅仅掌握PLC可能会限制您的竞争力。尽管PLC在自动化控制系统中扮演重要的角色&#xff0c;但现代工业界对多样化技能和知识的需求越来越高。 为了提高竞争力&#xff0c;以下是一些建议&#xff1a; 学习其他自动化技术&#xff1a;除了PLC&am…

人脸跟踪:基于人脸检测API的连续检测与姿态估计技术

人脸跟踪技术在视频监控、虚拟现实和人机交互等领域发挥着重要作用。通过连续的人脸检测与姿态估计&#xff0c;可以实现对人脸在视频序列中的跟踪和姿态分析。 本文将介绍基于人脸检测API的人脸跟踪技术&#xff0c;探讨其原理、应用场景以及未来发展前景。 人脸跟踪的意义和…

typescript中interface,type和Record的使用

vitevue3ts中interface&#xff0c;type和Record的使用 vitevue3ts中interface&#xff0c;type和Record的使用 interface&#xff1a;接口type&#xff1a;类型别名 基本类型组合元组类型捕捉遍历属性 扩展 interface扩展interface&#xff08;合并&#xff09;interface扩展i…

你以为的网络工程师VS实际工作中的网络工程师

我的网工朋友&#xff0c;大家好。 前两天不是端午节嘛&#xff0c;去亲戚家吃饭。饭后闲聊说起&#xff0c;他们家的电脑开不了机了&#xff0c;问我能不能修下。 我说我不太会&#xff0c;让他们打电话报修&#xff0c;会有人上门看的。 结果亲戚蹦出一句话&#xff1a;你…

Qt Widget提升为QChartView绘制曲线

1、在工程文件"*.pro"中添加"charts"组件 在工程文件"*.pro"中添加"charts"组件&#xff0c;同时在工程文件添加qcustomplot类。 QT core gui printsupport charts下载qcustomplot类。 网址&#xff1a;https://www.qcustom…