谷粒商城后端项目开发

06-谷粒商城项目 人人开源快速开发 renren-fast前后端联调 逆向工程搭建&使用 这里需要注意一点,由于我使用的boot版本过于老旧,所以与cloud版本冲突了,导致我测试一直报错,等我将cloud版本回退到Greenwich.SR6后才成功测试。将我的测试代码贴到下面。 阅读详情

谷粒商城后端项目开发

1.三级分类-逻辑删除(需要mybatis-plus支持)

---->对项目进行配置(yml举例)

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: flag  # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1,全局)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0,全局)

---->实体类字段上加上@TableLogic注解

//value:默认逻辑未删除值(局部,该值可无、会自动获取全局配置)
//delval:默认逻辑删除值(局部,该值可无、会自动获取全局配置)
@TableLogic(value = "1",delval = "0")
Integer show_status;

2.商品服务-品牌管理

---->页面新增品牌管理菜单

在这里插入图片描述

3.Aliyun Spring Boot OSS文件上传

---->导入pom文件

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
</dependency>

---->access-key,secret-key获取(创建完成后记得先保存)


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

---->配置application.properties

spring.cloud.alicloud.access-key= (自己的key)
spring.cloud.alicloud.secret-key= (自己的key)
spring.cloud.alicloud.oss.endpoint= (自己的endpoint)

---->在测试类中进行测试

@Autowired
private OSSClient ossClient;

@Test
public void saveFile() throws FileNotFoundException {
        // download file to local
    FileInputStream fileInputStream = new FileInputStream("E:\\0d40c24b264aa511.jpg");
    ossClient.putObject("gulimall","0d40c24b264aa511.jpg",fileInputStream);
    ossClient.shutdown();
    System.out.println("上传成功");
}

---->在页面上确认是否上传成功

在这里插入图片描述

4.OSS获取服务端签名

---->创建gulimall-third-party微服务

---->导入common的pom并排除mybatis-plus

<dependency>
    <groupId>com.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>

---->在nacos-config中新增一个命名空间gulimall-third-party并新增oss.properties

spring.cloud.alicloud.access-key=xxxx
spring.cloud.alicloud.secret-key= xxxx
spring.cloud.alicloud.oss.endpoint= xxxx

---->创建OssController

@RestController
public class OssController {
    @Autowired
    OSS ossClient;
    @Value("${spring.cloud.alicloud.oss.bucket}")
    private String bucket;
    @Value("${spring.cloud.alicloud.oss.endpoint}")
    private String endpoint;
    @Value("${spring.cloud.alicloud.access-key}")
    private String accessId;

@RequestMapping("/oss/policy")
public Map<String,String> policy() throws Exception {
    Map<String, String> respMap= null;
    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 + "/"; // 用户上传文件时指定的前缀。
    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));
    return respMap;
	}
}

---->添加yml配置文件

spring:
  cloud:
    nacos:
      discovery:
        server-addr: xxxx:8848
    alicloud:
      access-key: xxxx
      secret-key: xxxx
      oss:
        endpoint: oss-cn-beijing.aliyuncs.com
        bucket: xxxx
  application:
    name: gulimall-third-party
server:
  port: 20000

---->修改网关配置文件

spring:
  cloud:
    gateway:
      routes:
        - id: third_party_route
          uri: lb://gulimall-third-party
          predicates:
            - Path=/api/thirdparty/**
          filters:
            - RewritePath=/api/thirdparty/(?<segment>.*),/$\{segment}

---->访问测试

localhost:88/api/thirdparty/oss/policy

5.实现文件上传

---->编写前端页面

---->参考官方文档配置并修改CORS跨域权限

https://help.aliyun.com/document_detail/31926.html?spm=a2c4g.11174283.6.1568.5fb67da2s0gRxy

https://help.aliyun.com/document_detail/91868.html?spm=a2c4g.11186623.2.15.45496e28hbo8lP#concept-ahk-rfz-2fb

---->gulimall-third-party的OssController里的policy方法以R类型返回josn串

@RequestMapping("/oss/policy")
public R policy() throws Exception {
    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;
    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));
    return R.ok().put("data",respMap);
}

---->修改前端upload下的路径

–>src/components/upload下的multiUpload,singleUpload,policy.js的
Bucket路径为自己的路径

---->上传测试

在这里插入图片描述

6.JSR303后端校验

---->给Bean添加校验注解

javax.validation.constraints,并定义自己的message提示,举例:

/**
检索首字母
*/
@NotEmpty
@Pattern(regexp = "/^[a-zA-Z]$/]",message = "检索首字母必须为字母")
private String firstLetter;

