【SpringBoot】--03.数据访问、基础特性(外部化和内部外配置、整合JUnit)

news/2025/1/6 7:59:17/

文章目录

  • SpringBoot3-数据访问
  • 1.整合SSM场景
    • 1.1创建SSM整合项目
    • 1.2配置数据源
    • 1.3配置MyBatis
    • 1.4CRUD编写
  • 2.自动配置原理
  • 3.扩展:整合其他数据源
    • 3.1 Druid 数据源
  • SpringBoot3-基础特性
  • 1. SpringApplication
    • 1.1 自定义 banner
    • 1.2.自定义 SpringApplication
    • 1.3FluentBuilder API
  • 2.Profiles
    • 2.1 使用
      • 2.1.1 指定环境
      • 2.1.2 环境激活
      • 2.1.3 环境包含
    • 2.2 Profile 分组
    • 2.3Profile 配置文件
  • 3.外部化配置
    • 3.1 配置优先级
    • 3.2. 外部配置
    • 3.3. 导入配置
    • 3.4. 属性占位符
  • 4. 单元测试-JUnit5
    • 4.1 整合
    • 4.2测试
      • 4.2.0 组件测试
      • 4.2.1 注解
      • 4.2.2 断言
      • 4.2.3 嵌套测试
      • 4.2.4 参数化测试

学习视频: 尚硅谷SpringBoot3视频

SpringBoot3-数据访问

1.整合SSM场景

SpringBoot 整合 SpringSpringMVCMyBatis 进行数据访问场景开发

1.1创建SSM整合项目

image-20230712161250792

勾选之后会导入以下包

<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.1</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency>

1.2配置数据源

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root

安装MyBatisX 插件,帮我们生成Mapper接口的xml文件即可
在接口处 : Alt + 回车

1.3配置MyBatis

必须把mapper的xml文件映射位置在配置文件定义!
而驼峰命名转换建议也开启

#指定mapper映射文件位置
mybatis.mapper-locations=classpath:/mapper/*.xml
#驼峰命名转换
mybatis.configuration.map-underscore-to-camel-case=true

1.4CRUD编写

  • 编写Bean
package com.atguigu.boot.ssm.bean;import lombok.Data;@Data
public class TUser {private Integer id;private String loginName;private String nickName;private String passwd;
}
  • 编写Mapper
public interface UserMapper {public TUser getUserById(@Param("id") Long id);}
  • 使用mybatisx插件,快速生成MapperXML
<?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.atguigu.boot.ssm.mapper.UserMapper"><select id="getUserById" resultType="com.atguigu.boot.ssm.bean.TUser">select * from t_user where id=#{id}</select>
</mapper>
  • 测试CRUD

UserController

@RestController
public class UserController {@AutowiredUserMapper userMapper;@GetMapping("/user/{id}")public TUser getUser(@PathVariable("id") Long id){TUser user = userMapper.getUserById(id);return user;}
}
/*** 1.@MapperScan告诉Mybatis,扫描哪个包下面的所有接口* 2.使用mybatis.mapper-locations 告诉mybatis,每个接口的xml文件都在哪里*/
@MapperScan(basePackages = "com.atguigu.boot.ssm.mapper")
@SpringBootApplication
public class Boot05SsmApplication {public static void main(String[] args) {SpringApplication.run(Boot05SsmApplication.class, args);}}

运行结果:

image-20230712170658192

