商品服务-品牌管理基础功能
1. 页面展示
- 直接使用renren-fast逆向生成代码。将vue组件复制到对应位置。
显示效果:

修改权限,先将权限检查功能关闭。(不然不显示增加和删除按钮)
- 在
src-utils-index.js中修改
/**
* 是否有权限
* @param {*} key
*/
export function isAuth (key) {
// return JSON.parse(sessionStorage.getItem('permissions') || '[]').indexOf(key) !== -1 || false
return true;
}
关闭es6语法检索。(每次启动都报错)
- 在
build-webpack.base.conf.js中修改。
const createLintingRule = () => ({
// test: /\.(js|vue)$/,
// loader: 'eslint-loader',
// enforce: 'pre',
// include: [resolve('src'), resolve('test')],
// options: {
// formatter: require('eslint-friendly-formatter'),
// emitWarning: !config.dev.showEslintErrorsInOverlay
// }
})
1.1 效果优化与快速选择开关
element ui与表格相关内容:https://element.eleme.cn/#/zh-CN/component/table
显示状态为
Switch 开关形式
:active-value="1"激活(绿色)时是1(和数据库保持一致)。使用:进行双向绑定时,冒号里面是对象。即数字1。而不是字符串1。@change="updateBrandStatus(scope.row)。将该行所有数据传递给函数。
<el-table-column prop="showStatus" header-align="center" align="center" label="显示状态">
<template slot-scope="scope">
<!-- 传递该行的所有信息@change="updateBrandStatus(scope.row) -->
<el-switch v-model="scope.row.showStatus" active-color="#13ce66" inactive-color="#ff4949" :active-value="1" :inactive-value="0" @change="updateBrandStatus(scope.row)">
</el-switch>
</template>
</el-table-column>
- 方法体获取需要传递给后端的
brandId和showStatus。
updateBrandStatus(data) {
//解构获取需要的两个值
let {brandId,showStatus}=data;
//后台发送修改信息。
this.$http({
url: this.$http.adornUrl('/product/brand/update'),
method: 'post',
data: this.$http.adornData({brandId,showStatus}, false)
}).then(({ data }) => {
this.$message({
type:"success",
message:"状态更新成功"
})
});
},
页面效果
- 打开时,数据库状态变为1。关闭时,数据库状态变为0。

点击新增时,品牌logo地址应该是文件的网络地址。表格中显示的也应该是图片。
- 使用阿里云云存储OSS存放上传的图片。并获取回调的图片url展示在表格中。


2. 云存储开通与使用
- 使用阿里云云存储来存储项目需要的文件,按量收费。

开通OSS对象服务

2.1 SpringCloud Alibaba-OSS 简介
对象存储服务(Object Storage Service,OSS)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。
专业术语:
| 中文 | 英文 | 说明 |
|---|---|---|
| 存储空间 | Bucket | 存储空间是您用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间。 |
| 对象/文件 | Object | 对象是 OSS 存储数据的基本单元,也被称为OSS的文件。对象由元信息(Object Meta)、用户数据(Data)和文件名(Key)组成。对象由存储空间内部唯一的Key来标识。 |
| 地域 | Region | 地域表示 OSS 的数据中心所在物理位置。您可以根据费用、请求来源等综合选择数据存储的地域。详情请查看OSS已经开通的Region。 |
| 访问域名 | Endpoint | Endpoint 表示OSS对外服务的访问域名。OSS以HTTP RESTful API的形式对外提供服务,当访问不同地域的时候,需要不同的域名。通过内网和外网访问同一个地域所需要的域名也是不同的。具体的内容请参见各个Region对应的Endpoint。 |
| 访问密钥 | AccessKey | AccessKey,简称 AK,指的是访问身份验证中用到的AccessKeyId 和AccessKeySecret。OSS通过使用AccessKeyId 和AccessKeySecret对称加密的方法来验证某个请求的发送者身份。AccessKeyId用于标识用户,AccessKeySecret是用户用于加密签名字符串和OSS用来验证签名字符串的密钥,其中AccessKeySecret 必须保密。 |
本项目采用服务端签名后直传方式上传文件。
- 阿里云OSS账号和密码保存在服务器。
- 浏览器上传文件,找服务器要一个签名。(包含账号和密码加密值)。将文件和签名发给阿里云OSS服务。阿里云对签名进行验证。验证通过,同意上传。
- 这样做的好处:避免账号密码泄露。节省文件上传带宽(文件不用经过服务器。直接由浏览器上传给OSS)。

新建一个bucket(存储空间),选择需要功能。低频访问和公共读。

