技术标签: 商城-练手项目 SpringCloud 微服务 java 服务器 数据库 SpringBoot 框架
文件存储大致分为以上三种方式:普通文件上传,普通文件的分布式情况,文件存储服务。
普通文件上传: 单体应用或小项目可以部署在一个服务器上,浏览器发送上传文件的请求将文件存储在项目中的某个位置,如下次要用到此文件浏览器可以发送请求给服务器,服务器返回此文件进行展示。
普通文件的分布式情况: 分布式情况下,商品服务分布在不同的服务器上。若只将文件存储在A服务器中,下次浏览器的请求被负载均衡到B服务器,则浏览器访问不到文件。
文件存储服务: 无论浏览器发到那个服务进行文件上传,最终将上传的文件统一存储在文件存储系统中例如自建的服务器,云存储服务(阿里云,七牛云等)。本文记录阿里云对象存储服务OSS相关知识。
对象存储(Object Storage Service,OSS) 也叫基于对象的存储,是一种解决和处理离散单元的方法,可提供基于分布式系统之上的对象形式的数据存储服务。
存储类型(Storage Class)
OSS提供标准、低频访问、归档、冷归档四种存储类型,全面覆盖从热到冷的各种数据存储场景。其中标准存储类型提供高持久、高可用、高性能的对象存储服务,能够支持频繁的数据访问;低频访问存储类型适合长期保存不经常访问的数据(平均每月访问频率1到2次),存储单价低于标准类型;归档存储类型适合需要长期保存(建议半年以上)的归档数据;冷归档存储适合需要超长时间存放的极冷数据。更多信息,请参见存储类型介绍。
存储空间(Bucket)
存储空间是您用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间。存储空间具有各种配置属性,包括地域、访问权限、存储类型等。您可以根据实际需求,创建不同类型的存储空间来存储不同的数据。
对象(Object)
对象是OSS存储数据的基本单元,也被称为OSS的文件。对象由元信息(Object Meta)、用户数据(Data)和文件名(Key)组成。对象由存储空间内部唯一的Key来标识。对象元信息是一组键值对,表示了对象的一些属性,例如最后修改时间、大小等信息,同时您也可以在元信息中存储一些自定义的信息。
地域(Region)
地域表示OSS的数据中心所在物理位置。您可以根据费用、请求来源等选择合适的地域创建Bucket。更多信息,请参见OSS已开通的地域。
访问域名(Endpoint)
Endpoint表示OSS对外服务的访问域名。OSS以HTTP RESTful API的形式对外提供服务,当访问不同地域的时候,需要不同的域名。通过内网和外网访问同一个地域所需要的域名也是不同的。更多信息,请参见各个Region对应的Endpoint。
访问密钥(AccessKey)
AccessKey简称AK,指的是访问身份验证中用到的AccessKey ID和AccessKey Secret。OSS通过使用AccessKey ID和AccessKey Secret对称加密的方法来验证某个请求的发送者身份。AccessKey ID用于标识用户;AccessKey Secret是用户用于加密签名字符串和OSS用来验证签名字符串的密钥,必须保密。关于获取AccessKey的方法,请参见获取AccessKey。
使用过程:
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.5.0</version>
</dependency>
@Test
public void testUpload() throws FileNotFoundException {
//endPoint以杭州为例 其他Region请按实际情况填写
String endPoint = "oss-cn-hangzhou.aliyuncs.com";
//云账号AccessKey所有API访问权限 建议遵循阿里云安全最佳实践创建并适用 RAM子账号进行API访问或日常运维
String accessKeyId = "**********************";
String accessKeySecret = "*********************";
//创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endPoint,accessKeyId,accessKeySecret);
//文件流上传
InputStream inputStream = new FileInputStream("C:\\Users\\Administrator.DESKTOP-UJHR16T\\Pictures\\I\\IMG_4909(20210220-081040).JPG");
ossClient.putObject("gulimall-hello-11","Ha.JPG",inputStream);
System.out.println("上传完成!");
//oss客户端关闭
ossClient.shutdown();
}
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
spring:
cloud:
alicloud:
access-key: ************************
secret-key: ************************
oss:
endPoint: oss-cn-hangzhou.aliyuncs.com
@Autowired
private OSSClient ossClient;
@Test
public void testUpload() throws FileNotFoundException {
//文件流上传
InputStream inputStream = new FileInputStream("C:\\Users\\Administrator.DESKTOP-UJHR16T\\Pictures\\Camera Roll\\IMG_6254.JPG");
ossClient.putObject("gulimall-hello-1128","shuai.JPG",inputStream);
System.out.println("上传完成!");
//oss客户端关闭
ossClient.shutdown();
}
gulimall-third-party 第三方服务作为整个项目文件上传服务,若为每个微服务创建文件存储功能,都使用OSS对象存储服务则过于繁琐,只需创建gulimall-third-party 第三方服务即可。
4.1.1 导入依赖
<!--springcloud-alibababa的oss依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<!--web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--openfeign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
4.1.2 编写配置
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
alicloud:
access-key: ********************
secret-key: ********************
oss:
endPoint: oss-cn-hangzhou.aliyuncs.com
bucket: gulimall-hello-1128
application:
name: gulimall-third-party
server:
port: 30000
spring.application.name=gulimall-third-party
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=1d48db76-7f24-4cd2-b671-8a0ee2esda1
spring.cloud.nacos.config.ext-config[0].data-id=oss.yml
spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.ext-config[0].refresh=true
4.1.3 编写代码
@RestController
public class OssController {
@Autowired
OSS ossClient;
@Value("${spring.cloud.alicloud.oss.endpoint}")
private String endpoint;
@Value("${spring.cloud.alicloud.oss.bucket}")
private String bucket;
@Value("${spring.cloud.alicloud.access-key}")
private String accessId;
@RequestMapping("/oss/policy")
public R policy() {
//https://gulimall-hello-1128.oss-cn-hangzhou.aliyuncs.com/hahaha.jpg
String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
// callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
//String callbackUrl = "http://88.88.88.88:8888";
String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
String dir = format + "/"; // 用户上传文件时指定的前缀。
Map<String, String> respMap = null;
try {
long expireTime = 30;
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
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(StandardCharsets.UTF_8);
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
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));
} catch (Exception e) {
// Assert.fail(e.getMessage());
System.out.println(e.getMessage());
}
return R.ok().put("data",respMap);
}
}
文章浏览阅读1.5k次。1.根据下标截取:String str = str.substring(开始的下标,截取的长度)2.根据字符截取://截取_之前字符串:String str = str.substring(0, str.indexOf("_"));------------------------------------------------------------------//截取_之后字符串:String str = str.substring(0, str.indexOf("_"));String_java根据下标获取字符
文章浏览阅读1.7k次。一、环境配置(安装)服务器端:yum install targetcli #管理程序systemctl start target #打开服务客户端:yum install iscsi-initiator-utils #iscsi应用程序通常这个都安装过了。二、targetcli的配置服务器端: 首先要有一块需要共享的硬盘分区,这是我要共享的..._在linux操作系统上配置iscsi的服务器targetcli不小心退出了
文章浏览阅读1.1w次,点赞10次,收藏87次。QTreeWidget继承自QTreeView,是通过树形结构来展示数据结构的控件。1.QTreeWidget和QTreeView的区别QTreeView一般和相应的QXXModel合用,形成Model/View结构.QTreeView是一个视图类,你需要手动给其指定模型类,才能够显示数据。QTreeWidget继承自QTreeView,是封闭了默认Model的QTreeView,应用了模型/视图的编程方法,将数据和显示分开了。就灵活性来讲,QTreeView要灵活些。QTreewidg._qtreewidget用法
文章浏览阅读1.9k次。Jetpack CameraX 库 的 PreviewView 可以帮助您解决这一问题。通过在各种 Android 设备上提供开发者友好、一致且稳定的 API,使得展示相机的预览变得不再困难。_camerax surfaceview
文章浏览阅读310次。链接器作为计算机系统中重要的组成部分,负责将多个目标文件和库文件合并成可执行文件。它通过符号解析、地址重定位和符号重定位等步骤,完成了程序的连接和重定位工作。此外,链接器还可以进行一些优化,以提高程序的执行效率。链接器的工作原理和功能对于软件开发人员来说至关重要,在编写高效、可靠的程序时起着重要作用。希望本文能够帮助读者更好地理解和应用链接器,提升软件开发的水平。_链接器linker
文章浏览阅读5.7k次,点赞15次,收藏53次。qtdesigner添加菜单栏和工具栏_qtdesigner顶部导航菜单栏
文章浏览阅读5.5k次,点赞3次,收藏9次。前言:我们在之前就有了子类与父类之间的传参,又有利用总线进行传参,但两者都有一定的弊端。如:总线定义组件太多容易混淆等;所以接下来我们会利用VueX进行参数传。目录一:VueX简介一:VueX简介官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。可以想象为一个“前端数据库”(数据仓库), 让其在各个页面上实现数据的共享包括状态,并且可操作 Vuex分成五个部分: 1.State:单一状态树 2.Getters:状态获取 3..._vuex同步异步获取数据的区别
文章浏览阅读2.6w次,点赞2次,收藏17次。servlet返回数据的方法方法1. RequestDispatcher.forward()界面跳转 HttpSession session =request.getSession(); Object obj = session.getAttribute (LoginConstants.LOGIN_USER); if (null !=..._servlet 返回值
文章浏览阅读1.8w次。package mainimport ( "fmt" "strings")func main() { fmt.Println("Hello, 世界") var s string s = "333," strings.TrimRight(s, ",") fmt.Println(s) s = strings.TrimRight(s, ",") fmt.Println(s)..._golang 取字符串最后一个元素
文章浏览阅读2.2k次。出现原因我在build游戏时发现没有安装WebGLbuild工具,安装的同时在buildPC版,unity崩了,我强退。解决方法此项目里的内容已损坏,GG,新建个项目,导入资源包。可能是出BUG了,发现从unity中open还是打不开。show in explorer,从资源管理器中打开,成功。..._unity报错把hierarschy没了
文章浏览阅读2k次,点赞7次,收藏21次。而对于字符数组scanf("%s",数组名)来说,我要输入字符串的话,就不需要“&”,因为你输入的字符串会自动寻址,依次存入。但是如果你用的是单个字符的话scanf("%c",&数组名[下标]),就需要添加“&”,因为得寻址,依次添加即可。int数组,是scanf("%d",&数组名[下标]),&寻址符号,在它的后面添加变量,意思是找到变量的地址然后依次进行存储。_数组输入要加&吗
文章浏览阅读1.2k次。十九、EF框架(Entity FrameWork Core框架)_ef框架