阿里 对象存储OSS 云存储服务

1.简介

对象存储服务(Object Storage Service ,OSS) 是一种 海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。

2.如何使用。参考文档

 

看文档,说的很明白,这里就不演示了

3. SpringCloudAlibaba-OSS

spring-cloud-alibaba/README-zh.md at 2022.x · alibaba/spring-cloud-alibaba · GitHub

好像新版本没有starter了

自己封装一下原生API吧

package com.jmj.gulimall.product.config;import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class OssClientConfiguration {@Value("${spring.cloud.alicloud.access-key}")private String accessKey;@Value("${spring.cloud.alicloud.secret-key}")private String secretKey;@Value("${spring.cloud.alicloud.endpoint}")private String endpoint;@Beanpublic OSS ossClient() {// 创建OSSClient实例。CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKey, secretKey);// 创建ClientBuilderConfiguration。// ClientBuilderConfiguration是OSSClient的配置类,可配置代理、连接超时、最大连接数等参数。ClientBuilderConfiguration conf = new ClientBuilderConfiguration();// 设置Socket层传输数据的超时时间,默认为50000毫秒。conf.setSocketTimeout(10000);// 设置建立连接的超时时间,默认为50000毫秒。conf.setConnectionTimeout(10000);// 设置失败请求重试次数,默认为3次。conf.setMaxErrorRetry(5);OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider,conf);return ossClient;}}
package com.jmj.gulimall.product.ossclient;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;@Component
@Slf4j
public class OssClientTemplate {@Autowiredprivate OSS ossClient;public Boolean uploadFile(String bucketName, String objectName, File file) {// 创建PutObjectRequest对象。try {PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, file);// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。ObjectMetadata metadata = new ObjectMetadata();metadata.setHeader("x-oss-forbid-overwrite", true);// metadata.setObjectAcl(CannedAccessControlList.Private);putObjectRequest.setMetadata(metadata);// 上传文件。PutObjectResult result = ossClient.putObject(putObjectRequest);log.info("上传成功:文件名 {}", objectName);return true;} catch (OSSException oe) {log.error("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");log.error("Error Message:" + oe.getErrorMessage());log.error("Error Code:" + oe.getErrorCode());log.error("Request ID:" + oe.getRequestId());log.error("Host ID:" + oe.getHostId());} catch (ClientException ce) {log.error("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");log.error("Error Message:" + ce.getMessage());}return false;}public Boolean uploadFile(String bucketName, String objectName, String content){// 创建PutObjectRequest对象。ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content.getBytes());try {PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, byteArrayInputStream);// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。ObjectMetadata metadata = new ObjectMetadata();metadata.setHeader("x-oss-forbid-overwrite", true);// metadata.setObjectAcl(CannedAccessControlList.Private);putObjectRequest.setMetadata(metadata);// 上传文件。PutObjectResult result = ossClient.putObject(putObjectRequest);log.info("上传成功:文件名 {}", objectName);return true;} catch (OSSException oe) {log.error("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");log.error("Error Message:" + oe.getErrorMessage());log.error("Error Code:" + oe.getErrorCode());log.error("Request ID:" + oe.getRequestId());log.error("Host ID:" + oe.getHostId());} catch (ClientException ce) {log.error("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");log.error("Error Message:" + ce.getMessage());}finally {if (byteArrayInputStream!=null){try {byteArrayInputStream.close();} catch (IOException e) {e.printStackTrace();}}}return false;}public Boolean uploadFile(String bucketName, String objectName, InputStream inputStream){// 创建PutObjectRequest对象。try {PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。ObjectMetadata metadata = new ObjectMetadata();metadata.setHeader("x-oss-forbid-overwrite", true);// metadata.setObjectAcl(CannedAccessControlList.Private);putObjectRequest.setMetadata(metadata);// 上传文件。PutObjectResult result = ossClient.putObject(putObjectRequest);log.info("上传成功:文件名 {}", objectName);return true;} catch (OSSException oe) {log.error("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");log.error("Error Message:" + oe.getErrorMessage());log.error("Error Code:" + oe.getErrorCode());log.error("Request ID:" + oe.getRequestId());log.error("Host ID:" + oe.getHostId());} catch (ClientException ce) {log.error("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");log.error("Error Message:" + ce.getMessage());}finally {if (inputStream!=null){try {//其实流已经被关闭了,我再关闭一下保险一点inputStream.close();} catch (IOException e) {e.printStackTrace();}}}return false;}public Boolean uploadFile(String objectName, InputStream inputStream){// 创建PutObjectRequest对象。return uploadFile("gulimall-jmj", objectName, inputStream);}
}

4.后端签名直传

package com.jmj.gulimall.third.config;import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.jmj.gulimall.third.ossclient.OssClientTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@EnableConfigurationProperties({OssConfigurationProperties.class})
@Slf4j
@RefreshScope //动态从配置中心获取配置
public class OssClientConfiguration {@Autowiredprivate OssConfigurationProperties ossConfigurationProperties;@Beanpublic OSS ossClient() {// 创建OSSClient实例。CredentialsProvider credentialsProvider = new DefaultCredentialProvider(ossConfigurationProperties.getAccessKey(), ossConfigurationProperties.getSecretKey());// 创建ClientBuilderConfiguration。// ClientBuilderConfiguration是OSSClient的配置类,可配置代理、连接超时、最大连接数等参数。ClientBuilderConfiguration conf = new ClientBuilderConfiguration();// 设置是否支持CNAME。CNAME用于将自定义域名绑定到目标Bucket。conf.setSupportCname(true);// 设置Socket层传输数据的超时时间,默认为50000毫秒。conf.setSocketTimeout(10000);// 设置建立连接的超时时间,默认为50000毫秒。conf.setConnectionTimeout(10000);// 设置失败请求重试次数,默认为3次。conf.setMaxErrorRetry(5);OSS ossClient = new OSSClientBuilder().build(ossConfigurationProperties.getEndpoint(), credentialsProvider, conf);log.info("ossClient初始化完成,properties={}",ossConfigurationProperties);return ossClient;}@Beanpublic OssClientTemplate ossClientTemplate(OSS ossClient) {return new OssClientTemplate(ossClient,ossConfigurationProperties);}}
package com.jmj.gulimall.third.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;@ConfigurationProperties(prefix = "spring.cloud.alicloud")
@Data
@RefreshScope //动态从配置中心获取配置
public class OssConfigurationProperties {private String accessKey;private String secretKey;private String endpoint;private String regionEnd;private String bucket;}
package com.jmj.gulimall.third.controller;import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.jmj.gulimall.third.common.R;
import com.jmj.gulimall.third.config.OssConfigurationProperties;
import com.jmj.gulimall.third.ossclient.OssClientTemplate;
import lombok.extern.slf4j.Slf4j;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;@RestController
@Slf4j
@RequestMapping("/oss")
public class OssController {@Autowiredprivate OssClientTemplate ossClientTemplate;@Autowiredprivate OssConfigurationProperties properties;@GetMapping("/policy")public R policy(HttpServletRequest request, HttpServletResponse response) {// 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。
//                String callbackUrl = "https://192.168.0.0:8888";// 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");String formatDate = simpleDateFormat.format(new Date());String dir = formatDate + "/";OSS ossClient = ossClientTemplate.getOssClient();String accessKeyId = properties.getAccessKey();String regionEnd = properties.getRegionEnd();String bucket = properties.getBucket();String host = "https://" + bucket + "." + regionEnd;try {long expireTime = 30;long expireEndTime = System.currentTimeMillis() + expireTime * 1000;Date expiration = new Date(expireEndTime);// PostObject请求最大可支持的文件大小为5 GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。PolicyConditions policyConds = new PolicyConditions();policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);byte[] binaryData = postPolicy.getBytes("utf-8");String accessId = accessKeyId;String encodedPolicy = BinaryUtil.toBase64String(binaryData);String postSignature = ossClient.calculatePostSignature(postPolicy);Map<String, String> respMap = new LinkedHashMap<String, String>();respMap.put("accessid", accessId);respMap.put("policy", encodedPolicy);respMap.put("signature", postSignature);respMap.put("dir", dir);respMap.put("host", host);respMap.put("expire", String.valueOf(expireEndTime / 1000));// respMap.put("expire", formatISO8601Date(expiration));return R.ok().put("data",respMap);} catch (Exception e) {// Assert.fail(e.getMessage());log.error(e.getMessage(), e);}return  R.error("上传签名异常");}}
package com.jmj.gulimall.third.ossclient;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.jmj.gulimall.third.config.OssConfigurationProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;@Slf4j
public class OssClientTemplate {private OSS ossClient;public OSS getOssClient() {return ossClient;}private OssConfigurationProperties properties;public OssClientTemplate(OSS ossClient, OssConfigurationProperties properties) {this.ossClient = ossClient;this.properties = properties;}public Boolean uploadFile(String bucketName, String objectName, File file) {// 创建PutObjectRequest对象。try {PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, file);// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。ObjectMetadata metadata = new ObjectMetadata();metadata.setHeader("x-oss-forbid-overwrite", true);// metadata.setObjectAcl(CannedAccessControlList.Private);putObjectRequest.setMetadata(metadata);// 上传文件。PutObjectResult result = ossClient.putObject(putObjectRequest);log.info("上传成功:文件名 {}", objectName);return true;} catch (OSSException oe) {log.error("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");log.error("Error Message:" + oe.getErrorMessage());log.error("Error Code:" + oe.getErrorCode());log.error("Request ID:" + oe.getRequestId());log.error("Host ID:" + oe.getHostId());} catch (ClientException ce) {log.error("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");log.error("Error Message:" + ce.getMessage());}return false;}public Boolean uploadFile(String bucketName, String objectName, String content){// 创建PutObjectRequest对象。ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content.getBytes());try {PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, byteArrayInputStream);// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。ObjectMetadata metadata = new ObjectMetadata();metadata.setHeader("x-oss-forbid-overwrite", true);// metadata.setObjectAcl(CannedAccessControlList.Private);putObjectRequest.setMetadata(metadata);// 上传文件。PutObjectResult result = ossClient.putObject(putObjectRequest);log.info("上传成功:文件名 {}", objectName);return true;} catch (OSSException oe) {log.error("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");log.error("Error Message:" + oe.getErrorMessage());log.error("Error Code:" + oe.getErrorCode());log.error("Request ID:" + oe.getRequestId());log.error("Host ID:" + oe.getHostId());} catch (ClientException ce) {log.error("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");log.error("Error Message:" + ce.getMessage());}finally {if (byteArrayInputStream!=null){try {byteArrayInputStream.close();} catch (IOException e) {e.printStackTrace();}}}return false;}public Boolean uploadFile(String bucketName, String objectName, InputStream inputStream){// 创建PutObjectRequest对象。try {PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。ObjectMetadata metadata = new ObjectMetadata();metadata.setHeader("x-oss-forbid-overwrite", true);// metadata.setObjectAcl(CannedAccessControlList.Private);putObjectRequest.setMetadata(metadata);// 上传文件。PutObjectResult result = ossClient.putObject(putObjectRequest);log.info("上传成功:文件名 {}", objectName);return true;} catch (OSSException oe) {log.error("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");log.error("Error Message:" + oe.getErrorMessage());log.error("Error Code:" + oe.getErrorCode());log.error("Request ID:" + oe.getRequestId());log.error("Host ID:" + oe.getHostId());} catch (ClientException ce) {log.error("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");log.error("Error Message:" + ce.getMessage());}finally {if (inputStream!=null){try {//其实流已经被关闭了,我再关闭一下保险一点inputStream.close();} catch (IOException e) {e.printStackTrace();}}}return false;}public Boolean uploadFile(String objectName, InputStream inputStream){// 创建PutObjectRequest对象。return uploadFile(properties.getBucket(), objectName, inputStream);}
}

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

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

相关文章

【python从入门到精通】-- 第四战:语句汇总

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文…

docker从入门到熟悉

一、什么是docker&#xff1f; Docker是一个用于开发&#xff0c;交付和运行应用程序的开放平台。Docker使您能够将应用程序与基础架构分开&#xff0c;从而可以快速交付软件。借助Docker&#xff0c;您可以以与管理应用程序相同的方式来管理基础架构。通过利用Docker的快速交付…

GPT3, llama2, InternLM2技术报告对比

GPT3&#xff08;September 22, 2020&#xff09;是大语言应用的一个milestone级别的作品&#xff0c;Llama2&#xff08;February 2023&#xff09;则是目前开源大模型中最有影响力的作品&#xff0c;InternLM2&#xff08;2023.09.20&#xff09;则是中文比较有影响力的作品。…

Linux文件搜索工具(gnome-search-tool)

opensuse下安装: sudo zypper install gnome-search-tool 操作界面:

JNews Theme最新版本:新闻网站首选的WordPress主题,功能强大且灵活

JNews Theme最新版本&#xff1a;新闻网站的首选WordPress主题 在当今数字化时代&#xff0c;新闻网站扮演着至关重要的角色。为了打造一个吸引读者、功能齐全的新闻平台&#xff0c;选择一款合适的WordPress主题显得尤为关键。而JNews Theme最新版本正是新闻网站的首选WordPr…

MacOS - brew 和 brew cask 有什么区别?

brew 是 ruby 的包管理&#xff0c;后来看 yangzhiping 的博客介绍了 brew cask&#xff0c;感觉 cask 是更好的关联关系管理&#xff0c;但是&#xff0c;我后来使用过程中&#xff0c;发现很多软件 brew cask 里没有&#xff0c;但是 brew 里面倒是挺多&#xff01;今天来给说…

java面试题(Redis)

事情干的差不多了&#xff0c;开刷面试题和算法&#xff0c;争取在短时间内快速成长&#xff0c;理解java面试的常见题型 一、redis使用场景&#xff1a; 缓存&#xff1a;穿透、击穿、雪崩 双写一致、持久化 数据过期、淘汰策略 分布式锁&#xff1a;setnx、redisson 计数…

【JavaScript】函数 ⑦ ( 函数定义方法 | 命名函数 | 函数表达式 )

文章目录 一、函数定义方法1、命名函数2、函数表达式3、函数表达式示例 一、函数定义方法 1、命名函数 定义函数的标准方式 就是 命名函数 , 也就是之前讲过的 声明函数 ; 函数 声明后 , 才能被调用 ; 声明函数的语法如下 : function functionName(parameters) { // 函数体 …

计算机网络:数据链路层 - 可靠传输协议

计算机网络&#xff1a;数据链路层 - 可靠传输协议 可靠传输概念停止-等待协议 SW回退N帧协议 GBN选择重传协议 SR 可靠传输概念 如下所示&#xff0c;帧在传输过程中受到干扰&#xff0c;产生了误码。接收方的数据链路层&#xff0c;通过真伪中的真检验序列 FCS 字段的值&…

ROS 2边学边练(13)-- 创建一个功能包

前言 功能包是啥 简单理解&#xff0c;功能包就是一个文件夹&#xff0c;一个具备一定功能的文件夹&#xff0c;一个有组织有结构的文件夹&#xff0c;一个能方便分享给其他人使用的文件夹&#xff0c;比如我们的小海龟功能包&#xff0c;它就是一个文件夹&#xff0c;名字叫t…

WPS 不登录无法使用基本功能的解决办法

使用wps时&#xff0c;常常有个比较让人烦恼的事&#xff0c;在不登录的情况下&#xff0c;新建或者打开文档时&#xff0c;wps不让你使用其基本的功能&#xff0c;如设置字体等&#xff0c;相关界面变成灰色&#xff0c;这时Wps提示用户登录注册或登录&#xff0c;但我又不想登…

【QT入门】 无边框窗口设计之综合运用,实现WPS的tab页面

往期回顾&#xff1a; 【QT入门】 无边框窗口设计之实现窗口阴影-CSDN博客 【QT入门】 无边框窗口设计之实现圆角窗口-CSDN博客 【QT入门】 无边框窗口设计综合运用之自定义标题栏带圆角阴影的窗口-CSDN博客 【QT入门】 无边框窗口设计之综合运用&#xff0c;实现WPS的tab页面 …

Nexus的docker安装,maven私服

文章目录 前言安装创建文件夹设置文件夹权限docker创建指令制作docker-compose.yaml文件 查看网站访问网页查看密码 前言 nexus作为私服的maven仓库&#xff0c;在企业级应用中&#xff0c;提供了依赖来源的稳定性&#xff0c;为构建庞大的微服务体系&#xff0c;打下基础 安…

算法——分治(快速排序)

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 此篇文章与大家分享分治算法关于快速排序的专题 对于快速排序在我个人主页专栏 <排序> 有详细的介绍,此专题对快排进行了优化操作,并介绍了优化后的快排的几种运用 如果有不足的或者错误的请…

【正点原子探索者STM32F4】TFTLCD实验学习记录:FSMC控制 TFTLCD的寄存器配置

FSMC控制 TFTLCD的寄存器配置 异步模式 A控制 TFTLCDFSMC寄存器配置ILI9341电平持续时间要求 参考 异步模式 A控制 TFTLCD LCD以ILI9341为例 FSMC寄存器配置 对于异步突发访问方式&#xff0c; FSMC 主要设置 3 个时间参数&#xff1a;地址建立时间(ADDSET)、 数据 建立时间…

Unity之PUN实现多人联机射击游戏的优化(Section 2)

目录 &#x1f3ae;一、准备工作 &#x1f3ae;二、实现手雷投掷动作 &#x1f3ae;三、手雷投掷同步 &#x1f4a4;3.1 photonView.RPC &#x1f3ae;四、同步手雷伤害 这几周都给我布置任务了&#xff0c;最近可忙。现在终于有机会更新了&#xff0c;也谢谢大家的阅读&a…

JavaSE-11笔记【多线程2(+2024新)】

文章目录 6.线程安全6.1 线程安全问题6.2 线程同步机制6.3 关于线程同步的面试题6.3.1 版本16.3.2 版本26.3.3 版本36.3.4 版本4 7.死锁7.1 多线程卖票问题 8.线程通信8.1 wait()和sleep的区别&#xff1f;8.2 两个线程交替输出8.3 三个线程交替输出8.4 线程通信-生产者和消费者…

Tailwind 4.0 即将到来:前端开发的“速度与激情”

随着前端开发技术的不断进步&#xff0c;我们每天都在寻找更快、更简洁的解决方案来提升我们的开发效率和用户体验。今天&#xff0c;我要为大家介绍一项令人振奋的新技术进展——Tailwind 4.0的来临&#xff01; 对于经常使用Tailwind的朋友们来说&#xff0c;这个消息无疑是激…

阿里云短信服务业务

一、了解阿里云用户权限操作 1.注册账号、实名认证&#xff1b; 2.使用AccessKey 步骤一 点击头像&#xff0c;权限安全的AccessKey 步骤二 设置子用户AccessKey 步骤三 添加用户组和用户 步骤四 添加用户组记得绑定短信服务权限 步骤五 添加用户记得勾选openApi访问 添加…

Educational Codeforces Round 162 (Rated for Div. 2) ----- E. Count Paths --- 题解

E. Count Paths&#xff1a; 题目大意&#xff1a; 思路解析&#xff1a; 根据题目中定义的美丽路径&#xff0c;我们可以发现路径只有两种情况&#xff1a; 当前结点作为起始结点&#xff0c;那我们只需要知道它的子树下有多少个相同颜色的结点&#xff0c;并且相同颜色的结…