---->开启校验功能

在controller需要校验的参数前加入@Valid

效果:校验参数会有默认响应

public R save(@Valid @RequestBody BrandEntity brand, BindingResult result){}

---->给校验的bean后紧跟一个BindingResult就可以获取到校验的结果

//获取校验的错误信息
result.getFieldErrors().forEach((item)->{
//获取错误提示
String message = item.getDefaultMessage();
//获取错误的属性名字
String field = item.getField();
});

---->在postman访问测试

localhost:88/api/product/brand/save

在这里插入图片描述

7.统一异常处理

---->编写exception.GulimallExceptionControllerAdvice

@Slf4j
@RestControllerAdvice(basePackages = "接收异常的地址全类名")
public class GulimallExceptionControllerAdvice {
//value:异常类型
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleException(MethodArgumentNotValidException ex){
    BindingResult result = ex.getBindingResult();
    HashMap<String, String> map = new HashMap<>();
    result.getFieldErrors().forEach((fieldError)->{
        map.put(fieldError.getField(),fieldError.getDefaultMessage());
    });
    return R.error(BizCodeEnum.VAILD_EXCEPTION.getCode(),BizCodeEnum.VAILD_EXCEPTION.getMsg()).put("data",map);
}
} 

---->在common下创建公用枚举异常类BizCodeEnum

–>自定义所有的异常消息,异常编码。
public enum BizCodeEnum {  
	UNKNOW_EXCEPTION(10000,"系统未知异常"),  
	VAILD_EXCEPTION(10001,"参数格式校验异常");
  	private int code;  
  	private String msg;

  	BizCodeEnum(int code, String msg) {    
  		this.code = code;    
  		this.msg = msg;  
  	}
  BizCodeEnum() {  }
  public int getCode() {    return code;  }
  public void setCode(int code) {    this.code = code;  }
  public String getMsg() {    return msg;  }
  public void setMsg(String msg) {    this.msg = msg;  }}

---->测试

在这里插入图片描述

8.分组新增&级联选择器

---->在AttrGroupController里新增list方法

@RequestMapping("/list/{catelogId}")
public R list(@RequestParam Map<String, Object> params,@PathVariable("catelogId") Long catelogId){
    PageUtils page = attrGroupService.queryPage(params,catelogId);
	return R.ok().put("page", page);
}

---->创建queryPage的接口与实现类impl

@Override
public PageUtils queryPage(Map<String, Object> params, Long catelogId) {


if (catelogId == 0){
    IPage<AttrGroupEntity> page = this.page(
            new Query<AttrGroupEntity>().getPage(params),
            new QueryWrapper<AttrGroupEntity>()
    );

return new PageUtils(page);

}else {
    String key = (String) params.get("key");
    QueryWrapper<AttrGroupEntity> wrapper = new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId);
    if (!StringUtils.isEmpty(key)){
        wrapper.and((obj)->{
           obj.eq("attr_group_id","key").or().like("attr_group_name",key);
        });
    }
    IPage<AttrGroupEntity> page = this.page(new Query<AttrGroupEntity>().getPage(params),
            wrapper);
    return new PageUtils(page);
}
}

---->修改前端页面

---->在CategoryEntity增加新注解

