学习目标:
在代码生成器中,生成品牌相关的表到service-product
商品微服务模块,相关表名称如下
需求:
YAPI接口地址:http://192.168.200.128:3000/project/11/interface/api/371
package com.atguigu.gmall.product.controller;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.product.model.BaseTrademark;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.atguigu.gmall.product.service.BaseTrademarkService;
import org.springframework.web.bind.annotation.RestController;
/**
* 品牌表 前端控制器
*
* @author atguigu
* @since 2022-12-24
*/
@Api(tags = "品牌表控制器")
@RestController
@RequestMapping("/admin/product/baseTrademark")
public class BaseTrademarkController {
@Autowired
private BaseTrademarkService baseTrademarkService;
/**
* 品牌分页查询
* @param page
* @param limit
* @return
*/
@GetMapping("/baseTrademark/{page}/{limit}")
public Result getBaseTrademarkByPage(@PathVariable("page") Long page, @PathVariable("limit") Long limit){
//封装MP分页对象-封装页码 页大小
IPage<BaseTrademark> iPage = new Page<>(page, limit);
//调用业务逻辑进行分页查询封装其他数据
iPage = baseTrademarkService.getBaseTrademarkByPage(iPage);
return Result.ok(iPage);
}
}
package com.atguigu.gmall.product.service;
import com.atguigu.gmall.product.model.BaseTrademark;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* 品牌表 业务接口类
* @author atguigu
* @since 2022-12-24
*/
public interface BaseTrademarkService extends IService<BaseTrademark> {
/**
* 品牌分页查询
* @param iPage
* @return
*/
IPage<BaseTrademark> getBaseTrademarkByPage(IPage<BaseTrademark> iPage);
}
package com.atguigu.gmall.product.service.impl;
import com.atguigu.gmall.base.model.BaseEntity;
import com.atguigu.gmall.product.model.BaseTrademark;
import com.atguigu.gmall.product.mapper.BaseTrademarkMapper;
import com.atguigu.gmall.product.service.BaseTrademarkService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* 品牌表 业务实现类
*
* @author atguigu
* @since 2022-12-24
*/
@Service
public class BaseTrademarkServiceImpl extends ServiceImpl<BaseTrademarkMapper, BaseTrademark> implements BaseTrademarkService {
/**
* 品牌分页查询
*
* @param iPage
* @return
*/
@Override
public IPage<BaseTrademark> getBaseTrademarkByPage(IPage<BaseTrademark> iPage) {
//分页条件
LambdaQueryWrapper<BaseTrademark> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.orderByDesc(BaseTrademark::getUpdateTime);
//调用业务层或者持久层对象分页方法
return this.page(iPage, queryWrapper);
}
}
package com.atguigu.gmall.product.mapper;
import com.atguigu.gmall.product.model.BaseTrademark;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface BaseTrademarkMapper extends BaseMapper<BaseTrademark> {
}
BaseTrademarkController 中完成品牌的增删改查,调用公共业务接口方法即可。
package com.atguigu.gmall.product.controller;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.product.model.BaseTrademark;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.atguigu.gmall.product.service.BaseTrademarkService;
import org.springframework.web.bind.annotation.RestController;
/**
* 品牌表 前端控制器
*
* @author atguigu
* @since 2022-12-24
*/
@Api(tags = "品牌表控制器")
@RestController
@RequestMapping("/admin/product/baseTrademark")
public class BaseTrademarkController {
@Autowired
private BaseTrademarkService baseTrademarkService;
/**
* 品牌保存
* @param baseTrademark
* @return
*/
@PostMapping("/baseTrademark/save")
public Result saveBaseTrademark(@RequestBody BaseTrademark baseTrademark){
baseTrademarkService.save(baseTrademark);
return Result.ok();
}
/**
* 根据品牌ID查询品牌信息
* @param id
* @return
*/
@GetMapping("/baseTrademark/get/{id}")
public Result getBaseTrademarkById(@PathVariable("id") Long id){
BaseTrademark baseTrademark = baseTrademarkService.getById(id);
return Result.ok(baseTrademark);
}
/**
* 更新品牌
* @param baseTrademark
* @return
*/
@PutMapping("/baseTrademark/update")
public Result updateBaseTrademark(@RequestBody BaseTrademark baseTrademark){
baseTrademarkService.updateById(baseTrademark);
return Result.ok();
}
/**
* 删除品牌
* @param id
* @return
*/
@DeleteMapping("/baseTrademark/remove/{id}")
public Result deleteBaseTrademarkById(@PathVariable("id") Long id){
baseTrademarkService.removeById(id);
return Result.ok();
}
}
YAPI接口地址:
package com.atguigu.gmall.product.controller;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.product.model.BaseTrademark;
import com.atguigu.gmall.product.model.CategoryTrademarkVo;
import com.atguigu.gmall.product.service.BaseCategoryTrademarkService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import org.apache.ibatis.annotations.Delete;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.atguigu.gmall.product.service.BaseTrademarkService;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 品牌表 前端控制器
*
* @author atguigu
* @since 2023-02-22
*/
@Api(tags = "品牌表控制器")
@RestController
@RequestMapping("/admin/product")
public class BaseTrademarkController {
@Autowired
private BaseTrademarkService baseTrademarkService;
@Autowired
private BaseCategoryTrademarkService baseCategoryTrademarkService;
/**
* 根据category3Id获取品牌列表
*
* @param category3Id
* @return
*/
@GetMapping("/baseCategoryTrademark/findTrademarkList/{category3Id}")
public Result getTrademarkListByCategoryId(@PathVariable("category3Id") Long category3Id) {
List<BaseTrademark> list = baseTrademarkService.getTrademarkListByCategoryId(category3Id);
return Result.ok(list);
}
/**
* 根据分类ID查询该分类未关联品牌
*
* @param category3Id 三级分类ID
* @return
*/
@GetMapping("/baseCategoryTrademark/findCurrentTrademarkList/{category3Id}")
public Result getCurrentTrademarkList(@PathVariable("category3Id") Long category3Id) {
List<BaseTrademark> list = baseTrademarkService.getCurrentTrademarkList(category3Id);
return Result.ok(list);
}
/**
* 将品牌关联到分类
*
* @param vo
* @return
*/
@PostMapping("/baseCategoryTrademark/save")
public Result saveCategoryTrademark(@RequestBody CategoryTrademarkVo vo) {
baseCategoryTrademarkService.saveCategoryTrademark(vo);
return Result.ok();
}
/**
* 解除品牌分类关联
* @param category3Id
* @param trademarkId
* @return
*/
@DeleteMapping("/baseCategoryTrademark/remove/{category3Id}/{trademarkId}")
public Result deleteCategoryTrademark(@PathVariable("category3Id") Long category3Id, @PathVariable("trademarkId") Long trademarkId){
baseCategoryTrademarkService.deleteCategoryTrademark(category3Id, trademarkId);
return Result.ok();
}
}
package com.atguigu.gmall.product.service;
import com.atguigu.gmall.product.model.BaseTrademark;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* 品牌表 业务接口类
* @author atguigu
* @since 2023-02-22
*/
public interface BaseTrademarkService extends IService<BaseTrademark> {
/**
* 根据category3Id获取品牌列表
* @param category3Id
* @return
*/
List<BaseTrademark> getTrademarkListByCategoryId(Long category3Id);
/**
* 根据分类ID查询该分类未关联品牌
* @param category3Id 三级分类ID
* @return
*/
List<BaseTrademark> getCurrentTrademarkList(Long category3Id);
}
package com.atguigu.gmall.product.service;
import com.atguigu.gmall.product.model.BaseCategoryTrademark;
import com.atguigu.gmall.product.model.CategoryTrademarkVo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* 分类品牌中间表 业务接口类
* @author atguigu
* @since 2023-02-22
*/
public interface BaseCategoryTrademarkService extends IService<BaseCategoryTrademark> {
/**
* 将品牌关联到分类
* @param vo
* @return
*/
void saveCategoryTrademark(CategoryTrademarkVo vo);
/**
* 解除品牌分类关联
* @param category3Id
* @param trademarkId
* @return
*/
void deleteCategoryTrademark(Long category3Id, Long trademarkId);
}
package com.atguigu.gmall.product.service.impl;
import com.atguigu.gmall.product.mapper.BaseTrademarkMapper;
import com.atguigu.gmall.product.model.BaseCategoryTrademark;
import com.atguigu.gmall.product.mapper.BaseCategoryTrademarkMapper;
import com.atguigu.gmall.product.model.BaseTrademark;
import com.atguigu.gmall.product.model.CategoryTrademarkVo;
import com.atguigu.gmall.product.service.BaseCategoryTrademarkService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 分类品牌中间表 业务实现类
*
* @author atguigu
* @since 2022-12-24
*/
@Service
public class BaseCategoryTrademarkServiceImpl extends ServiceImpl<BaseCategoryTrademarkMapper, BaseCategoryTrademark> implements BaseCategoryTrademarkService {
@Autowired
private BaseTrademarkMapper baseTrademarkMapper;
/**
* 查询分类下关联的品牌列表
*
* @param category3Id 三级分类ID
* @return
*/
@Override
public List<BaseTrademark> findTrademarkList(Long category3Id) {
//1.根据分类ID查询 分类品牌关系表得到分类品牌集合
LambdaQueryWrapper<BaseCategoryTrademark> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(BaseCategoryTrademark::getCategory3Id, category3Id);
List<BaseCategoryTrademark> baseCategoryTrademarks = super.list(queryWrapper);
//2.获取分类品牌集合中品牌ID集合
if (!CollectionUtils.isEmpty(baseCategoryTrademarks)) {
//采用Stream流处理集合 将集合对象中 品牌ID 获取 转为品牌ID集合
List<Long> trademardIdList = baseCategoryTrademarks.stream().map(BaseCategoryTrademark::getTrademarkId).collect(Collectors.toList());
//3.根据品牌ID集合查询品牌列表
List<BaseTrademark> baseTrademarkList = baseTrademarkMapper.selectBatchIds(trademardIdList);
return baseTrademarkList;
}
return null;
}
/**
* 查询当前分类可选品牌列表
*
* @param category3Id 三级分类ID
* @return
*/
@Override
public List<BaseTrademark> findCurrentTrademarkList(Long category3Id) {
//调用持久层方法执行自定义SQL得到可选品牌列表
List<BaseTrademark> list = baseTrademarkMapper.findCurrentTrademarkList(category3Id);
return list;
}
/**
* 将品牌关联到分类
*
* @param categoryTrademarkVo
* @return
*/
@Override
public void saveBasecategoryTrademark(CategoryTrademarkVo categoryTrademarkVo) {
//1.获取品牌ID集合
List<Long> trademarkIdList = categoryTrademarkVo.getTrademarkIdList();
//2.遍历品牌ID集合构建品牌分类中间对象 执行新增
if (!CollectionUtils.isEmpty(trademarkIdList)) {
//采用Stream流将集合泛型 由 Long 转为 BaseCategoryTrademark
List<BaseCategoryTrademark> baseCategoryTrademarkList = trademarkIdList.stream().map(tmId -> {
BaseCategoryTrademark baseCategoryTrademark = new BaseCategoryTrademark();
baseCategoryTrademark.setTrademarkId(tmId);
baseCategoryTrademark.setCategory3Id(categoryTrademarkVo.getCategory3Id());
return baseCategoryTrademark;
}).collect(Collectors.toList());
//执行当前关系业务父类中方法 批量保存
super.saveBatch(baseCategoryTrademarkList);
}
}
/**
* 删除分类品牌关联
*
* @param category3Id
* @param trademarkId
*/
@Override
public void removeCategoryTrademark(Long category3Id, Long trademarkId) {
//方式一:逻辑删除
//LambdaQueryWrapper<BaseCategoryTrademark> queryWrapper = new LambdaQueryWrapper<>();
//queryWrapper.eq(BaseCategoryTrademark::getCategory3Id, category3Id);
//queryWrapper.eq(BaseCategoryTrademark::getTrademarkId, trademarkId);
//super.remove(queryWrapper);
//方式二:执行物理删除
baseMapper.removeCategoryTrademark(category3Id, trademarkId);
}
}
package com.atguigu.gmall.product.mapper;
import com.atguigu.gmall.product.model.BaseTrademark;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 品牌表 Mapper 接口
*
* @author atguigu
* @since 2023-02-22
*/
public interface BaseTrademarkMapper extends BaseMapper<BaseTrademark> {
List<BaseTrademark> getCurrentTrademarkList(@Param("category3Id") Long category3Id);
}
package com.atguigu.gmall.product.mapper;
import com.atguigu.gmall.product.model.BaseCategoryTrademark;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.*;
/**
* 分类品牌中间表 Mapper 接口
*
* @author atguigu
* @since 2023-02-22
*/
public interface BaseCategoryTrademarkMapper extends BaseMapper<BaseCategoryTrademark> {
//@Select()
//@Update()
//@Insert()
@Delete("DELETE FROM base_category_trademark bct where bct.category3_id=#{category3Id} and bct.trademark_id = #{trademarkId}")
void deleteCategoryTrademark(@Param("category3Id") Long category3Id, @Param("trademarkId") Long trademarkId);
}
自定义SQL
BaseTrademarkMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.gmall.product.mapper.BaseTrademarkMapper">
<!--查询该分类下未关联分类的品牌列表-->
<select id="getCurrentTrademarkList" resultType="com.atguigu.gmall.product.model.BaseTrademark">
SELECT bt.id,
bt.tm_name,
bt.logo_url
FROM base_trademark bt
LEFT JOIN (SELECT *
FROM base_category_trademark bct
WHERE bct.is_deleted = '0' AND bct.category3_id = #{category3Id}) t1
ON bt.id = t1.trademark_id
WHERE t1.id IS NULL
</select>
</mapper>
销售属性,就是商品详情页右边,可以通过销售属性来定位一组spu下的哪款sku。
因此,在制作spu之前要先确定当前商品有哪些销售属性!
YAPI接口地址:http://192.168.200.128:3000/project/11/interface/api/187
在代码生成器中,生成商品SPU相关的表基础代码到service-product
商品微服务模块,相关表名称如下
但是这里我们不建议生成以上相关表三层类,这样同时生成的三层类过于多,而以上的6张表都跟商品SPU相关,故建议只提供对应的实体类跟持久层接口。业务层/持久层我们提供一个抽取SpuManagerXxx
注意:在mybatis-plus-code
代码生成器模块中CodeGenerator
设置禁用模板来达到目标
package com.atguigu.gmall.product.controller;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.product.model.SpuInfo;
import com.atguigu.gmall.product.service.SpuManageService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author: atguigu
* @create: 2022-12-24 14:11
*/
@RestController
@RequestMapping("/admin/product")
public class SpuManageController {
@Autowired
private SpuManageService spuManageService;
/**
* 分页查询商品Spu列表
*
* @param page
* @param size
* @return
*/
@GetMapping("/{page}/{size}")
public Result getSpuListByPage(@PathVariable("page") Long page,
@PathVariable("size") Long size,
@RequestParam(value = "category3Id") Long category3Id) {
//1.封装分页对象Page
Page<SpuInfo> iPage = new Page<>(page, size);
//2.调用业务层完成分页查询
iPage = spuManageService.getSpuListByPage(iPage, category3Id);
return Result.ok(iPage);
}
}
package com.atguigu.gmall.product.service;
import com.atguigu.gmall.product.model.SpuInfo;
import com.baomidou.mybatisplus.core.metadata.IPage;
public interface SpuManageService {
/**
* 分页查询商品SPU列表
*
* @param iPage
* @param category3Id
* @return
*/
Page<SpuInfo> getSpuListByPage(Page<SpuInfo> iPage, Long category3Id);
}
package com.atguigu.gmall.product.service.impl;
import com.atguigu.gmall.product.model.SpuInfo;
import com.atguigu.gmall.product.service.SpuInfoService;
import com.atguigu.gmall.product.service.SpuManageService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author: atguigu
* @create: 2023-02-22 11:52
*/
@Service
public class SpuManageServiceImpl implements SpuManageService {
@Autowired
private SpuInfoService spuInfoService;
/**
* 根据分类查询商品SPU列表
*
* @param iPage
* @param category3Id
* @return
*/
@Override
public Page<SpuInfo> getSpuListByPage(Page<SpuInfo> iPage, Long category3Id) {
//1.构建查询查询 排序
LambdaQueryWrapper<SpuInfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SpuInfo::getCategory3Id, category3Id);
queryWrapper.orderByDesc(SpuInfo::getUpdateTime);
//2.执行分页查询
iPage = spuInfoService.page(iPage, queryWrapper);
return iPage;
}
}
package com.atguigu.gmall.product.mapper;
import com.atguigu.gmall.product.model.SpuInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface SpuInfoMapper extends BaseMapper<SpuInfo> {
}
MinIO 是一个基于Apache License v3.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
官方文档:http://docs.minio.org.cn/docs 旧一点 中文
https://docs.min.io/ 新 英文
· 高性能:作为高性能对象存储,在标准硬件条件下它能达到55GB/s的读、35GB/s的写速率
· 可扩容:不同MinIO集群可以组成联邦,并形成一个全局的命名空间,并跨越多个数据中心
· 云原生:容器化、基于K8S的编排、多租户支持
· Amazon S3兼容:Minio使用Amazon S3 v2 / v4 API。可以使用Minio SDK,Minio Client,AWS SDK和AWS CLI访问Minio服务器。
· 可对接后端存储: 除了Minio自己的文件系统,还支持DAS、 JBODs、NAS、Google云存储和Azure Blob存储。
· SDK支持: 基于Minio轻量的特点,它得到类似Java、Python或Go等语言 的sdk支持
· Lambda计算: Minio服务器通过其兼容AWS SNS / SQS的事件通知服务触发Lambda功能。支持的目标是消息队列,如Kafka,NATS,AMQP,MQTT,Webhooks以及Elasticsearch,Redis,Postgres和MySQL等数据库。
· 有操作页面
· 功能简单: 这一设计原则让MinIO不容易出错、更快启动
· 支持纠删码:MinIO使用纠删码、Checksum来防止硬件错误和静默数据污染。在最高冗余度配置下,即使丢失1/2的磁盘也能恢复数据!
Minio使用纠删码erasure code和校验和checksum。 即便丢失一半数量(N/2)的硬盘,仍然可以恢复数据。纠删码是一种恢复丢失和损坏数据的数学算法。
docker pull minio/minio
docker run
-p 9000:9000
-p 9001:9001
--name minio
-d --restart=always
-e "MINIO_ROOT_USER=admin"
-e "MINIO_ROOT_PASSWORD=admin123456"
-v /home/data:/data
-v /home/config:/root/.minio
minio/minio server /data --console-address ":9001"
浏览器访问:http://IP:9001/minio/login,如图:
登录账户说明:安装时指定了登录账号:admin/admin123456
注意:文件上传时,需要调整一下linux 服务器的时间与windows 时间一致!
第一步:安装ntp服务 yum -y install ntp
第二步:开启开机启动服务 systemctl enable ntpd
第三步:启动服务 systemctl start ntpd
第四步:更改时区 timedatectl set-timezone Asia/Shanghai
第五步:启用ntp同步 timedatectl set-ntp yes
第六步:同步时间 ntpq -p
定时自动同步
echo "*/2 * * * * /usr/sbin/ntpdate us.pool.ntp.org | logger -t NTP" >> /tmp/crontab.bak
crontab /tmp/crontab.bak
参考文档:https://docs.min.io/docs/java-client-api-reference.html
在service-product
模块中添加依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.0</version>
</dependency>
在nacos 配置中心列表中的service-product-dev.yaml
增加以下信息!
minio:
endpointUrl: http://192.168.200.128:9000
accessKey: admin
secreKey: admin123456
bucketName: gmall
在service-product
模块中新建config包 提供配置类注册客户端对象
package com.atguigu.gmall.product.config;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author: atguigu
* @create: 2023-04-18 15:19
*/
@Configuration
public class MinIOConfig {
@Value("${minio.endpointUrl}")
private String endpointUrl;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secreKey}")
private String secreKey;
@Bean
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpointUrl)
.credentials(accessKey, secreKey)
.build();
}
}
YAPI接口地址:http://192.168.200.128:3000/project/11/interface/api/427
package com.atguigu.gmall.product.controller;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.product.service.FileUploadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* @author: atguigu
* @create: 2023-04-18 15:14
*/
@RestController
@RequestMapping("/admin/product")
public class FileUploadController {
@Autowired
private FileUploadService fileUploadService;
/**
* 将文件/图片上传到MinIO中
* @param file
* @return
*/
@PostMapping("/fileUpload")
public Result fileUpload(MultipartFile file){
String url = fileUploadService.fileUpload(file);
return Result.ok(url);
}
}
package com.atguigu.gmall.product.service;
import org.springframework.web.multipart.MultipartFile;
public interface FileUploadService {
/**
* 图片上传
* @param file
* @return
*/
String fileUpload(MultipartFile file);
}
package com.atguigu.gmall.product.service.impl;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.product.service.FileUploadService;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.util.Date;
import java.util.UUID;
/**
* @author: atguigu
* @create: 2023-04-18 15:16
*/
@Service
public class FileUploadServiceImpl implements FileUploadService {
@Autowired
private MinioClient minioClient;
@Value("${minio.bucketName}")
private String bucketName;
@Value("${minio.endpointUrl}")
private String endpointUrl;
/**
* 将图片上传到Minor获取上传后文件在线地址用于前端展示图片
*
* @param file
* @return
*/
@Override
public String fileUpload(MultipartFile file) {
try {
//todo 创建存储空间 下发虚拟机中包含gmall存储空间 切记保证该存储空间 访问权限设置Public
boolean found =
minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (!found) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket("asiatrip").build());
}
//1.构建新上传文件 文件对象标识 UUID+时间戳构成 /a/a.png
//1.1 获取文件后缀
String extName = StringUtils.substringAfterLast(file.getOriginalFilename(), ".");
//1.2 封装上传后文件名称
String fileName = DateUtil.formatDate(new Date()) + "/" +
UUID.randomUUID().toString()
.replaceAll("-", "") + "." + extName;
//2.调用Minioclient对象方法完成文件上传
minioClient.putObject(
PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build()
);
//3.拼接上传后文件地址即可
return endpointUrl + "/" + bucketName + "/" + fileName;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
需求:在添加SPU商品需要选择当前商品的销售属性
YAPI接口地址:http://192.168.200.128:3000/project/11/interface/api/307
package com.atguigu.gmall.product.controller;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.product.service.BaseSaleAttrService;
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;
/**
* @author: atguigu
* @create: 2023-02-22 15:34
*/
@RestController
@RequestMapping("/admin/product")
public class BaseSaleAttrController {
@Autowired
private BaseSaleAttrService baseSaleAttrService;
/**
* 查询平台所有的销售属性名称
* @return
*/
@GetMapping("/baseSaleAttrList")
public Result getBaseSaleAttrList(){
return Result.ok(baseSaleAttrService.list());
}
}
package com.atguigu.gmall.product.mapper;
import com.atguigu.gmall.product.model.BaseSaleAttr;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface BaseSaleAttrMapper extends BaseMapper<BaseSaleAttr> {
}
YAPI接口地址:http://192.168.200.128:3000/project/11/interface/api/171
BaseCategoryTrademarkController 完成
YAPI接口地址:http://192.168.200.128:3000/project/11/interface/api/219
/**
* 保存商品SPU信息
* @param spuInfo
* @return
*/
@PostMapping("/saveSpuInfo")
public Result saveSpuInfo(@RequestBody SpuInfo spuInfo){
spuManageService.saveSpuInfo(spuInfo);
return Result.ok();
}
/**
* 保存商品SPU信息
* @param spuInfo
*/
void saveSpuInfo(SpuInfo spuInfo);
@Autowired
private SpuInfoService spuInfoService;
@Autowired
private SpuImageService spuImageService;
@Autowired
private SpuPosterService spuPosterService;
@Autowired
private SpuSaleAttrService spuSaleAttrService;
@Autowired
private SpuSaleAttrValueService spuSaleAttrValueService;
/**
* 保存商品SPU信息
* 1.将商品基本信息封装SpuInfo对象 存入spu_info表
* 2.将提交商品图片封装到SpuImage集合中 存入spu_image表
* 3.将提交海报图片封装到SpuPost集合中 存入spu_poster表
* 4.将提交销售属性名称SpuSaleAttr集合 存入spu_sale_attr表
* 5.将提交销售属性值SpuSaleAttrValue集合 存入spu_sale_attr_value表
*
* @param spuInfo
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void saveSpuInfo(SpuInfo spuInfo) {
//1.将商品基本信息封装SpuInfo对象 存入spu_info表
spuInfoService.save(spuInfo);
Long spuId = spuInfo.getId();
//2.将提交商品图片封装到SpuImage集合中 存入spu_image表
List<SpuImage> spuImageList = spuInfo.getSpuImageList();
if (!CollectionUtils.isEmpty(spuImageList)) {
spuImageList.stream().forEach(spuImage -> {
spuImage.setSpuId(spuId);
});
//批量执行保存
spuImageService.saveBatch(spuImageList);
}
//3.将提交海报图片封装到SpuPost集合中 存入spu_poster表
List<SpuPoster> spuPosterList = spuInfo.getSpuPosterList();
if (!CollectionUtils.isEmpty(spuPosterList)) {
spuPosterList.stream().forEach(spuPoster -> {
spuPoster.setSpuId(spuId);
});
spuPosterService.saveBatch(spuPosterList);
}
//4.将提交销售属性名称SpuSaleAttr集合 存入spu_sale_attr表
List<SpuSaleAttr> spuSaleAttrList = spuInfo.getSpuSaleAttrList();
if (!CollectionUtils.isEmpty(spuSaleAttrList)) {
spuSaleAttrList.stream().forEach(spuSaleAttr -> {
spuSaleAttr.setSpuId(spuId);
//5.将提交销售属性值SpuSaleAttrValue集合 存入spu_sale_attr_value表
List<SpuSaleAttrValue> spuSaleAttrValueList = spuSaleAttr.getSpuSaleAttrValueList();
if (!CollectionUtils.isEmpty(spuSaleAttrValueList)) {
spuSaleAttrValueList.stream().forEach(spuSaleAttrValue -> {
//关联商品SPUID
spuSaleAttrValue.setSpuId(spuId);
//为平台属性名称赋值
spuSaleAttrValue.setSaleAttrName(spuSaleAttr.getSaleAttrName());
});
spuSaleAttrValueService.saveBatch(spuSaleAttrValueList);
}
});
spuSaleAttrService.saveBatch(spuSaleAttrList);
}
}
建立对应的mapper 文件
package com.atguigu.gmall.product.mapper;
import com.atguigu.gmall.product.model.SpuImage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface SpuImageMapper extends BaseMapper<SpuImage> {
}
package com.atguigu.gmall.product.mapper;
import com.atguigu.gmall.product.model.SpuSaleAttr;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface SpuSaleAttrMapper extends BaseMapper<SpuSaleAttr> {
}
package com.atguigu.gmall.product.mapper;
import com.atguigu.gmall.product.model.SpuSaleAttrValue;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface SpuSaleAttrValueMapper extends BaseMapper<SpuSaleAttrValue> {
}
package com.atguigu.gmall.product.mapper;
import com.atguigu.gmall.product.model.SpuPoster;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface SpuPosterMapper extends BaseMapper<SpuPoster> {
}