第03讲:MinIO分布式文件服务器
一、什么是MinIO
Minio 是个基于 Golang 编写的开源对象存储套件,虽然轻量,却拥有着不错的性能。
- 官网地址:MinIO | High Performance, Kubernetes Native Object Storageopen in new window
- 官网文档地址:MinIO | The MinIO Quickstart Guideopen in new window
- 官网文档( 中文 )地址:官网中文网址open in new window 中文文档对应的是上个版本,新版本中有些内容已发生了变化,所以最好是看英文文档。
- JAVA SDK API:minio java sdk api 文档
何为对象存储?
对象存储服务( Object Storage Service,OSS )是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。
对于中小型企业,如果不选择存储上云,那么 Minio 是个不错的选择,麻雀虽小,五脏俱全
二、CentOS7下安装MinIO
2.1、下载MinIO
在usr/local下创建minio文件夹,并在minio文件里面创建bin和data目录,把下载好的minio文件拷贝到bin目录里面
创建目录,命令:
mkdir /usr/local/minio && cd /usr/local/minio && mkdir bin data
效果:

下载MinIO,命令:
wget https://dl.min.io/server/minio/release/linux-amd64/minio bin
mv minio bin/
效果:

2.2、运行MinIO
赋予可执行的权限,命令:
chmod +x bin/minio
运行MinIO,命令:
./bin/minio server ./data
2.3、将 minio 添加成 Linux 的服务
cat > /etc/systemd/system/minio.service << EOF
[Unit]
Description=Minio
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/minio/bin/minio[Service]
WorkingDirectory=/usr/local/minio/
PermissionsStartOnly=true
ExecStart=/usr/local/minio/bin/minio server /usr/local/minio/data
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true[Install]
WantedBy=multi-user.target
EOF
这样就可以使用 systemctl 启停 minio,命令:
systemctl start minio # 启动
systemctl stop minio # 停止
运行效果:

2.4、测试
MinIO Server 成功启动后访问 http://10.211.55.9:9000,你会看到类似如下界面:
Ps:要关闭防火墙或开放9000端口
systemctl stop firewalld

输入用户名/密码 minioadmin/minioadmin 可以进入 web 管理系统:

刚打开的时候,是没有bucket桶,可以手动或者通过java代码来创建一个桶。
创建的桶默认的权限时private私有的,外部不能访问,你可以修改桶的属性,点击manage,找到Access Policy,修改权限为public即可。