@JsonInclude(JsonInclude.Include.NON_EMPTY)
@TableField(exist = false)
private List<CategoryEntity> children;

9.品牌分类-修改(路径回显)

---->修改Controller

@RequestMapping("/info/{attrGroupId}")
  //@RequiresPermissions("product:attrgroup:info")
  public R info(@PathVariable("attrGroupId") Long attrGroupId){
AttrGroupEntity attrGroup = attrGroupService.getById(attrGroupId);
  Long catelogId = attrGroup.getCatelogId();
  Long[] catelogPath = categoryService.findCatelogPath(catelogId);
  attrGroup.setCatelogPath(catelogPath);
  return R.ok().put("attrGroup", attrGroup);
  }

---->新增findCatelogPath接口并添加实现类

@Override
public Long[] findCatelogPath(Long catelogId) {
    List<Long> paths = new ArrayList<>();
    List<Long> parentPath = findParentPath(catelogId, paths);
    Collections.reverse(parentPath);
    return (Long[]) parentPath.toArray(new Long[parentPath.size()]);
}

private List<Long> findParentPath(Long catelogId,List<Long> paths){
    paths.add(catelogId);
    CategoryEntity byId = this.getById(catelogId);
    if (byId.getParentCid()!=0){
        findParentPath(byId.getParentCid(),paths);
    }
    return paths;
}

---->测试

@Test
public void testFindPath(){
    Long[] catelogPath = categoryService.findCatelogPath(225L);
    log.info("完整路径:"+ Arrays.asList(catelogPath));
}

---->页面效果

在这里插入图片描述

最新Java项目实战《谷粒商城》视频教程 转存失败重新上传取消 目录:/77 2019最新项目实战《谷粒商城》 ┣━━day01-2019年5月22日 ┃ ┣━━01-视频 ┃ ┃ ┣━━01 谷粒商城的简介.avi ┃ ┃ ┣━━02 谷粒商城的相关技术.avi ┃ ┃ ┣━━03 谷粒商城的工程浏览.avi ┃ ┃ ┣━━04 开发工具的介绍.avi ┃ ┃ ┣━━05 idea的简单配置.avi ┃ ┃ ┣━━06 idea和gi... 阅读详情

相关推荐

谷粒商城 - 架构图

如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。 创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客

星海IT学习之路 3761

通用商城项目(下)

通用商城项目的完成最后一部分。

stein的博客 623

谷粒商城资料整理课件.zip_谷粒商城课件

基础篇\课件\01、分布式基础&项目环境搭建.pdf 基础篇\课件\02、SpringCloud组件.pdf 基础篇\课件\03、前端开发基础知识.pdf 基础篇\课件\04、商品服务.pdf 基础篇\课件\谷粒商城-分布式基础-图.pdf 运维篇\课件\K8S部署&DevOps.pdf 高级篇\课件\01、Reactive&WebFlux.pdf 高级篇\课件\02、接口幂等性.pdf 高级篇\课件\03、本地事务&分布式事务.pdf 高级篇\课件\04、性能与压力测试.pdf 高级篇\课件\05、缓存&分布式锁.pdf 高级篇\课件\06、ElasticSearch.pdf 高级篇\课件\07、异步&线程池.pdf 高级篇\课件\08、单点登录与社交登录.pdf 高级篇\课件\09、商城业务.pdf 高级篇\课件\10、RabbitMQ.pdf 高级篇\课件\11、支付.pdf 高级篇\课件\12、定时任务与分布式调度.pdf 高级篇\课件\13、ShardingSphere.pdf 高级篇\课件\14、SpringCloud组件.pdf 高级篇\课件\usingthymeleaf

shopping

从前慢-谷粒商城篇章1_unique_perfect的博客-优快云博客_从前慢 谷粒商城 2.1安装docker(CentOS) 3.2 安装mysql 如何查看容器名称方式一:使用docker ps 查看方式二:在启动时我们命名的名字关于启动容器的命令说明视频链接 --name指定容器名字-v目录挂载-p指定端口映射 -e设置mysql参数-d后台运行图中的示例跟我的不一样,具体是按照上面的文本挂载的 1.使用git导入项目到idea中2.到仓库中复制地址 3.粘贴 4.这样