2.2 使用Java SDK操作OSS(测试)
SDK介绍:https://help.aliyun.com/document_detail/32009.html
1.导入依赖
- 在common服务中导入。其他服务都需要该依赖。
- 实际项目需要将该依赖存放在一个单独的用来管理第三方服务。
<!--OSS文件上传依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
</dependency>
- 创建阿里云账号子账户
- 不能直接使用阿里云账号来授权给OSS使用。权限过大,有风险。
- 新建一个子账号。该账号只能使用OSS服务。且只能通过API调用使用(勾选)。

- 对该账号授权
- 管理对象存储服务(OSS)权限。
- 包括读和写权限。

- 在product服务编写配置文件
- 测试使用,实际配置文件都应该存在第三方服务中。
spring:
cloud:
alicloud:
access-key: LTAI5tFxxxxxxxxxxxxx
secret-key: 0J0heLwByxxxxxxxxxxxxxxxxx
oss:
endpoint: oss-cn-beijing.aliyuncs.com
- 编写测试方法
- 记得添加注解
@RunWith(SpringRunner.class)
@RunWith(SpringRunner.class)
@SpringBootTest
public class GulimallProductApplicationTests {
@Autowired
BrandService brandService;
@Autowired
OSSClient ossClient;
@Test
public void testUpload() throws FileNotFoundException {
FileInputStream inputStream = new FileInputStream("F:\\文件\\照片\\极简壁纸\\bcfe1a09ed9.jpg");
ossClient.putObject("cxnph","bcfe1a09ed9.jpg",inputStream);
ossClient.shutdown();
System.out.println("上传完成");
}
}
- 阿里云上传效果展示

2.3 使用Java SDK操作OSS(正式)
之后有许多第三方服务。新建一个springboot工程,统一用来管理这些第三方服务。

2.3.1 引入依赖
- 三方服务暂时不需要数据配置。引入gulimall-common时排除mybatis-plus依赖。
<dependency>
<groupId>com.atguigu.gulimall</groupId>
<artifactId>gulimall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--OSS文件上传依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.3.2 添加依赖管理配置
介绍:
- Maven中的dependencyManagement元素提供了一种管理依赖版本号的方式。
- 在dependencyManagement元素中声明所依赖的jar包的版本号等信息,那么所有子项目再次引入此依赖jar包时则无需显式的列出版本号。
- Maven会沿着父子层级向上寻找拥有dependencyManagement 元素的项目,然后使用它指定的版本号
优点:
- 如果有多个子项目都引用同一样依赖,则可以避免在每个使用的子项目里都声明一个版本号。
- 当想升级或切换到另一个版本时,只需要在顶层父容器里更新,而不需要逐个修改子项目。
- 如果某个子项目需要另外的一个版本,只需要声明version即可。
注意事项:
- dependencyManagement中定义的只是依赖的声明,并不实现引入,因此子项目需要显式的声明需要用的依赖。
由于其他服务基本上都需要引用第三方服务。所以在该服务中添加依赖管理配置。
- spring-cloud和alibaba-cloud
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
<spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.3.3 配置nacos配置中心
nacos新建命名空间,第三方配置放在该命名空间下

bootstrap.properties
spring.application.name=gulimall-third-party
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=f085e776-8540-4715-87c5-7da63183a98a
2.3.4 配置nacos注册中心
access-key等应该是在配置中心配置。为了开发方便,先在yml中配置。
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
alicloud:
access-key: LTAI5tFxxxxxxxxxxxxx
secret-key: 0J0heLwByxxxxxxxxxxxxxxxxx
oss:
endpoint: oss-cn-beijing.aliyuncs.com
application:
name: gulimall-third-party
server:
port: 30000
logging:
level:
com.atguigu.gulimall: debug
2.3.5 开启服务发现注解
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallThirdPartyApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallThirdPartyApplication.class, args);
}
}
启动测试,看服务在nacos有没有启动
- 服务启动成功,在nacos能发现该服务。
2.3.6 在该服务(第三方服务)进行上传测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class GulimallThirdPartyApplicationTests {
@Autowired
OSSClient ossClient;
@Test
public void testUpload() throws FileNotFoundException {
FileInputStream inputStream = new FileInputStream("F:\\文件\\照片\\极简壁纸\\bcfe1a09ed9.jpg");
ossClient.putObject("xxxxx","bcfe1a09ed9.jpg",inputStream);
ossClient.shutdown();
System.out.println("上传完成");
}
}
2.4 服务端签名后直传具体实现

