springboot基础及上传组件封装
简介
本文主要以文件上传为demo,介绍了一些 springboot web
开发的入门的技术栈。
对应刚接触 springboot
的可以参考下。
主要包括文件md5比对、生成图片缩略图、数据库迁移、文件记录持久化、请求全局异常处理等功能。
准备工作
- 在
idea
中创建项目,java8
,springboot 2
maven
所需依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.bimcc</groupId><artifactId>iot</artifactId><version>0.0.1-SNAPSHOT</version><name>iot</name><description>iot</description><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.6.13</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--数据库迁移 --><dependency><groupId>org.flywaydb</groupId><artifactId>flyway-core</artifactId><version>5.2.4</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><!--请求验证--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId><version>2.7.8</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>20.0</version></dependency><!--工具包--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.4.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><mainClass>com.bimcc.iot.IotApplication</mainClass><skip>true</skip></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build></project>
- 创建项目目录
目录意义如下:
- 修改
application.yml
配置:
---
# 开发环境的配置
server:port: 9090
spring:controller:api-prefix: /apiflyway:enabled: true #开启数据迁移table: flyway_schema_history #用于存储迁移历史记录的表名,默认为flyway_schema_historybaseline-on-migrate: true #当迁移数据库存在但没有元数据的表时,自动执行基准迁移,新建flyway_schema_history表locations: classpath:db/migration #数据库迁移脚本的位置,默认为classpath:db/migration,classpath 羡慕resources目录clean-disabled: true #用于控制是否禁用 Flyway 的 clean 操作。datasource:username: rootpassword: rooturl: jdbc:mysql://127.0.0.1:3306/java_iot?serverTimezone=GMT%2b8config:activate:on-profile: dev #开发环境servlet:multipart:enabled: true # 允许文件上传max-file-size: 20971520 # 单文件最大限制 20Mmax-request-size: 52428800 # 单次请求最大限制 50M
file:upload:path: E:\project-java\java-upload # 文件上传保存服务器绝对路径suffix: jpg,jpeg,png,bmp,xls,xlsx,pdf # 文件上传保存路径is-thumb: true # 是否开启缩略图 true falseproportion: 5 # 缩略图缩放比例path-pattern: uploads # 访问虚拟目录
log:level: INFO # INFO DEBUG ERROR
---# 当前启用的配置
spring:application:name: iot # 应用平台profiles:active: dev # 当前环境
- 创建数据表迁移文件
写入以下内容:
CREATE TABLE sys_file
(id INT AUTO_INCREMENT COMMENT 'id',file_name VARCHAR(255) NOT NULL COMMENT '文件名称',ip VARCHAR(255) COMMENT '上传ip',file_path VARCHAR(255) NOT NULL COMMENT '文件路径',thumb_path VARCHAR(255) COMMENT '缩略图文件路径',file_size INT COMMENT '字节大小',file_type VARCHAR(255) COMMENT '文件类型',file_ext CHAR(36) COMMENT '文件后缀',file_md5 VARCHAR(255) COMMENT '文件md5',created_at DATETIME COMMENT '创建时间',updated_at DATETIME COMMENT '修改时间',deleted_at DATETIME COMMENT '删除时间',PRIMARY KEY (id)
) ENGINE = InnoDB DEFAULT CHARSET = UTF8MB4;
创建上传实体类
- 在
dto目录
创建BaseEntity
及FileEntity
实体类
BaseEntity
写入以下内容:
// 省略 package import @Data
public class BaseEntity implements Serializable {@TableId(value = "id",type = IdType.AUTO)private Integer id;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") //格式化时间,空值不会格式化@TableField(value = "created_at",fill = FieldFill.INSERT)@JsonProperty("created_at") //json格式化显示字段private Date createdAt;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")@TableField(value = "updated_at",fill = FieldFill.INSERT_UPDATE)@JsonProperty("updated_at")private Date updatedAt;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")@JsonProperty("deleted_at")@TableField(value = "deleted_at")@TableLogic(value = "null",delval = "now()")private Date deletedAt;}
FileEntity
写入以下内容:
// 省略 package import
@Data
@TableName("sys_file")
public class FileEntity extends BaseEntity {@TableField(value = "file_name")private String fileName;@TableField(value = "ip")private String ip;@TableField(value = "file_path")private String filePath;@TableField(value = "thumb_path")private String thumbPath;@TableField(value = "file_size")private Long fileSize;@TableField(value = "file_type")private String fileType;@TableField(value = "file_ext")private String fileExt;@TableField(value = "file_md5")private String fileMd5;
}
- 创建
mapper
, 在mapper
目录创建FileMapper
接口类
// 省略 package import @Mapper
public interface FileMapper extends BaseMapper<FileEntity> {FileEntity queryByMd5(String md5);
}
- 创建
mapper xml
文件。在resources
目录下面创建mapper
目录,然后再创建FileMapper.xml
。并写入以下内容
<?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.bimcc.iot.mapper.FileMapper"><!-- 询的结果集字段和实体类的user属性名不一致,自定义查询结果集的映射规则 --><resultMap id="queryFile" type="com.bimcc.iot.dto.FileEntity"><id property="id" column="id"/><result property="fileName" column="file_name"/><result property="ip" column="ip"/><result property="filePath" column="file_path"/><result property="fileSize" column="file_size"/><result property="fileType" column="file_type"/><result property="fileExt" column="file_ext"/><result property="fileMd5" column="file_md5"/><result property="createdAt" column="created_at"/><result property="updatedAt" column="updated_at"/><result property="deletedAt" column="deleted_at"/></resultMap><select id="queryByMd5" resultMap="queryFile">select * from sys_file where file_md5 = #{md5} and deleted_at is null</select></mapper>
全局异常处理
- 在
exceptin
目录里面创建ServiceException
类,编写如下代码:
// 省略 package import //专用于处理业务层的异常基类
public class ServiceException extends RuntimeException{public ServiceException() {super();}public ServiceException(String message) {super(message);}public ServiceException(String message, Throwable cause) {super(message, cause);}public ServiceException(Throwable cause) {super(cause);}protected ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);}
}
- 在
controller
目录里面创建BaseController
基类,后续controller
继承他
// 省略 package import @ControllerAdvice
public class BaseController {public static final int OK = 200;/*** 全局手动抛出异常处理* 1.当出现了value内的异常之一,就会将下方的方法作为新的控制器方法进行执行* 因此该方法的返回值也同时是返回给前端的页面* 2.此外还自动将异常对象传递到此方法的参数列表中,这里使用Throwable e来接收**/@ExceptionHandler(ServiceException.class) //统一处理抛出的异常public ResJson<Void> handleException(Throwable e){ResJson<Void> result = new ResJson<>(e);result.setCode(5000); //数据库或服务器有问题return result;}}
注册配置
在 config
目录创建 GlobalControllerPathPrefixConfig
类,写入以下内容:
// 省略 package import //群集统一配置接口前缀
@Configuration
public class GlobalControllerPathPrefixConfig implements WebMvcConfigurer {@Value("${spring.controller.api-prefix}")private String pathPrefix;@Value("${file.upload.path-pattern}")private String pathPattern;@Value("${file.upload.path}")private String fileUploadPath;//全局接口注册 api前缀@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {configurer.addPathPrefix(pathPrefix, c -> c.isAnnotationPresent(RestController.class));}//静态资源图片上传,虚拟路径返回@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {//将匹配上/files/**虚拟路径的url映射到文件上传到服务器的目录,获取静态资源registry.addResourceHandler("/" +pathPattern + "/**").addResourceLocations("file:" + fileUploadPath+File.separator);WebMvcConfigurer.super.addResourceHandlers(registry);}}
创建工具类
- 创建一个全局返回类。在
utils
里面创建一个ResJson
类型
// 省略 import@Data
public class ResJson<E> implements Serializable {/*** 状态码*/private Integer code;/*** 提示信息*/private String message;/*** 返回数据*/private E data;public ResJson(Integer code) {this.code = code;}public ResJson(Integer code,String message) {this.code = code;this.message = message;}public ResJson(Throwable e) {this.message = e.getMessage();}public ResJson(Integer code,String message,E data) {this.code = code;this.data = data;this.message = message;}}
- 创建一个
md5
加密类。在utils
里面创建一个PasswordEncryptedUtils
类型
// 省略 package import
public class PasswordEncryptedUtils {public static String getPasswordByMD5(String pwd,String salt){for (int i = 0; i < 3 ; i++) {//md5加密算法的调用pwd = DigestUtils.md5DigestAsHex((salt + pwd + salt).getBytes()).toUpperCase();}//返回经过加密的结果return pwd;}
}
创建上传服务
- 在
server
目录里面创建FileServer
接口类
// 省略 package import public interface FileServer {FileEntity upload(MultipartFile file);String createThumb(String fileDir,String filePath,String fileName,String suffix);}
- 在
server目录
里面创建impl目
录并在里面创建FileServerImpl
类实现上面的接口功能
// 省略 package import @Service
public class FileServerImpl implements FileServer {public static final int maxWidth = 100;//拦截的url,虚拟路径public String pathPattern = "uploads";//文件磁盘路径@Value("${file.upload.path}")private String fileUploadPath;@Value(value = "${file.upload.suffix:jpg,jpeg,png,bmp,xls,xlsx,pdf}")private String fileUploadSuffix;@Value(value = "${file.upload.is-thumb}")private Boolean isThumb;@Value(value = "${file.upload.proportion}")private Integer proportion;@AutowiredHttpServletRequest request;@AutowiredFileMapper fileMapper;//文件上传@Overridepublic FileEntity upload(MultipartFile file) {FileEntity fileRes = new FileEntity();if (file.isEmpty()) {// log.error("the file to be uploaded is empty");return fileRes;}List<String> suffixList = Lists.newArrayList(fileUploadSuffix.split(","));try {//校验文件后缀String originalFilename = file.getOriginalFilename();//获取文件类型String type = FileUtil.extName(originalFilename);//文件后缀String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);if (!suffixList.contains(suffix)) {//log.error("unsupported file format");return fileRes;}//获取文件md5String md5 = SecureUtil.md5(file.getInputStream());// 从数据库查询是否存在相同的记录FileEntity dbFiles = fileMapper.queryByMd5(md5);if (dbFiles != null) { // 文件已存在return dbFiles;}String year = new SimpleDateFormat("yyyy").format(new Date());String month = new SimpleDateFormat("MM").format(new Date());String day = new SimpleDateFormat("dd").format(new Date());String fileDir = fileUploadPath;String filePath = File.separator + year + File.separator + month + File.separator + day + File.separator;//首次需生成目录File folder = new File(fileDir + filePath);if (!folder.exists()) {folder.mkdirs();}AtomicInteger counter = new AtomicInteger(0);String uniqueString = String.valueOf(Instant.now().toEpochMilli());String fileName = uniqueString + "." + suffix;String absolutePath = fileDir + filePath + fileName;file.transferTo(new File(absolutePath));//网页路径String dataFilePath = pathPattern + "/" + year + "/" + "/" + month + "/" + day + "/" + fileName;fileRes.setFilePath(dataFilePath);fileRes.setFileName(fileName);fileRes.setIp(request.getRemoteAddr());fileRes.setFileSize(file.getSize() / 1024);fileRes.setFileType(type);fileRes.setFileExt(suffix);fileRes.setFileMd5(md5);//判断是否生成缩率图if (isThumb) {createThumb(fileDir, filePath, uniqueString, suffix);String dataFileThumbPath = pathPattern + "/" + year + "/" + "/" + month + "/" + day + "/" + uniqueString + "_thumb." + suffix;fileRes.setThumbPath(dataFileThumbPath);}fileMapper.insert(fileRes);} catch (IOException e) {e.printStackTrace();throw new ServiceException(e.getMessage());}return fileRes;}//生成缩率图@Overridepublic String createThumb(String fileDir, String filePath, String fileName, String suffix) {String localPath = fileDir + filePath + fileName + "." + suffix;String thumbPath = fileDir + filePath + fileName + "_thumb." + suffix;//判断缩略图是否存在Path path = Paths.get(thumbPath);if (Files.exists(path)) {return filePath + fileName + "_thumb." + suffix;}File originalFile = new File(localPath);try {BufferedImage originalImage = ImageIO.read(originalFile);int imageWidth = originalImage.getWidth();int imageHeight = originalImage.getHeight();double thumbWidth = 0;double thumbHeight = 0;if (imageWidth > maxWidth || imageHeight > maxWidth) {thumbWidth = (double) imageWidth / (double) proportion;thumbHeight = (double) imageHeight / (double) proportion;}if (thumbHeight > 0) {// 创建缩略图BufferedImage thumbnail = new BufferedImage((int) thumbWidth, (int) thumbHeight, BufferedImage.TYPE_INT_RGB);Graphics graphics = thumbnail.createGraphics();graphics.drawImage(originalImage.getScaledInstance((int) thumbWidth, (int) thumbHeight, Image.SCALE_SMOOTH), 0, 0, null);graphics.dispose();// 输出到文件ImageIO.write(thumbnail, suffix, new File(thumbPath));return filePath + fileName + "_thumb." + suffix;}} catch (IOException e) {e.printStackTrace();throw new ServiceException(e.getMessage());}return "";}}
上传
- 创建一个上传控制器
UploadController
,写入以下内容:
// 省略 package import @RestController
public class UploadController extends BaseController {@AutowiredFileServer fileServer;@PostMapping("/upload")public ResJson<FileEntity> upload(@RequestParam MultipartFile file){FileEntity fileRes= fileServer.upload(file);return new ResJson<>(OK,"上传成功!",fileRes);}}
- 测试
通过 postman
接口测试,调用上面的上传接口
查看application.yml
里面配置的上传目录,是否有文件
通过网络路径访问图片
总结
本文适合 springboot
入门的初学者。
以文件上传为demo,衍生出了一些常用功能,包含:文件上传,入库,请求。异常处理,api前缀,数据迁移,生成缩略图,等功能。
希望能对初学者有一个参考的作用。
– 欢迎点赞、关注、转发、收藏【我码玄黄】,gonghao同名
相关文章:

springboot基础及上传组件封装
简介 本文主要以文件上传为demo,介绍了一些 springboot web 开发的入门的技术栈。 对应刚接触 springboot 的可以参考下。 主要包括文件md5比对、生成图片缩略图、数据库迁移、文件记录持久化、请求全局异常处理等功能。 准备工作 在 idea 中创建项目ÿ…...
WHAT - package.json 解释
目录 一、前言二、介绍2.1 package.json 文件示例2.2 关键字段2.3 常用命令2.4 自定义脚本 三、element-plus 完整示例3.1 main 和 module1. main 字段2. module 字段3. 综合示例 3.2 types1. 示例2. TypeScript 类型定义文件的作用3. 类型定义文件示例4. 发布带有类型定义的包…...

Python知识点14---被规定的资源
提前说一点:如果你是专注于Python开发,那么本系列知识点只是带你入个门再详细的开发点就要去看其他资料了,而如果你和作者一样只是操作其他技术的Python API那就足够了。 在Python中被规定的东西不止有常识中的那些关键字、构造器等编程语言…...

文献阅读:GCNG:用于从空间转录组数据推断基因相互作用的图卷积网络
文献介绍 「文献题目」 GCNG: graph convolutional networks for inferring gene interaction from spatial transcriptomics data 「研究团队」 Ziv Bar-Joseph(美国卡内基梅隆大学) 「发表时间」 2020-12-10 「发表期刊」 Genome Biology 「影响因子…...

Mybatis第一讲——你会Mybatis吗?
文章目录 什么是MybatisMybatis的作用是什么 Mybatis 怎么使用注解的方式注解的多种使用Options注解ResultType注解 XML的方式update标签 #{} 和 ${}符号的区别#{}占位${}占位 ${}占位的危险性(SQL注入)数据库连接池 什么是Mybatis 首先什么是Mybatis呢?Mybatis是一…...

【HarmonyOS】List组件多层对象嵌套ForEach渲染更新的处理
【HarmonyOS】List组件多层对象嵌套ForEach渲染更新的处理 问题背景: 在鸿蒙中UI更新渲染的机制,与传统的Android IOS应用开发相比。开发会简单许多,开发效率提升显著。 一般传统应用开发的流程处理分为三步:1.画UI,…...

PostgreSQL基础(六):PostgreSQL基本操作(二)
文章目录 PostgreSQL基本操作(二) 一、字符串类型 二、日期类型 三、...

【前端部署——vercel】部署next.js使用了prisma的项目
部署流程参考 https://blog.csdn.net/qq_51116518/article/details/137042682 问题 PrismaClientInitializationError: Prisma has detected that this project was built on Vercel, which caches dependencies. This leads to an outdated Prisma Client because Prisma’s …...

Vue插槽与作用域插槽
title: Vue插槽与作用域插槽 date: 2024/6/1 下午9:07:52 updated: 2024/6/1 下午9:07:52 categories: 前端开发 tags:VueSlotScopeSlot组件通信Vue2/3插槽作用域API动态插槽插槽优化 第1章:插槽的概念与原理 插槽的定义 在Vue.js中,插槽(…...

类和对象(一)(C++)
类和对象: 类的引入: C语言结构体中只能定义变量,在C中,结构体内不仅可以定义变量,也可以定义函数。比如: 之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量&#…...

【免费Web系列】JavaWeb实战项目案例六
这是Web第一天的课程大家可以传送过去学习 http://t.csdnimg.cn/K547r 员工信息-删除&修改 前面我们已经实现了员工信息的条件分页查询以及新增操作。 关于员工管理的功能,还有两个需要实现: 删除员工 修改员工 除了员工管理的功能之外&#x…...
git分布式版本控制系统(四)
目前世界上最先进的分布式版本控制系统 官方网址:https://git-scm.com 学习目标: 1 了解 git 前世今生 2 掌握 git 基础概念、基础操作 3 各种 git 问题处理 4 互联网常用 gitflow(工作流程规范) 5 git 代码提交规范 6 git 分支管理及命名规范 常见问…...

【React篇】简述React-Router 的实现原理及工作方式
React Router 路由的基础实现原理分为两种,如果是切换 Hash 的方式,那么依靠浏览器 Hash 变化即可;如果是切换网址中的 Path,就要用到 HTML5 History API 中的 pushState、replaceState 等。在使用这个方式时,还需要在…...

Django里多app
在 Django 里的某一个项目,里面得包含很多 App (功能),那么如何在该项目里管理这么多App呢? 先说明下背景:未先创建 apps 文件夹来存各个app文件夹,直接在项目文件目录里创建各个app。为了便于管理,得将各…...

Prime1 - 信息收集和分析能力的试炼
主机发现 nmap扫描与分析 端口22、80 详细扫描;linux、ubuntu、 udp扫描 端口都是关闭的 脚本扫描 web渗透 打开只有一张图片;源码有图片和一个alt:hnp security不知道有啥用,先记录下来吧 继续web渗透思路走吧,目录…...
3.location的写法
location的写法 一、location的写法1、 精确匹配2、~ 以正则表达式匹配请求,区分大小写3、~* 以正则匹配请求,不区分大小写4、^~ 不以正则的方式匹配请求 二、stub_status模块显示工作状态三、url地址重写 rewrite模块1、语法2、针对项目结构有变化3、网…...
AndroidStudio设置允许APP获取定位权限
1. 在AndroidManifest.xml中声明权限 常用的定位权限有以下两种: <uses-permission android:name"android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name"android.permission.ACCESS_COARSE_LOCATION"/>2. …...

Spring Boot 统一数据返回格式
在 Spring Boot 项目中,统一的数据格式返回是一种良好的实践,它提高了代码的可维护性和一致性,并改善了客户端与服务端之间的通信。本文将介绍如何在 Spring Boot 中实现统一的数据格式返回。 1 为什么需要统一数据返回格式 ⽅便前端程序员更…...

Android 项目Gradle文件讲解(Groovy和Kotlin)
Android 项目Gradle文件讲解(Groovy和Kotlin) 前言正文一、Gradle的作用二、Gradle的种类① 工程build.gradle② 项目build.gradle③ settings.gradle④ gradle.properties⑤ gradle-wrapper.properties⑥ local.properties 三、Groovy和Kotlin的语言对比…...

python-最接近target的值
【问题描述】:给定一个数组,在数组中找到两个数,使它们的和最接近目标值的值但不超过目标值,然后返回它们的和。 【问题示例】:输入target15,array[1,3,5,11,7],输出14,31114。 完整代码如下: …...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...