三、SpringBoot整合MinIO
第1步:pom.xml中添加依赖
<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.8.1</version>
</dependency>
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.3.9</version>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.70</version>
</dependency>
第2步:application.yml
server:port: 8070
spring:servlet:multipart:max-file-size: 200MB #设置单个文件的大小 因为springboot内置tomact的的文件传输默认为10MBmax-request-size: 500MB #设置单次请求的文件总大小enabled: true #千万注意要设置该参数,否则不生效
# minio 文件存储配置信息
minio:endpoint: http://10.211.55.9:9000accesskey: minioadminsecretKey: minioadmin
第3步:minio配置类和配置属性
配置属性MinioProp.java
package demo.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioProp {private String endpoint;private String accesskey;private String secretKey;
}
配置类MinioConfig.java
package demo.config;import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@EnableConfigurationProperties(MinioProp.class)
public class MinioConfig {@Autowiredprivate MinioProp minioProp;@Beanpublic MinioClient minioClient() throws Exception {return MinioClient.builder().endpoint(minioProp.getEndpoint()).credentials(minioProp.getAccesskey(), minioProp.getSecretKey()).build();}
}
第4步:文件上传工具类
package demo.utils;import com.alibaba.fastjson.JSONObject;
import demo.config.MinioProp;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import java.io.InputStream;@Slf4j
@Component
public class MinioUtils {@Autowiredprivate MinioClient client;@Autowiredprivate MinioProp minioProp;/*** 创建bucket*/public void createBucket(String bucketName) {BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(bucketName).build();MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();try {if (client.bucketExists(bucketExistsArgs))return;client.makeBucket(makeBucketArgs);} catch (Exception e) {log.error("创建桶失败:{}", e.getMessage());throw new RuntimeException(e);}}/*** @param file 文件* @param bucketName 存储桶* @return*/public JSONObject uploadFile(MultipartFile file, String bucketName) throws Exception {JSONObject res = new JSONObject();res.put("code", 0);// 判断上传文件是否为空if (null == file || 0 == file.getSize()) {res.put("msg", "上传文件不能为空");return res;}// 判断存储桶是否存在createBucket(bucketName);// 文件名String originalFilename = file.getOriginalFilename();// 新的文件名 = 存储桶名称_时间戳.后缀名String fileName = bucketName + "_" + System.currentTimeMillis() + originalFilename.substring(originalFilename.lastIndexOf("."));// 开始上传InputStream inputStream = file.getInputStream();PutObjectArgs args = PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(inputStream,inputStream.available(),-1).build();client.putObject(args);res.put("code", 1);res.put("msg", minioProp.getEndpoint() + "/" + bucketName + "/" + fileName);return res;}
}
第5步:测试Controller
package demo.controller;import com.alibaba.fastjson.JSONObject;
import demo.utils.MinioUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;@RestController
public class TestController {@Autowiredprivate MinioUtils minioUtils;@PostMapping("/uploadimg")@ResponseBodypublic String uploadimg(@RequestParam(name = "file", required = false) MultipartFile file,HttpServletRequest request) {JSONObject res = null;try {res = minioUtils.uploadFile(file, "qin");} catch (Exception e) {e.printStackTrace();res.put("code", 0);res.put("msg", "上传失败");}return res.toJSONString();}
}
第6步:前端页面upload.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="assets/vue.min-v2.5.16.js"></script><script src="assets/axios.min.js"></script>
</head>
<body>
<div id="app"><input type="file" @change="Upload" />
</div>
<script>new Vue({el: '#app',data: {},methods: {Upload(event){const flie = event.target.files[0];// 在这里进行一系列的校验const formData = new FormData();formData.append("file",flie);axios.post('http://localhost:8070/uploadimg',formData,{'Content-type' : 'multipart/form-data'}).then(res=>{console.log(res.data);},err=>{console.log(err)})}}});
</script>
</body>
</html>
运行效果:
浏览器访问upload.html,选择文件上传

访问console响应的url,发现文件已经成功上传
<body><imgsrc="http://10.211.55.9:9000/qin/qin_1680766685084.jpg"style="width: 500px;">
</body>

四、附录
4.1、JavaSDK
@SpringBootTest
class DemoApplicationTests {@Testpublic void demo() throws Exception {// 使用 MinIO 服务的 URL 和端口,Access key 和 Secret key 创建一个 MinioClient 对象。MinioClient minioClient = MinioClient.builder().endpoint("http://127.0.0.1:9000").credentials("minioadmin", "minioadmin").build();// 检查存储桶是否已经存在boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket("kongming").build());if (isExist) {System.out.println("Bucket already exists.");} else {// 创建一个名为 asiatrip 的存储桶,用于存储文件。minioClient.makeBucket(MakeBucketArgs.builder().bucket("kongming").build());}// 使用 putObject 上传一个文件到存储桶中。File file = new File("e:/BluceLee/1.jpg");InputStream inputStream = new FileInputStream(file);PutObjectArgs args = PutObjectArgs.builder().bucket("kongming").object("xiaolong.jpg").contentType("image/jpg").stream(inputStream, inputStream.available(), -1).build();minioClient.putObject(args);System.out.println(" successfully uploaded as xiaolong.png to `kongming` bucket.");}
}
4.2、完整工具类
package com.woniu.util;import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.*;
// import net.minidev.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.concurrent.TimeUnit;public class MinioUtils1 {private static final Logger log = LoggerFactory.getLogger(MinioUtils1.class);private final String endpoint;private final String accessKey;private final String secretKey;private MinioClient minioClient;public MinioUtils1(String endpoint, String accessKey, String secretKey) {this.endpoint = endpoint;this.accessKey = accessKey;this.secretKey = secretKey;this.minioClient = MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();}/*@PostConstructprivate MinioClient client() {}
*/public boolean doesBucketExists(String bucketName) {BucketExistsArgs args = BucketExistsArgs.builder().bucket(bucketName).build();try {return minioClient.bucketExists(args);} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {throw new RuntimeException(e);}}/*** 创建 bucket** @param bucketName 桶名*/public void createBucket(String bucketName) {BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(bucketName).build();MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();try {if (minioClient.bucketExists(bucketExistsArgs))return;minioClient.makeBucket(makeBucketArgs);} catch (Exception e) {log.error("创建桶失败:{}", e.getMessage());throw new RuntimeException(e);}}/*** 判断文件是否存在** @param bucketName 存储桶* @param objectName 对象* @return true:存在*/public boolean doesObjectExist(String bucketName, String objectName) {StatObjectArgs args = StatObjectArgs.builder().bucket(bucketName).object(objectName).build();try {minioClient.statObject(args);} catch (Exception e) {return false;}return true;}/*** 判断文件夹是否存在** @param bucketName 存储桶* @param objectName 文件夹名称(去掉/)* @return true:存在*/public boolean doesFolderExist(String bucketName, String objectName) {ListObjectsArgs args = ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(false).build();boolean exist = false;try {Iterable<Result<Item>> results = minioClient.listObjects(args);for (Result<Item> result : results) {Item item = result.get();if (!item.isDir())continue;if (objectName.equals(item.objectName())) {exist = true;}}} catch (Exception e) {exist = false;}return exist;}/*** 通过 MultipartFile ,上传文件** @param bucketName 存储桶* @param file 文件* @param objectName 对象名*/public ObjectWriteResponse putObject(String bucketName, MultipartFile file, String objectName, String contentType) {try {InputStream inputStream = file.getInputStream();PutObjectArgs args = PutObjectArgs.builder().bucket(bucketName).object(objectName).contentType(contentType).stream(inputStream, inputStream.available(), -1).build();return minioClient.putObject(args);} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {throw new RuntimeException(e);}}/*** 上传本地文件** @param bucketName 存储桶* @param objectName 对象名称* @param fileName 本地文件路径*/public ObjectWriteResponse putObject(String bucketName, String objectName, String fileName) {try {UploadObjectArgs args = UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build();return minioClient.uploadObject(args);} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {throw new RuntimeException(e);}}/*** 通过流上传文件** @param bucketName 存储桶* @param objectName 文件对象* @param inputStream 文件流*/public ObjectWriteResponse putObjectByStream(String bucketName, String objectName, InputStream inputStream) {try {PutObjectArgs args = PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(inputStream, inputStream.available(), -1).build();return minioClient.putObject(args);} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {throw new RuntimeException(e);}}/*** 创建文件夹或目录** @param bucketName 存储桶* @param objectName 目录路径*/public ObjectWriteResponse putDirObject(String bucketName, String objectName) {PutObjectArgs args = PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(new ByteArrayInputStream(new byte[]{}), 0, -1).build();try {return minioClient.putObject(args);} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {throw new RuntimeException(e);}}/*** 获取全部 bucket*/public List<Bucket> getAllBuckets() throws Exception {return minioClient.listBuckets();}/*** 根据 bucketName 删除信息** @param bucketName 桶名*/public void removeBucket(String bucketName) {try {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {e.printStackTrace();}}/*** 获取⽂件外链** @param bucketName bucket名称* @param objectName ⽂件名称* @param expires 过期时间 <=7*/public String getObjectUrl(String bucketName, String objectName, Integer expires) {GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(objectName).expiry(expires) // 单位:秒.build();try {return minioClient.getPresignedObjectUrl(args);} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidResponseException | InvalidKeyException | NoSuchAlgorithmException | IOException | XmlParserException | ServerException e) {throw new RuntimeException(e);}}/*** 获取⽂件外链** @param bucketName bucket名称* @param objectName ⽂件名称* @param duration 过期时间* @param unit 过期时间的单位*/public String getObjectUrl(String bucketName, String objectName, int duration, TimeUnit unit) {GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(objectName).expiry(duration, unit).build();try {return minioClient.getPresignedObjectUrl(args);} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidResponseException | InvalidKeyException | NoSuchAlgorithmException | IOException | XmlParserException | ServerException e) {throw new RuntimeException(e);}}/*** 获取文件** @param bucketName bucket名称* @param objectName ⽂件名称* @return ⼆进制流*/public InputStream getObject(String bucketName, String objectName) throws Exception {GetObjectArgs args = GetObjectArgs.builder().bucket(bucketName).object(objectName).build();return minioClient.getObject(args);}/*** 上传文件** @param bucketName bucket名称* @param objectName ⽂件名称* @param stream ⽂件流* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject*/public void putObject(String bucketName, String objectName, InputStream stream) {putObjectByStream(bucketName, objectName, stream);}/*** 文件流上传文件** @param bucketName bucket名称* @param objectName ⽂件名称* @param stream ⽂件流* @param size ⼤⼩* @param contextType 类型*/public void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) {putObjectByStream(bucketName, objectName, stream);}/*** 获取文件信息** @param bucketName bucket名称* @param objectName ⽂件名称* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject*/public StatObjectResponse getObjectInfo(String bucketName, String objectName) {StatObjectArgs args = StatObjectArgs.builder().bucket(bucketName).object(objectName).build();try {return minioClient.statObject(args);} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {throw new RuntimeException(e);}}/*** 删除文件** @param bucketName bucket名称* @param objectName ⽂件名称* @throws Exception https://docs.minio.io/cn/java-client-apireference.html#removeObject*/public void removeObject(String bucketName, String objectName) {RemoveObjectArgs args = RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build();try {minioClient.removeObject(args);} catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {e.printStackTrace();}}
}
相关文章:
第03讲:MinIO分布式文件服务器
一、什么是MinIO Minio 是个基于 Golang 编写的开源对象存储套件,虽然轻量,却拥有着不错的性能。 官网地址:MinIO | High Performance, Kubernetes Native Object Storageopen in new window官网文档地址:MinIO | The MinIO Qui…...
WireShark
wireshark 常用命令: frame.len 帧数据总长度:包含MAC头IP头UDP头UDP数据 eg: 1、 重传命令的长度是62, Frame.len 62 2、 长度大于200的包,frame.len > 200 3、 长度小于80的包,frame.len < 80 Ip.src 数据包的发送源IP地…...
Thinkphp 6.0多语言
本节课我们来学习一下如何配置的多语言功能,并实现调用方法。 一.多语言 1. 如果要开启多语言切换功能,中间件定义文件 middleware.php 开启; // 多语言加载 \think\middleware\LoadLangPack::class, 2. 配置文件在 config/lang…...
生成式AI已形成全球性“AI再造业务”趋势
3月28日至31日,博鳌亚洲论坛2023年年会在海南举行。实体经济与数字经济如何融合发展,产业数字化如何加速向深层次拓展,生成式AI会给产业经济带来哪些变革?这些话题成为今年论坛热点。 百度集团执行副总裁、百度智能云事业群总裁沈…...
kubesphere 安装 skywalking
kubesphere 安装 skywalking 前言 在测试ELK过程中,框架内部使用skywalking来插入的traceId,没有服务端导致Ignored_Trace,先安装下试试skywalking使用效果,后面考了替换为Tlog 先来安装skywalking… 1. 导入helm原 地址&#x…...
乐鑫 × 全国大学生物联网设计竞赛|探究基于 ESP32-S3 的农业革新应用
2023 年全国大学生物联网设计竞赛(下简称“竞赛”)现已官宣启幕!乐鑫科技 (688018.SH) 作为竞赛金牌合作伙伴,将为同学们带来基于 AI SoC ESP32-S3 的独立竞赛任务,并全程提供软硬件开发资源、技术培训…...
【技术分享】华为防火墙多出口接入到Internet
组网需求 如图1所示,FW作为安全网关部署在网络出口,企业分别从ISP1和ISP2租用一条链路。 企业希望访问Server 1的报文从ISP1链路转发,访问Server 2的报文从ISP2链路转发。 当其中一条链路故障时,后续流量可以通过另一条链路转发…...
Winnolin绘制药时曲线图C-T
文章目录前言一、各受试者C-T图1.导入数据2.设置-运行2.查看结果,修改参数二、各制剂C-T图1.导入数据2.设置-运行2.查看结果,修改参数三、平均C-T图1.计算统计量2.设置统计量计算参数(Set Up)3.绘图XY Plot4.查看结果,…...
Kafka系列——详解如何使用和配置生产者实现可靠的消息发送
在可靠的系统里使用生产者 即使我们尽可能把 broker 配置得很可靠,但如果没有对生产者进行可靠性方面的配置,整个系统仍然有可能出现突发性的数据丢失。 比如下面的两个例子: (一)为 broker 配置了 3 个副本࿰…...
wordpres漏洞扫描器——wpscan
WordPress 使用PHP语言开发的博客平台 WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。也可以把 WordPress当作一个内容管理系统(CMS)来使用。 WordPress是一款个人博客系统,…...
代码随想录_二叉树_leetcode112、113
leetcode112 路径总和 112. 路径总和 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返…...
mongo-db相关方法
一、参数 名称描述db.adminCommand()针对admin数据库运行命令。db.aggregate()运行不需要基础集合的管理/诊断管道。db.cloneDatabase(hostname)不推荐使用。当针对MongoDB 4.0或更早版本运行时,将数据库从远程主机复制到当前主机。针对MongoDB 4.2或更高版本运行时…...
《Vue3实战》 第二章 创建项目和目录结构
1、创建项目 1.1、命令格式:vue create 项目名称 vue create vue3_example0011.2、运行项目 npm run serve1.2.1、增加run命令 启动时想修改命令,例如: npm run dev1、找到项目根路径下的package.json文件; 2、找到【scripts…...
13433元!上海一季度平均薪酬出炉!你拖后腿了吗?(附招聘岗位)
2023年第一季度智联招聘, 发布《中国企业招聘薪酬报告》, 显示上海平均招聘薪酬为 13433元/月!!! 13433元/月!!! 13433元/月!!! ☟ ☟ ☟ 同…...
leetcode剑指 Offer 16. 数值的整数次方
题目描述解题思路执行结果leetcode .题目描述 实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。 示例 1: 输入:x 2.00000, n 10 输出:1…...
漏洞挖掘相关-信息收集
一、常见端口以及漏洞 1.FTP:文件传输协议 TCP端口20、21,20用于传输数据,21用于传输控制信息 (1) ftp基础爆破: owasp的Bruter,hydra以及msf中的ftp爆破模块。 (2) ftp匿名访问:用户名: anonymous密码:为空或者任意邮箱 (3) vsftpd后门: …...
海外分支如何加速访问国内总部办公系统?海域网发布 Sea-WAN解决方案
近年来,一大批优秀的中国企业走向世界,品牌越来越响亮,海外影响力越来越大,比如名创优品,国货之光“花西子”,安科创新等,很多企业在海外设立分支机构为当地客户服务,与此同时&#…...
js设计模式——责任链模式
一、概述 责任链是一种行为设计模式,它允许将请求沿着处理链传递,直到有一个处理器可以处理该请求。在这种模式中,每个处理器都有机会处理请求,如果没有一个处理器能够处理请求,那么请求最终将被忽略。这种模式可以帮…...
接口组成更新
接口组成更新概述: 接口的组成: 常量 public static final 抽象方法 public abstract 默认方法java8 静态方法java8 私有方法java9 接口中默认方法 接口中默认方法的定义格式: 格式:public default 返回值类型 方法名&#x…...
int(1) 和 int(10)区别
有个表的要加个user_id字段,user_id字段可能很大, alter table xxx ADD user_id int(1)。 int(1)怕是不够用吧,接下来是一通解释。 我们知道在mysql中 int占4个字节,那么对于无符号的int,最大值是2^32-1 4294967295&a…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