2.4.1 ossControlle获取文件上传签名请求
- 新建一个ossController,用来给浏览器获取文件上传签名。将结果封装在data中。
@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(){
String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
// 用户上传文件时指定的前缀。以日期为文件夹。每一天新建一个文件夹,存放图片
String dir = format+"/";
// 创建OSSClient实例。
Map<String, String> respMap=null;
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 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());
} finally {
ossClient.shutdown();
}
return R.ok().put("data",respMap);
}
}
2.4.2 配置bucket
yml配置(第三方服务)
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
alicloud:
access-key: LTAI5tFdYPxxxxxxxxxxxxxx
secret-key: 0J0heLwByD2Jxxxxxxxxxxxxxx
oss:
endpoint: oss-cn-beijing.aliyuncs.com
bucket: xxxxx
2.4.3 配置网关
- 编写controller之后,向
localhost:30000/oss/policy发送请求即可获取签名数据。 - 所有请求都需要交给网关处理。所以需要在网关进行路径映射。
- id: third_party_router
uri: lb://gulimall-third-party
# 前端请求都是/api开头的。都转给renren-fast服务
predicates:
- Path=/api/thirdparty/**
# 目前请求:http://localhost:88/api/thirdparty/oss/policy
# 实际需要:http://localhost:30000/oss/policy
filters:
- RewritePath=/api/thirdparty/(?<segment>.*),/$\{segment}
2.4.4 请求测试
给网关
http://localhost:88/api/thirdparty/oss/policy发请求测试
- 成功获取签名数据。

2.5 结合前端实现单文件上传
- 编写一个单文件上传组件
singleUpload.vue。并将其对外暴露。 - 在
brand-add-or-update.vue组件中引用该组件。
2.5.1 点击新增按钮
- 点击新增按钮,调用单击函数
addOrUpdateHandle()。 this.addOrUpdateVisible = true打开新增页面。
<el-button v-if="isAuth('product:brand:save')" type="primary" @click="addOrUpdateHandle()">新增</el-button>
import AddOrUpdate from "./brand-add-or-update";
export default {
data() {
return {
addOrUpdateVisible: false,
};
},
components: {
AddOrUpdate,
},
}
addOrUpdateHandle(id) {
this.addOrUpdateVisible = true;
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id);
});
},
2.5.2 点击上传按钮
- 调用
SingleUpload组件。 - 将组件绑定
dataForm.logo值。获取文件上传后的url。
<el-form-item label="品牌logo地址" prop="logo">
<single-upload v-model="dataForm.logo"></single-upload>
</el-form-item>
import SingleUpload from "../../../components/upload/singleUpload.vue";
export default {
components: { SingleUpload: SingleUpload },
}
2.5.3 文件上传实现
<template>
<div>
<!-- 替换自己的oss bucket域名地址 -->
<el-upload
action="http://xxxxx.oss-cn-beijing.aliyuncs.com"
:data="dataObj"
list-type="picture"
:multiple="false" :show-file-list="showFileList"
:file-list="fileList"
:before-upload="beforeUpload"
:on-remove="handleRemove"
:on-success="handleUploadSuccess"
:on-preview="handlePreview">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过10MB</div>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="fileList[0].url" alt="">
</el-dialog>
</div>
</template>
文件上传前获取签名
- 获取前面,将后端获取的
data中的值保存在_self.dataObj中。
beforeUpload(file) {
let _self = this;
return new Promise((resolve, reject) => {
policy().then(response => {
console.log("响应数据",response);
_self.dataObj.policy = response.data.policy;
_self.dataObj.signature = response.data.signature;
_self.dataObj.ossaccessKeyId = response.data.accessid;
_self.dataObj.key = response.data.dir +getUUID()+'_${filename}';
_self.dataObj.dir = response.data.dir;
_self.dataObj.host = response.data.host;
resolve(true)
}).catch(err => {
reject(false)
})
})
},
向后端发请求获取签名值
policy.js
import http from '@/utils/httpRequest.js'
export function policy() {
return new Promise((resolve,reject)=>{
http({
url: http.adornUrl("/thirdparty/oss/policy"),
method: "get",
params: http.adornParams({})
}).then(({ data }) => {
resolve(data);
})
});
}
前面获取后的操作。
- 获取拼接url路径地址。(即该图片上传的网络路径url)
- 父组件可以使用 props 把数据传给子组件。
- 子组件可以使用 $emit,让父组件监听到自定义事件。(给父组件传递url值。)
emitInput(val) {
this.$emit('input', val)
},
handleUploadSuccess(res, file) {
console.log("上传成功...")
this.showFileList = true;
this.fileList.pop();
//关键代码。
this.fileList.push({name: file.name, url: this.dataObj.host + '/' + this.dataObj.key.replace("${filename}",file.name) });
this.emitInput(this.fileList[0].url);
}
2.5.4 文件上传测试
上传一张图片进行测试。发现跨域问题。

2.6 解决跨域问题
在阿里云OSS上配置跨域问题。(正式环境要配置来源,不能配置*)

再次上传设置,图片成功上传并回显到该页面


浙公网安备 33010602011771号