Spring Cloud + Vue前后端分离-第10章 基于阿里云OSS的文件上传
源代码在GitHub - 629y/course: Spring Cloud + Vue前后端分离-在线课程
Spring Cloud + Vue前后端分离-第10章 基于阿里云OSS的文件上传
前面介绍的文件上传是基于本地文件服务器的文件上传,但是自己搭文件服务器会有很多运维的问题,比如磁盘满了要扩容,高峰期要增加带宽,低谷期要减少带宽,为了安全,我们还要对文件做备份等等。
所以一般会选择云平台来存储文件,云平台有很多,比如阿里云、腾讯云、百度云等,云平台做的最好的是亚马逊,我们这里选择国内最大的阿里云。
10-1 阿里云OSS简介
面向海量数据规模的分布式存储服务
从浏览器通过ECS( 服务器)访问OSS,算内网访问,不算流量费,但是要考虑ECS的带宽问题。从浏览器直接访问OSS资源,算外网访问OSS,需付流量费,但是可以不用考虑带宽。
10-2 基于OSS接口的文件上传
阿里云OSS控台的使用
bucket:存储空间,名称必须是全阿里云唯一
这个文件地址可以直接打开观看
基于OSS接口实现文件上传
1.大文件断点续传与极速秒传:基于OSS接口实现文件上传,增加文件追加上传oss-append 和简单上传oss-simple
pom.xml
OssController.java
package com.course.file.controller.admin;import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.AppendObjectRequest;
import com.aliyun.oss.model.AppendObjectResult;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.course.server.dto.FileDto;
import com.course.server.dto.ResponseDto;
import com.course.server.enums.FileUseEnum;
import com.course.server.service.FileService;
import com.course.server.util.Base64ToMultipartFile;
import com.course.server.util.UuidUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import java.io.ByteArrayInputStream;@RestController
@RequestMapping("/admin")
public class OssController {private static final Logger LOG = LoggerFactory.getLogger(OssController.class);@Value("${oss.accessKeyId}")private String accessKeyId;@Value("${oss.accessKeySecret}")private String accessKeySecret;@Value("${oss.endpoint}")private String endpoint;@Value("${oss.bucket}")private String bucket;@Value("${oss.domain}")private String ossDomain;public static final String BUSINESS_NAME = "文件上传";@Resourceprivate FileService fileService;@PostMapping("/oss-append")public ResponseDto fileUpload(@RequestBody FileDto fileDto) throws Exception {LOG.info("上传文件开始");String use = fileDto.getUse();String key = fileDto.getKey();String suffix = fileDto.getSuffix();Integer shardIndex = fileDto.getShardIndex();Integer shardSize = fileDto.getShardSize();String shardBase64 = fileDto.getShard();MultipartFile shard = Base64ToMultipartFile.base64ToMultipart(shardBase64);// 保存文件到本地FileUseEnum useEnum = FileUseEnum.getByCode(use);// //如果文件夹不存在则创建String dir = useEnum.name().toLowerCase();
// File fullDir = new File(FILE_PATH + dir);
// if (!fullDir.exists()) {
// fullDir.mkdir();
// }// String path = dir + File.separator + key + "." + suffix + "." + fileDto.getShardIndex();String path = new StringBuffer(dir).append("/").append(key).append(".").append(suffix).toString(); // course\6sfSqfOwzmik4A4icMYuUe.mp4
// String localPath = new StringBuffer(path)
// .append(".")
// .append(fileDto.getShardIndex())
// .toString(); // course\6sfSqfOwzmik4A4icMYuUe.mp4.1
// String fullPath = FILE_PATH + localPath;
// File dest = new File(fullPath);
// shard.transferTo(dest);
// LOG.info(dest.getAbsolutePath());// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);ObjectMetadata meta = new ObjectMetadata();
// 指定上传的内容类型。meta.setContentType("text/plain");// 通过AppendObjectRequest设置多个参数。AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucket, path, new ByteArrayInputStream(shard.getBytes()), meta);// 通过AppendObjectRequest设置单个参数。// 设置存储空间名称。//appendObjectRequest.setBucketName("<yourBucketName>");// 设置文件名称。//appendObjectRequest.setKey("<yourObjectName>");// 设置待追加的内容。有两种可选类型:InputStream类型和File类型。这里为InputStream类型。//appendObjectRequest.setInputStream(new ByteArrayInputStream(content1.getBytes()));// 设置待追加的内容。有两种可选类型:InputStream类型和File类型。这里为File类型。//appendObjectRequest.setFile(new File("<yourLocalFile>"));// 指定文件的元信息,第一次追加时有效。//appendObjectRequest.setMetadata(meta);// 第一次追加。// 设置文件的追加位置。
// appendObjectRequest.setPosition(0L);appendObjectRequest.setPosition((long) ((shardIndex - 1) * shardSize));AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);// 文件的64位CRC值。此值根据ECMA-182标准计算得出。System.out.println(appendObjectResult.getObjectCRC());System.out.println(JSONObject.toJSONString(appendObjectResult));// // 第二次追加。
// // nextPosition指明下一次请求中应当提供的Position,即文件当前的长度。
// appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
// appendObjectRequest.setInputStream(new ByteArrayInputStream(content2.getBytes()));
// appendObjectResult = ossClient.appendObject(appendObjectRequest);
//
// // 第三次追加。
// appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
// appendObjectRequest.setInputStream(new ByteArrayInputStream(content3.getBytes()));
// appendObjectResult = ossClient.appendObject(appendObjectRequest);// 关闭OSSClient。ossClient.shutdown();LOG.info("保存文件记录开始");fileDto.setPath(path);fileService.save(fileDto);ResponseDto responseDto = new ResponseDto();fileDto.setPath(ossDomain + path);responseDto.setContent(fileDto);// if (fileDto.getShardIndex().equals(fileDto.getShardTotal())) {
// this.merge(fileDto);
// }return responseDto;}@PostMapping("/oss-simple")public ResponseDto fileUpload(@RequestParam MultipartFile file, String use) throws Exception {LOG.info("上传文件开始");FileUseEnum useEnum = FileUseEnum.getByCode(use);String key = UuidUtil.getShortUuid();String fileName = file.getOriginalFilename();String suffix = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();String dir = useEnum.name().toLowerCase();String path = dir + "/" + key + "." + suffix;// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);// 创建PutObjectRequest对象。
// String content = "Hello OSS";// <yourObjectName>表示上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, path, new ByteArrayInputStream(file.getBytes()));// 如果需要上传时设置存储类型与访问权限,请参考以下示例代码。// ObjectMetadata metadata = new ObjectMetadata();// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());// metadata.setObjectAcl(CannedAccessControlList.Private);// putObjectRequest.setMetadata(metadata);// 上传字符串。ossClient.putObject(putObjectRequest);// LOG.info("保存文件记录开始");
// fileDto.setPath(path);
// fileService.save(fileDto);ResponseDto responseDto = new ResponseDto();FileDto fileDto = new FileDto();fileDto.setPath(ossDomain + path);responseDto.setContent(fileDto);return responseDto;}
}
application.properties
big-file.vue
file.vue
演示:头像上传是用的单文件传输到OSS;视频上传是用的分片传输到OSS
teacher.vue
测试
上传视频和头像
10-3{white}阿里云视频点播服务介绍{white}{white}
阿里云视频点播服务介绍
视频点播控台的使用
视频点播帮助文档概览
10-4 基于OSS原生SDK上传视频到点播服务
VOD上传并加密转码
VOD上传并加密转码
1.视频加密与授权播放:基于 OSS原生SDK上传视频到点播服务,官方示例代码
pom.xml(course)
pom.xml(server)
VodUtil.java
package com.course.server.util;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSSClient;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.vod.model.v20170321.*;
import org.apache.commons.codec.binary.Base64;import java.io.File;
import java.io.InputStream;public class VodUtil {/*** 使用AK初始化VOD客户端* @param accessKeyId* @param accessKeySecret* @return* @throws ClientException*/public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {// 点播服务接入区域,国内请填cn-shanghai,其他区域请参考文档[点播中心](~~98194~~)String regionId = "cn-shanghai";DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);DefaultAcsClient client = new DefaultAcsClient(profile);return client;}/*** 获取视频上传地址和凭证* @param vodClient* @return* @throws ClientException*/public static CreateUploadVideoResponse createUploadVideo(DefaultAcsClient vodClient, String fileName) throws ClientException {CreateUploadVideoRequest request = new CreateUploadVideoRequest();request.setFileName(fileName);request.setTitle(fileName);//request.setDescription("this is desc");//request.setTags("tag1,tag2");
// request.setCoverURL("http://vod.aliyun.com/test_cover_url.jpg");
// request.setCateId(1000115308L);
// request.setTemplateGroupId("78fffb8c0c2426efd5baaaafed76fe36");//request.setWorkflowId("");//request.setStorageLocation("");//request.setAppId("app-1000000");//设置请求超时时间request.setSysReadTimeout(1000);request.setSysConnectTimeout(1000);return vodClient.getAcsResponse(request);}/*** 使用上传凭证和地址初始化OSS客户端(注意需要先Base64解码并Json Decode再传入)* @param uploadAuth* @param uploadAddress* @return*/public static OSSClient initOssClient(JSONObject uploadAuth, JSONObject uploadAddress) {String endpoint = uploadAddress.getString("Endpoint");String accessKeyId = uploadAuth.getString("AccessKeyId");String accessKeySecret = uploadAuth.getString("AccessKeySecret");String securityToken = uploadAuth.getString("SecurityToken");return new OSSClient(endpoint, accessKeyId, accessKeySecret, securityToken);}/*** 简单上传* @param ossClient* @param uploadAddress* @param inputStream*/public static void uploadLocalFile(OSSClient ossClient, JSONObject uploadAddress, InputStream inputStream){String bucketName = uploadAddress.getString("Bucket");String objectName = uploadAddress.getString("FileName");// 单文件上传ossClient.putObject(bucketName, objectName, inputStream);/* 视频点播不支持追加上传// 追加上传ObjectMetadata meta = new ObjectMetadata();meta.setContentType("text/plain");AppendObjectRequest request = new AppendObjectRequest(bucketName, objectName, file, meta);request.setPosition(0L);ossClient.appendObject(request);*/}/*** 上传本地文件* @param ossClient* @param uploadAddress* @param localFile*/public static void uploadLocalFile(OSSClient ossClient, JSONObject uploadAddress, String localFile){String bucketName = uploadAddress.getString("Bucket");String objectName = uploadAddress.getString("FileName");File file = new File(localFile);// 单文件上传ossClient.putObject(bucketName, objectName, file);/* 视频点播不支持追加上传// 追加上传ObjectMetadata meta = new ObjectMetadata();meta.setContentType("text/plain");AppendObjectRequest request = new AppendObjectRequest(bucketName, objectName, file, meta);request.setPosition(0L);ossClient.appendObject(request);*/}/*** 刷新上传凭证* @param vodClient* @return* @throws ClientException*/public static RefreshUploadVideoResponse refreshUploadVideo(DefaultAcsClient vodClient) throws ClientException {RefreshUploadVideoRequest request = new RefreshUploadVideoRequest();request.setAcceptFormat(FormatType.JSON);request.setVideoId("VideoId");//设置请求超时时间request.setSysReadTimeout(1000);request.setSysConnectTimeout(1000);return vodClient.getAcsResponse(request);}/*** 获取源文件信息* @param client 发送请求客户端* @return GetMezzanineInfoResponse 获取源文件信息响应数据* @throws Exception*/public static GetMezzanineInfoResponse getMezzanineInfo(DefaultAcsClient client, String videoId) throws Exception {GetMezzanineInfoRequest request = new GetMezzanineInfoRequest();request.setVideoId(videoId);//源片下载地址过期时间request.setAuthTimeout(3600L);return client.getAcsResponse(request);}/*** 获取播放凭证函数* @param client* @return* @throws Exception*/public static GetVideoPlayAuthResponse getVideoPlayAuth(DefaultAcsClient client, String videoId) throws Exception {GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();request.setVideoId(videoId);return client.getAcsResponse(request);}public static void main(String[] argv) {//您的AccessKeyIdString accessKeyId = "xxxxxxxxxxxxx";//您的AccessKeySecretString accessKeySecret = "xxxxxxxxxxxxx";//需要上传到VOD的本地视频文件的完整路径,需要包含文件扩展名String localFile = "/Users/zhaoxiaoyun/Downloads/fourcats.mp4";try {// 初始化VOD客户端并获取上传地址和凭证DefaultAcsClient vodClient = initVodClient(accessKeyId, accessKeySecret);String fileName = "test.mp4";CreateUploadVideoResponse createUploadVideoResponse = createUploadVideo(vodClient, fileName);// 执行成功会返回VideoId、UploadAddress和UploadAuthString videoId = createUploadVideoResponse.getVideoId();JSONObject uploadAuth = JSONObject.parseObject(Base64.decodeBase64(createUploadVideoResponse.getUploadAuth()), JSONObject.class);JSONObject uploadAddress = JSONObject.parseObject(Base64.decodeBase64(createUploadVideoResponse.getUploadAddress()), JSONObject.class);// 使用UploadAuth和UploadAddress初始化OSS客户端OSSClient ossClient = initOssClient(uploadAuth, uploadAddress);// 上传文件,注意是同步上传会阻塞等待,耗时与文件大小和网络上行带宽有关uploadLocalFile(ossClient, uploadAddress, localFile);System.out.println("上传视频成功, VideoId : " + videoId); // 7d6b8c07ab48456e932187080f42e88fGetMezzanineInfoResponse response = new GetMezzanineInfoResponse();response = getMezzanineInfo(vodClient, videoId);System.out.println("获取视频信息, response : " + JSON.toJSONString(response));} catch (Exception e) {System.out.println("上传视频失败, ErrorMessage : " + e.getLocalizedMessage());}}
}
记得修改自己的
VOD上传到指定分类,并自动转码
1.视频加密与授权播放:基于 OSS原生SDK上传视频到点播服务,上传到指定分类,并自动转码
VodUtil.java
视频点播不支持追加上传
1.视频加密与授权播放:基于 OSS原生SDK上传视频到点播服务,视频点播不支持追加上传
官方示例中,用的是简单上传putObject ,我们要改成我们需要的追加上传
但是有严格封装编码要求的文件类型,都是不支持追加方式上传的;比如音视频、图片等,上传到视频点播不支持追加上传
VodUtil.java
效果就不演示了,感兴趣的自己尝试一下,把这段代码打开,把上面的单文件上传注释,然后看效果,是一直在上传,但是无法上传成功!
项目集成VOD上传
小节增加vod字段
1.视频加密与授权播放:小节增加vod字段
由于视频点播不支持追加上传,我们只能改成单文件传
all.sql
generatorConfig.xml
SectionDto.java
section.vue
简单快速的方案:在阿里云控台做文件上传和转码,然后将vod复制到我们自己的控台
增加vod组件,用于上传视频到视频点播服务
1.视频加密与授权播放:增加vod组件,用于上传视频到视频点播服务
big-file.vue
vod组件就是对big-file组件做了一层封装。程序员天然喜欢对代码做封装,要注意度,封装得越多,灵活度就越低
vod.vue
<template><big-file v-bind:input-id="inputId"v-bind:text="text"v-bind:suffixs="suffixs"v-bind:use="use"v-bind:after-upload="afterUpload"v-bind:shard-size="shardSize"v-bind:url="'oss-append'"></big-file>
</template><script>
import BigFile from "./big-file";
export default {name: "vod",components: {BigFile},props: {text: {default: "上传VOD"},inputId: {default: "vod-upload"},suffixs: {default: []},use: {default: ""},shardSize: {default: 50 * 1024},afterUpload: {type: Function,default: null},},
}
</script>
目前为止,vod和big-file功能一样,需要先测试下vod组件是否可用
section.vue
我们在js里对video赋值,vue会监听到值的变化,并渲染视频控件。如果还没渲染完,我们就去获取时长,这时就会得到NaN,所以需要加延时获取
测试,记得先清空数据库和oss文件
file表增加vod字段
1.视频加密与授权播放:file表增加vod字段
all.sql
generatorConfig.xml
FileDto.java
增加视频点播文件上传功能
1.视频加密与授权播放:增加视频点播文件上传功能
application.properties
vod.vue
由于视频点播不支持追加上传,所以使用vod组件进行上传的,只能有一个分片
section.vue
获取到的可播放地址是有时效的,所以就算保存到数据库也会过期,没用。以后会根据vod来播放。
文件检查时,根据是否是视频点播文件来获取视频信息
1.视频加密与授权播放:文件检查时,根据是否是视频点播文件来获取视频信息
UploadController.java
测试
10-6 视频授权播放功能开发
阿里云播放器的基本使用
1.视频加密与授权播放:集成阿里云播放器,制作player播放器组件
player.vue
<template><div v-bind:id="playerId">
<!--要做成动态的,所以不在这个地方写了-->
<!-- <div class="prism-player" id="J_prismPlayer"></div>--></div>
</template>
<script>
export default {name: "player",props: {playerId: {default: "player-div"},},data: function () {return {aliPlayer: {},//播放器实例}},methods: {playUrl(url) {let _this = this;console.log("开始播放:", url);//如果已经有播放器了,则将播放器div删除if (_this.aliPlayer) {_this.aliPlayer = null;$("#J_prismPlayer").remove();}// 初始化播放器$("#" + _this.playerId).append("<div class=\"prism-player\" id=\"J_prismPlayer\"></div>");_this.aliPlayer = new Aliplayer({id: "J_prismPlayer",width: '100%',autoplay: false,source: url,cover: 'http://imooc-coursemac.oss-cn-shanghai.aliyuncs.com/头像1.jpg',}, function (player) {console.log('播放器创建好了。')});},}
}
</script>
index.html
section.vue
video控件隐藏掉,不要删除,要通过它获取时长。也可以通过视频点播的API去获取视频时长。
测试
功能更强,可以倍速等等
获取vod授权码并授权播放
1.视频加密与授权播放:获取vod授权码并授权播放,需要在存储管理中把权限设置成公共读
默认是私有的,更改为公共读
VodUtil.java
VodController.java
player.vue
一个页面可能会放多个player组件,所以需要把id做成动态变化的,一个页面的元素,id值要是唯一的。
modal-player.vue
带有模态框的播放器组件modal-player,里面包含了player组件
<template><div id="player-modal" class="modal" tabindex="-1" role="dialog"><div class="modal-dialog" role="document"><div class="modal-content"><div class="modal-body"><player v-bind:player-id="'modal-player-div'"ref="player"></player></div></div></div></div>
</template>
<script>
import Player from "./player";
export default {name: 'modal-player',components: {Player},data: function () {return {aliPlayer: {}, // 播放器实例}},methods: {playUrl(url) {let _this = this;_this.$refs.player.playUrl(url);},playVod(vod) {let _this = this;_this.$refs.player.playVod(vod);$("#player-modal").modal("show");}}
}
</script><style scoped>
#player-modal .modal-body {padding: 0;
}
</style>
section.vue
测试
相关文章:

Spring Cloud + Vue前后端分离-第10章 基于阿里云OSS的文件上传
源代码在GitHub - 629y/course: Spring Cloud Vue前后端分离-在线课程 Spring Cloud Vue前后端分离-第10章 基于阿里云OSS的文件上传 前面介绍的文件上传是基于本地文件服务器的文件上传,但是自己搭文件服务器会有很多运维的问题,比如磁盘满了要扩容…...
C++ 中的耗时计算函数
#include <time.h>int clock_gettime (clockid_t clock_id, struct timespec *tp) 获取当前 clock_id 的时钟值并存储在 tp 中。 其中 tp 是一个 timespec 结构体,在 time.h 头文件中定义: #include <time.h>:struct timespec {time_t t…...

【Element】el-form和el-table嵌套实现表格编辑并提交表单校验
一、背景 页面需要用到表格采集用户数据,提交时进行表单校验;即表格中嵌套着表单,保存时进行表单校验 二、功能实现 2.1、el-form和el-table嵌套说明 ① :model"formData" 给表单绑定数据,formData是表单的数据对象 …...

初识Winform
什么是winform? WinForms(Windows Forms)是Microsoft .NET框架中的一个用户界面(UI)技术,用于创建Windows应用程序。它提供了一组用于构建图形用户界面的类和控件,以及与用户交互的事件模型。 …...

Redis:原理速成+项目实战——Redis实战5(互斥锁、逻辑过期解决缓存击穿问题)
👨🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:Redis:原理速成项目实战——Redis实战4(解决Redis缓存穿透、雪崩、击穿) 📚订阅专…...
前端优化之一:dns预获取 dns-prefetch 提升页面载入速度
问题:怎么做到dns域解析? 用于优化网站页面的图片 问题:怎么提升网站性能? dns域解析,是提升网站的一个办法。 DNS Prefetch,即DNS预获取,是前端优化的一部分。 一般来说,在前端…...
C语言中一些基本数据类型的典型大小
char:通常是1字节。表示一个字符。int:通常在现代系统中是4字节(但这取决于编译器和架构,有时可能是2字节)。float:通常是4字节。double:通常是8字节。short 和 short int:通常是2字…...

[C/C++]排序算法 快速排序 (递归与非递归)
目录 🚩概念: 🚩实现: ⚡1.hoare ⚡2.挖坑法 ⚡3.双指针法 🚩快速排序递归实现 🚩快速排序非递归实现 🚩概念: 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据比另一部分的所有…...

『年度总结』逐梦编程之始:我的2023学习回顾与展望
目录 前言 我与Python 我与C语言 第一篇正式博客: 第二篇正式博客(扫雷): 指针学习笔记: C语言学习笔记: 我与数据结构: yuan 这篇博客,我将回顾2023年编程之旅的起点,同时展…...

MyBatis学习二:Mapper代理开发、配置文件完成增删改查、注解开发
前言 公司要求没办法,前端也要了解一下后端知识,这里记录一下自己的学习 学习教程:黑马mybatis教程全套视频教程,2天Mybatis框架从入门到精通 文档: https://mybatis.net.cn/index.html Mapper代理开发 目的 解决…...

【React系列】受控非受控组件
本文来自#React系列教程:https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg5MDAzNzkwNA&actiongetalbum&album_id1566025152667107329) 一. refs 的使用 在React的开发模式中,通常情况下不需要、也不建议直接操作DOM原生,但是某些…...
OpenCV-Python(22):2D直方图
目标 了解图像的2D直方图绘制2D直方图 介绍 在前面的部分我们介绍了如何绘制一维直方图,之所以称为一维,是因为我们只考虑了图像的一个特征:灰度值。但是在2D 直方图中我们就需要考虑两个图像特征。对于彩色图像的直方图通常情况下我们需要…...
Kubernetes 100个常用命令
本文简单总结关于使用 Kubectl 进行 Kubernetes 诊断的指南。列出了 100 个 Kubectl 命令,这些命令对于诊断 Kubernetes 集群中的问题非常有用。这些问题包括但不限于: 集群信息 Pod 诊断 服务诊断 部署诊断 网络诊断 持久卷和持久卷声明诊断 资源…...

labuladong日常刷题-差分数组 | LeetCode 1109航班预定统计 | 花式遍历 151反转字符串里的单词
差分数组–前缀和数组的升级 LeetCode 1109 航班预定统计 2024.1.1 题目链接labuladong讲解[链接] class Solution { public:vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n) {//构建航班人数数组,数组大小为n,初…...

HbuilderX中的git的使用
原文链接https://blog.csdn.net/Aom_yt/article/details/119924356...
LeetCode每日一题 | 1944. 队列中可以看到的人数
文章目录 队列中可以看到的人数题目描述问题分析程序代码(Golang 版本) 队列中可以看到的人数 题目描述 原题链接 有 n 个人排成一个队列,从左到右 编号为 0 到 n - 1 。给你以一个整数数组 heights ,每个整数 互不相同ÿ…...
React16源码: JSX2JS及React.createElement源码实现
JSX 到 Javascript 的转换 React中的 JSX 类似于 Vue中的template模板文件,Vue是基于编译时将template模板转换成render函数在React中,JSX是类似于html和javascript混编的语法,而javascript是真的javascript, html并非真的html它的可阅读性可…...
整理composer安装版本的python脚本
整理composer安装版本的python脚本 脚本实现的功能是去除composer安装命令后的版本号 def remove_version_numbers(commands):"""Remove version numbers from composer require commands.Args:commands (list of str): List of composer require commands.Retu…...

十、基本对话框大集合(Qt5 GUI系列)
目录 一、设计需求 二、实现代码 三、代码解析 四、总结 一、设计需求 Qt提供了很多标准的对话框。例如标准文件对话框(QFileDialog)、标准颜色对话框(QColorDialog)、标准字体对话框 (QFontDialog)、标准输入对话框 (QInputDialog) 及消息对话框 (QMessageBox)。本文展示各…...
大A又跌了
才开盘几天,又开始下跌了。生活更加苦难。期待高深算法。...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...

【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...