2.自动配置原理

  1. 导入 mybatis-spring-boot-starter
  2. 配置数据源信息
  3. 配置mybatis的 mapper接口扫描xml映射文件扫描
  4. 编写bean,mapper,生成xml,编写sql 进行crud。事务等操作依然和Spring中用法一样
  5. 效果:
    - 所有sql写在xml中
    - 所有mybatis配置写在application.properties下面
  • jdbc场景的自动配置

    • mybatis-spring-boot-starter导入 spring-boot-starter-jdbc,jdbc是操作数据库的场景

    • Jdbc场景的几个自动配置

      • org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

        • 数据源的自动配置
        • 所有和数据源有关的配置都绑定在DataSourceProperties
        • 默认使用 HikariDataSource
      • org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration

        • 给容器中放了JdbcTemplate操作数据库
      • org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration

      • org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration

        • 基于XA二阶提交协议的分布式事务数据源
      • org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration

        • 支持事务
    • 具有的底层能力:数据源、JdbcTemplate事务

  • MyBatisAutoConfiguration:配置了MyBatis的整合流程

    • mybatis-spring-boot-starter导入 mybatis-spring-boot-autoconfigure(mybatis的自动配置包)

    • 默认加载两个自动配置类:

      • org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration

      • org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

        • 必须在数据源配置好之后才配置
        • 给容器中SqlSessionFactory组件。创建和数据库的一次会话
        • 给容器中SqlSessionTemplate组件。操作数据库
    • MyBatis的所有配置绑定在MybatisProperties

    • 每个Mapper接口代理对象是怎么创建放到容器中。详见**@MapperScan**原理:

      • 利用@Import(MapperScannerRegistrar.class)批量给容器中注册组件。解析指定的包路径里面的每一个类,为每一个Mapper接口类,创建Bean定义信息,注册到容器中。

如何分析哪个场景导入以后,开启了哪些自动配置类。

找:classpath:/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中配置的所有值,就是要开启的自动配置类,但是每个类可能有条件注解,基于条件注解判断哪个自动配置类生效了。

快速定位生效的配置

#开启调试模式,详细打印开启了哪些自动配置
debug=true
# Positive(生效的自动配置)  Negative(不生效的自动配置)

3.扩展:整合其他数据源

3.1 Druid 数据源

暂不支持 SpringBoot3

  • 导入druid-starter
  • 写配置
  • 分析自动配置了哪些东西,怎么用

Druid官网

#数据源基本配置
spring.datasource.url=jdbc:mysql://192.168.200.100:3306/demo
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource# 配置StatFilter监控
spring.datasource.druid.filter.stat.enabled=true
spring.datasource.druid.filter.stat.db-type=mysql
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=2000
# 配置WallFilter防火墙
spring.datasource.druid.filter.wall.enabled=true
spring.datasource.druid.filter.wall.db-type=mysql
spring.datasource.druid.filter.wall.config.delete-allow=false
spring.datasource.druid.filter.wall.config.drop-table-allow=false
# 配置监控页,内置监控页面的首页是 /druid/index.html
spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=admin
spring.datasource.druid.stat-view-servlet.allow=*# 其他 Filter 配置不再演示
# 目前为以下 Filter 提供了配置支持,请参考文档或者根据IDE提示(spring.datasource.druid.filter.*)进行配置。
# StatFilter
# WallFilter
# ConfigFilter
# EncodingConvertFilter
# Slf4jLogFilter
# Log4jFilter
# Log4j2Filter
# CommonsLogFilter

附录:示例数据库

CREATE DATABASE IF NOT EXISTS test;
USE test;
CREATE TABLE `t_user`
(`id`         BIGINT(20)   NOT NULL AUTO_INCREMENT COMMENT '编号',`login_name` VARCHAR(200) NULL DEFAULT NULL COMMENT '用户名称' COLLATE 'utf8_general_ci',`nick_name`  VARCHAR(200) NULL DEFAULT NULL COMMENT '用户昵称' COLLATE 'utf8_general_ci',`passwd`     VARCHAR(200) NULL DEFAULT NULL COMMENT '用户密码' COLLATE 'utf8_general_ci',PRIMARY KEY (`id`)
);
insert into t_user(login_name, nick_name, passwd) VALUES ('zhangsan','张三','123456');

SpringBoot3-基础特性

1. SpringApplication