weixin_46163707的博客 595

SIwave:在 SIwave 中释放计算频率扫描的强大功能

AEDT 的电路工具允许注入正确的电压和电流。要使用电路工具,SIwave 必须首先使用 PI 求解器求解结构的 S 参数。

jkh920184196的博客 1476

【C++】小猫钓鱼纸牌游戏--C++实现

小猫钓鱼问题: 描述:初始,两个人各有n张牌(牌面0-10),顺序固定,只能按顺序出牌。然后,两个人轮流在桌面上以接龙的方式出牌,当某个人放置的牌在桌面上已经出现时,他收起相同牌面及其中间的牌作为自己的筹码,同时需要再放一张牌到桌面。某人手上的牌出完后,另一个人继续出,直到两人手上都没牌为止,输出结束时两个人手上的筹码数。 #include<iostream> using namespace std; struct queue { int head; //队列首 int tail; //

qq_41344430的博客 3202

商城-文档

谷粒商城学习笔记

weixin_46925850的博客 8912

AIDD机器学习深度学习药物发现与设计教程总结

AIDD(AI Drug Discovery & Design):是近年来非常火热的技术应用,且已经介入到新药设计到研发的大部分环节当中,为新药发现与开发带来了极大的助力。倾向于机器对数据库信息的自我学习,可以对数据进行提取和学习,一定程度上避免了化合物设计过程中的试错路径,同时还会带来很多全新的结构,为药物发现打破常规的结构壁垒。覆盖了机器学习和深度学习,能与新药研发相结合并实质性的应用到靶点预测、高通量筛选、药物设计、药物的ADMET性质预测等;且算力方面,由早期应用于药物发现领域的决策树、随机

wutianlin0723的博客 6817

谷粒商城 原版 自带 开发文档 接口文档 md 文件

谷粒商城 原版 开发文档 给星星 谢谢

AaronSwarts的博客 1754

2025.1.16——五、LoveSQL1 sqlmap文件类|万能密码

题目来源:BUUCTF[极客大挑战2019]LoveSQL1。

2402_87387800的博客 1067

不止是打字机效果:手把手教你用SpannableStringBuilder打造Android富文本AI对话界面

本文详细介绍了如何使用SpannableStringBuilder在Android平台上构建专业级AI对话界面,涵盖流式文本处理、富文本解析、交互优化等核心技术。通过实战代码示例,帮助开发者实现类似DeepSeek的AI产品交互效果,提升用户体验和应用专业度。

weixin_28358083的博客 198

【雷丰阳-谷粒商城 】【分布式基础篇-全栈开发篇】【06】【商品服务】接口文档地址_三级分类_SPU_SKU

【雷丰阳-谷粒商城 】【分布式基础篇-全栈开发篇】【06】【商品服务】接口文档地址_三级分类_SPU_SKU

Keep Reading Keep Writing Keep Thinking 1593

RTC 实时时钟实验

如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个TR_CLK 周期中 RTC 产生一个中断(秒中断)。void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data) // 往备份区域写用户数据的函数 (这个函数的第一个参数就是寄存器的标号了,这个是通过宏定义定义的)存储在 RTC_ALR 寄存器中的可编程时间相比较,如果 RTC_CR 控制寄存器中设置了相应允许位,比较匹配时将产生一个闹钟中断。寄存器操作完成,并同步之后,设置秒钟中断。

m0_55996456的博客 1205

谷粒商城-架构篇

文章目录谷粒商城-架构篇 谷粒商城-架构篇

naumy的博客 461

贝叶斯核机回归估计混合物健康效应 【BKMR包】——实操篇

使用 ggplot2包绘制 h 的截面# 绘制总体风险摘要。