1.1 自定义 banner

  1. 类路径添加banner.txt或设置spring.banner.location就可以定制 banner
    1. 推荐网站:Spring Boot banner 在线生成工具,制作下载英文 banner.txt,修改替换 banner.txt 文字实现自定义,个性化启动 banner-bootschool.net

1.2.自定义 SpringApplication

import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class MyApplication {public static void main(String[] args) {//1.SpringApplication:Boot应用的核心API入口//SpringApplication.run(Boot306FeaturesApplication.class,args);//1.自定义SpringApplication的底层设置SpringApplication application = new SpringApplication(MyApplication.class);//程序化调整SpringApplication的参数//application.setDefaultProperties();//这个配置不优先//2.调整SpringApplication的参数application.setBannerMode(Banner.Mode.OFF);//3.SpringApplication运行起来application.run(args);}

1.3FluentBuilder API

流式方式启动SpringApplication

new SpringApplicationBuilder().sources(Parent.class).child(Application.class).bannerMode(Banner.Mode.OFF).run(args);

2.Profiles

环境隔离能力;快速切换开发、测试、生产环境

步骤:

  1. 标识环境:指定哪些组件、配置在哪个环境生效
  2. 切换环境:这个环境对应的所有组件和配置就应该生效

2.1 使用

2.1.1 指定环境

  • Spring Profiles 提供一种隔离配置的方式,使其仅在特定环境生效;
  • 任何@Component, @Configuration@ConfigurationProperties 可以使用 @Profile 标记,来指定何时被加载。【容器中的组件都可以被 @Profile标记】

2.1.2 环境激活

1.配置激活指定环境; 配置文件

spring.profiles.active=production,hsqldb

2.也可以使用命令行激活。--spring.profiles.active=dev,hsqldb

3.还可以配置默认环境不标注@Profile 的组件永远都存在。

  1. 以前默认环境叫default
  2. spring.profiles.default=test

4.推荐使用激活方式激活指定环境

2.1.3 环境包含

注意:

  1. spring.profiles.activespring.profiles.default 只能用到 无 profile 的文件中,如果在application-dev.yaml中编写就是无效的
  2. 也可以额外添加生效文件,而不是激活替换。比如:
spring.profiles.include[0]=common
spring.profiles.include[1]=local

最佳实战:

  • 生效的环境 = 激活的环境/默认环境 + 包含的环境

  • 项目里面这么用

    • 基础的配置mybatislogxxx:写到包含环境中
    • 需要动态切换变化的 dbredis:写到激活的环境中

2.2 Profile 分组

创建prod组,指定包含dbmq配置

spring.profiles.group.prod[0]=db
spring.profiles.group.prod[1]=mq

使用--spring.profiles.active=prod ,就会激活proddbmq配置文件

2.3Profile 配置文件

  • application-{profile}.properties可以作为指定环境的配置文件

  • 激活这个环境,配置就会生效。最终生效的所有配置

    • application.properties:主配置文件,任意时候都生效
    • application-{profile}.properties:指定环境配置文件,激活指定环境生效

如果发生配置冲突:profile优先级 > application

3.外部化配置

场景:线上应用如何快速修改配置,并应用最新配置

  • SpringBoot 使用 配置优先级 + 外部配置 简化配置更新、简化运维。
  • 只需要给jar应用所在的文件夹放一个application.properties最新配置文件,重启项目就能自动应用最新配置

3.1 配置优先级

Spring Boot 允许将配置外部化,以便可以在不同的环境中使用相同的应用程序代码。

我们可以使用各种外部配置源,包括Java Properties文件、YAML文件、环境变量和命令行参数。

@Value可以获取值,也可以用@ConfigurationProperties将所有属性绑定到java object中

以下是 SpringBoot 属性源加载顺序。 后面的会覆盖前面的值。由低到高,高优先级配置覆盖低优先级

  1. 默认属性(通过SpringApplication.setDefaultProperties指定的)
  2. @PropertySource指定加载的配置(需要写在@Configuration类上才可生效)
  3. 配置文件(application.properties/yml等)
  4. RandomValuePropertySource支持的random.*配置(如:@Value(“${random.int}”))
  5. OS 环境变量
  6. Java 系统属性(System.getProperties()
  7. JNDI 属性(来自java:comp/env
  8. ServletContext 初始化参数
  9. ServletConfig 初始化参数
  10. SPRING_APPLICATION_JSON属性(内置在环境变量或系统属性中的 JSON)
  11. 命令行参数
  12. 测试属性。(@SpringBootTest进行测试时指定的属性)
  13. 测试类@TestPropertySource注解
  14. Devtools 设置的全局属性。($HOME/.config/spring-boot)

结论:配置可以写到很多位置,常见的优先级顺序:

  • 命令行> 配置文件> springapplication配置

配置文件优先级如下:(后面覆盖前面)

  1. jar 包内application.properties/yml
  2. jar 包内application-{profile}.properties/yml
  3. jar 包外application.properties/yml
  4. jar 包外application-{profile}.properties/yml

建议用一种格式的配置文件如果.properties和.yml同时存在,则.properties优先

结论:包外 > 包内; 同级情况:profile配置 > application配置

所有参数均可由命令行传入,使用--参数项=参数值,将会被添加到环境变量中,并优先于配置文件

比如java -jar app.jar --name="Spring",可以使用@Value("${name}")获取

演示场景:

  • 包内: application.properties server.port=8000
  • 包内: application-dev.properties server.port=9000
  • 包外: application.properties server.port=8001
  • 包外: application-dev.properties server.port=9001

启动端口?:命令行 > 9001 > 8001 > 9000 > 8000

3.2. 外部配置

SpringBoot 应用启动时会自动寻找application.properties和application.yaml位置,进行加载。顺序如下:(后面覆盖前面

1.类路径: 内部

  1. 类根路径
  2. 类下/config包

2.当前路径(项目所在的位置)

  1. 当前路径
  2. 当前下/config子目录
  3. /config目录的直接子目录

最终效果:优先级由高到低,前面覆盖后面

  • 命令行 > 包外config直接子目录 > 包外config目录 > 包外根目录 > 包内目录

  • 同级比较:

    • profile配置 > 默认配置
    • properties配置 > yaml配置

image-20230712201336962

规律:最外层的最优先。

  • 命令行 > 所有
  • 包外 > 包内
  • config目录 > 根目录
  • profile > application

配置不同就都生效(互补),配置相同高优先级覆盖低优先级

3.3. 导入配置

使用spring.config.import可以导入额外配置

spring.config.import=my.properties
my.property=value

无论以上写法的先后顺序,my.properties的值总是优先于直接在文件中编写的my.property。

3.4. 属性占位符

配置文件中可以使用 ${name:default}形式取出之前配置过的值。

app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}

4. 单元测试-JUnit5

4.1 整合

SpringBoot 提供一系列测试工具集及注解方便我们进行测试。

spring-boot-test提供核心测试能力,spring-boot-test-autoconfigure 提供测试的一些自动配置。

我们只需要导入spring-boot-starter-test 即可整合测试

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

spring-boot-starter-test 默认提供了以下库供我们测试使用

  • JUnit 5
  • Spring Test
  • AssertJ
  • Hamcrest
  • Mockito
  • JSONassert
  • JsonPath

4.2测试

4.2.0 组件测试

直接@Autowired容器中的组件进行测试

4.2.1 注解

JUnit5的注解与JUnit4的注解有所变化

https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations

  • @Test:表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试
  • @ParameterizedTest:表示方法是参数化测试,下方会有详细介绍
  • @RepeatedTest:表示方法可重复执行,下方会有详细介绍
  • @DisplayName:为测试类或者测试方法设置展示名称
  • @BeforeEach:表示在每个单元测试之前执行
  • @AfterEach:表示在每个单元测试之后执行
  • @BeforeAll:表示在所有单元测试之前执行
  • @AfterAll:表示在所有单元测试之后执行
  • @Tag:表示单元测试类别,类似于JUnit4中的@Categories
  • @Disabled:表示测试类或测试方法不执行,类似于JUnit4中的@Ignore
  • @Timeout:表示测试方法运行如果超过了指定时间将会返回错误
  • @ExtendWith:为测试类或测试方法提供扩展类引用
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeTrue;import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;class StandardTests {@BeforeAllstatic void initAll() {}@BeforeEachvoid init() {}@DisplayName("😱")@Testvoid succeedingTest() {}@Testvoid failingTest() {fail("a failing test");}@Test@Disabled("for demonstration purposes")void skippedTest() {// not executed}@Testvoid abortedTest() {assumeTrue("abc".contains("Z"));fail("test should have been aborted");}@AfterEachvoid tearDown() {}@AfterAllstatic void tearDownAll() {}}

4.2.2 断言

方法说明
assertEquals判断两个对象或两个原始类型是否相等
assertNotEquals判断两个对象或两个原始类型是否不相等
assertSame判断两个对象引用是否指向同一个对象
assertNotSame判断两个对象引用是否指向不同的对象
assertTrue判断给定的布尔值是否为 true
assertFalse判断给定的布尔值是否为 false
assertNull判断给定的对象引用是否为 null
assertNotNull判断给定的对象引用是否不为 null
assertArrayEquals数组断言
assertAll组合断言
assertThrows异常断言
assertTimeout超时断言
fail快速失败

4.2.3 嵌套测试

JUnit 5 可以通过 Java 中的内部类和@Nested 注解实现嵌套测试,从而可以更好的把相关的测试方法组织在一起。在内部类中可以使用@BeforeEach 和@AfterEach 注解,而且嵌套的层次没有限制。

@DisplayName("A stack")
class TestingAStackDemo {Stack<Object> stack;@Test@DisplayName("is instantiated with new Stack()")void isInstantiatedWithNew() {new Stack<>();}@Nested@DisplayName("when new")class WhenNew {@BeforeEachvoid createNewStack() {stack = new Stack<>();}@Test@DisplayName("is empty")void isEmpty() {assertTrue(stack.isEmpty());}@Test@DisplayName("throws EmptyStackException when popped")void throwsExceptionWhenPopped() {assertThrows(EmptyStackException.class, stack::pop);}@Test@DisplayName("throws EmptyStackException when peeked")void throwsExceptionWhenPeeked() {assertThrows(EmptyStackException.class, stack::peek);}@Nested@DisplayName("after pushing an element")class AfterPushing {String anElement = "an element";@BeforeEachvoid pushAnElement() {stack.push(anElement);}@Test@DisplayName("it is no longer empty")void isNotEmpty() {assertFalse(stack.isEmpty());}@Test@DisplayName("returns the element when popped and is empty")void returnElementWhenPopped() {assertEquals(anElement, stack.pop());assertTrue(stack.isEmpty());}@Test@DisplayName("returns the element when peeked but remains not empty")void returnElementWhenPeeked() {assertEquals(anElement, stack.peek());assertFalse(stack.isEmpty());}}}
}

4.2.4 参数化测试

参数化测试是JUnit5很重要的一个新特性,它使得用不同的参数多次运行测试成为了可能,也为我们的单元测试带来许多便利。

利用@ValueSource等注解,指定入参,我们将可以使用不同的参数进行多次单元测试,而不需要每新增一个参数就新增一个单元测试,省去了很多冗余代码。

@ValueSource: 为参数化测试指定入参来源,支持八大基础类以及String类型,Class类型
@NullSource: 表示为参数化测试提供一个null的入参
@EnumSource: 表示为参数化测试提供一个枚举入参
@CsvFileSource:表示读取指定CSV文件内容作为参数化测试入参
@MethodSource:表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个流)

@ParameterizedTest
@ValueSource(strings = {"one", "two", "three"})
@DisplayName("参数化测试1")
public void parameterizedTest1(String string) {System.out.println(string);Assertions.assertTrue(StringUtils.isNotBlank(string));
}@ParameterizedTest
@MethodSource("method")    //指定方法名
@DisplayName("方法来源参数")
public void testWithExplicitLocalMethodSource(String name) {System.out.println(name);Assertions.assertNotNull(name);
}static Stream<String> method() {return Stream.of("apple", "banana");
}

http://www.ppmy.cn/news/845796.html

相关文章

蓝牙耳机适合跑步戴吗,五款适合跑步蓝牙耳机推荐

音乐是坚持运动下去的不懈动力&#xff0c;在运动当中佩戴蓝牙耳机&#xff0c;能够让我们远离枯燥无味&#xff0c;运动更有律动感&#xff0c;运动更为畅快。运动当中佩戴的蓝牙耳机&#xff0c;佩戴舒适度以及牢固度是我们十分需要注意的&#xff0c;下面这几款比较热门的运…

跑步耳机哪种好,五款跑步必备佩戴的耳机推荐

有些人花时间在户外运动是为了在运动完后可以感受到大自然所给予的馈赠&#xff0c;在戴着耳机运动的同时&#xff0c;还能感受到周围大自然所带来的各种愉悦声音&#xff0c;然而找到适合运动的耳机也是相当简单&#xff0c;就像在户外运动的人来说&#xff0c;耳机连接的稳定…

618有什么值得入的家用运动装备、运动健身器材推荐合集

要说近期还有什么“节”值得期待&#xff0c;那肯定是618这个电商节了。相较于双十一&#xff0c;618的优惠力度也是不小的&#xff0c;既然优惠力度这么大&#xff0c;那肯定不能错过机会&#xff0c;如果有什么想买的性价比好物之类的&#xff0c;这个时候就可以开始选品加购…

std::thread和std::mutex

std::thread std::thread用来创建一个线程&#xff1a; #include <thread>void threadFun(int temp) {int i 0; }int main() {std::thread t1(threadFun, 100);t1.join();//t1.detach();return 0; }创建了一个名为t1的线程&#xff0c;调用join方法阻塞等待线程退出&a…

类和对象(二)

今天&#xff0c;我带来类和对象的进阶篇。 目录 类的6个默认成员函数默认成员函数的概念构造函数构造函数的概念构造函数的特性 析构函数析构函数的概念析构函数的特性 拷贝构造函数拷贝构造函数的概念拷贝构造函数的特性 赋值运算符重载运算符重载赋值运算符重载 前置和后置重…

GLFore便携式声学照相机的应用领域

声学是研究声波在弹性介质中的产生、传播、接收、影响和应用的学科。声学作为一门经典学科&#xff0c;在近代取得了巨大的进步。它不仅广泛应用于工业、农业、医疗卫生、环境保护、人民日常生活等领域&#xff0c;而且广泛应用于国防建设。声学测量作为声学的重要组成部分&…

C#、WPF个性化照相机制作(一)项目概述和初期准备

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 概述运行界面效果搭建项目文件关于Winform 和 WPF 的取舍 配置调用的程序包关于Aforge ffmpeg 和 Opencvsharp 引用 概述 这几个周来导师留了学习C#和WPF的任务&am…

Micropython TPYBoard v102 进阶之旅 DIY照相机

摄像头(CAMERA或WEBCAM)又称为电脑相机、电脑眼、电子眼等&#xff0c;是一种视频输入设备&#xff0c;被广泛的运用于视频 会议&#xff0c;安防系统 、图像采集系统、 环境监控 、工业现场过程控制 等方面。本实验用TPYBoard v102以 及PTC06 串口摄像头模块DIY一个简易的照相…