三分钟热度 5382

从 Material Requirements Planning 看 SAP 物料计划的底层控制逻辑

文章摘要:SAP中的MRP(物料需求计划)不仅仅是运行一个程序(如MD01N),其关键在于主数据和组织层级的正确配置。MRP的核心是解决"何时需要多少物料"的问题,涉及采购、生产、库存等多种供应来源。物料主数据的MRP视图必须在组织层级(如工厂、存储位置)下维护,不同层级的计划逻辑可能完全不同。S/4HANA更强调MRP Area作为细分计划单位,取代传统存储位置MRP。实施时需注意MRP Profile的合理使用,避免批量错误,并特别关注物料生命周期管理(如停用物料和替代件),这些因素共同决定了MRP能否

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1412

谷粒商城项目笔记

谷粒商城项目笔记 谷粒商城篇章1:https://blog.csdn.net/unique_perfect/article/details/111392634 谷粒商城篇章2: https://blog.csdn.net/unique_perfect/article/details/113824202 谷粒商城篇章3: https://blog.csdn.net/unique_perfect/article/details/114035775 附带项目地址:https://gitee.com/unique_

qq_25983579的博客 1380

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

重构谷粒商城09:人人开源框架的快速入门

前言:这个系列将使用最前沿的cursor作为辅助编程工具,来快速开发一些基础的编程项目。目的是为了在真实项目中,帮助初级程序员快速进阶,以最快的速度,效率,快速进阶到中高阶程序员。 本项目将基于谷粒商城项目,并且对谷粒商城项目进行二次重构,使其满足最新的主流技术栈要求。 这篇文章主要介绍,人人开源框架的快速入门,使用它快速搭建项目后台。后面下篇文章考虑使用若依重构。敬请期待。

半旧518的博客 1715

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

十五、谷粒商城- 报错汇总

直接复制上面链接到下面就可以啦。解决:降版本与之前版本统一即可。解决:忘记修改版本了。

Daniel的博客 617

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

尚硅谷-谷粒商城项目问题统计(覆盖课程中遇到的大多数问题)

尚硅谷-谷粒商城项目问题统计(覆盖课程中遇到的大多数问题)

FebruaryQ的博客 784

谷粒商城---在线笔记预览

谷粒商城是一个 B2C 模式的电商平台,销售自营商品给客户。前后分离开发,并开发基于 vue 的后台管理系统。

℡﹏余温*** 686

谷粒商城笔记

尚硅谷谷粒商城项目笔记,主要用于记录自己学习的知识点。

爱哭的毛毛虫的博客 2302

谷粒商城笔记-02-项目整体效果展示

这是整个项目的第2集。重点记录一下三个阶段的主要内容和完成每个阶段后能够达到的技能水平。

epitomizelu的专栏 979

谷粒商城--从入门到入坟(持续更新)第一篇:总体概括

简介:谷粒商城项目,是尚硅谷的一套基于微服务的电商视频,在网上大受欢迎。本人系大三老狗,准备用大约一个月时间,去拆解该商品的知识点,由点及面,最后希望呈现一个比较好的效果。每个知识点、配套的安装软件及源码也会发布出来,希望有伙伴能一起进步。欧力给 前端vue+后端spring cloud+关系型数据库mysql+缓存redis+非关系型数据库elastic及其他相关组件。 ...

qq_44969643的博客 3万+

简单介绍一下谷粒商城这个项目。

谷粒商城(Gulimall)是一个基于 Spring Boot 和 Vue.js 的电子商务项目。通过学习和实践谷粒商城项目,您可以掌握许多有关 Web 开发、电子商务和技术栈的知识。通过学习谷粒商城项目,您将掌握许多有关 Web 开发、电子商务和技术栈的知识,为您未来的项目打下坚实的基础。

qq_44872509的博客 4159
上一篇: 谷粒商城环境搭建
下一篇: 双亲委派机制
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值