电商生鲜网站开发(四)——后台开发:商品模块-图片上传/多条件拼接sql

增加商品

上传图片

更新商品

删除商品

批量上下架

图片上传功能

文件名UUID

通用唯一识别码(Universally Unique Identifier)

防止重名、防止发图

生成规则:日期和时间、MAC地址、HashCode、随机数

配置application.properties

# 上传文件的路径,根据部署情况自行修改 该值注入到Constan类中
file.upload.dir=/Users/cat/Documents/project/java/online_mall/mall-prepare-static

Constant常量类

package com.learn2333.mall.common;import com.google.common.collect.Sets;
import com.learn2333.mall.exception.MallException;
import com.learn2333.mall.exception.MallExceptionEnum;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.Set;/*** 描述:    常量值*/
@Component
public class Constant {public static final String MALL_USER = "mall_user";public static final String SALT = "learn2333";public static String FILE_UPLOAD_DIR;//因为是static无法直接注入,使用set方法为静态变量注入赋值@Value("${file.upload.dir}")public void setFileUploadDir(String fileUploadDir) {FILE_UPLOAD_DIR = fileUploadDir;}

controller

    @PostMapping("/admin/upload/file")public ApiRestResponse upload(HttpServletRequest httpServletRequest,@RequestParam("file") MultipartFile file) {String fileName = file.getOriginalFilename();String suffixName = fileName.substring(fileName.lastIndexOf("."));  //后缀//生成文件名称UUIDUUID uuid = UUID.randomUUID();String newFileName = uuid.toString() + suffixName;//创建文件File fileDirectory = new File(Constant.FILE_UPLOAD_DIR);File destFile = new File(Constant.FILE_UPLOAD_DIR + newFileName);//如果文件夹不存在if (!fileDirectory.exists()) {if (!fileDirectory.mkdir()) {//创建文件夹throw new MallException(MallExceptionEnum.MKDIR_FAILED);}}//文件写入try {file.transferTo(destFile);} catch (IOException e) {e.printStackTrace();}//返回文件地址try {return ApiRestResponse.success(getHost(new URI(httpServletRequest.getRequestURL() + "")) + "/images/"+ newFileName);} catch (URISyntaxException e) {return ApiRestResponse.error(MallExceptionEnum.UPLOAD_FAILED);}}/*** 获取ip和端口号* @param uri* @return*/private URI getHost(URI uri) {URI effectiveURI;try {effectiveURI = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(),null, null, null);} catch (URISyntaxException e) {effectiveURI = null;}return effectiveURI;}

自定义静态资源映射目录

上传图片后回显

配置SpringBootWebMvcConfig

静态资源到本地目录到映射

package com.learn2333.mall.config;import com.learn2333.mall.common.Constant;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 描述:     配置Swagger地址映射*/
@Configuration
public class MallWebMvcConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {//图片目录映射registry.addResourceHandler("/images/**").addResourceLocations("file:" + Constant.FILE_UPLOAD_DIR);registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}
}

商品批量上下架

MyBatis遍历List

where语句拼接

    <update id="batchUpdateSellStatus">update mall_productset status = #{sellStatus}where id in<foreach collection="ids" open="(" close=")" item="id" separator=",">#{id}</foreach></update>

后台管理员商品列表接口

调用分页PageHelper,跟商品分类模块类似

前台用户商品列表接口

商品列表:搜索功能

使用入参判空、加%通配符、like关键字sql拼接

传入ProductListReq实体

package com.learn2333.mall.model.request;import java.util.Date;public class ProductListReq {private String keyword;  //关键字private Integer categoryId;        //分类idprivate String orderBy;       //排序方式//分页private Integer pageNum = 1;private Integer pageSize = 10;get;set;
}

ProjectController

    @ApiOperation("商品列表")@GetMapping("product/list")public ApiRestResponse list(ProductListReq productListReq){PageInfo list = productService.list(productListReq);return ApiRestResponse.success(list);}

对与这种条件比较多的,拼接麻烦的查询,可以建一个query,也方便后续的修改

ProductListQuery

package com.learn2333.mall.model.query;import java.util.List;/*** 描述:       查询商品列表的Query*/
public class ProductListQuery {private String keyword;//查询一个目录下的商品,不一定是只有当前目录下,还包含子目录,子子目录下的商品;因此之前传入一个目录的id现在还要获取它子目录的所有idprivate List<Integer> categoryIds;get;set;
}

productServiceImpl

    @Overridepublic PageInfo list(ProductListReq productListReq) {//构建Query对象ProductListQuery productListQuery = new ProductListQuery();//搜索处理if (!StringUtils.isEmpty(productListReq.getKeyword())) {String keyword = new StringBuilder().append("%").append(productListReq.getKeyword()).append("%").toString();productListQuery.setKeyword(keyword);}//目录处理:如果查某个目录下的商品,不仅是需要查出该目录下的,还要把所有子目录的所有商品都查出来,所以要拿到一个目录id的Listif (productListReq.getCategoryId() != null) {//复用之前写过的传入目录id查询子目录方法listCategoryForCustomerList<CategoryVO> categoryVOList = categoryService.listCategoryForCustomer(productListReq.getCategoryId());//将得到的树形目录结构categoryVOList展开ArrayList<Integer> categoryIds = new ArrayList<>();categoryIds.add(productListReq.getCategoryId());//用下面定义的方法来处理子目录的遍历,//通过下面的函数处理就可以将categoryVOList中子目录所有id放入categoryIds,因为传入的是List<CategoryVO>引用类型getCategoryIds(categoryVOList, categoryIds);productListQuery.setCategoryIds(categoryIds);}//排序处理String orderBy = productListReq.getOrderBy(); //为了系统安全,不能传入什么就直接按照什么排序,而是要拿到前台传入的排序规则if (Constant.ProductListOrderBy.PRICE_ASC_DESC.contains(orderBy)) {    //contains判断是否包含PageHelper.startPage(productListReq.getPageNum(), productListReq.getPageSize(), orderBy);} else {PageHelper.startPage(productListReq.getPageNum(), productListReq.getPageSize());}List<Product> productList = productMapper.selectList(productListQuery);PageInfo pageInfo = new PageInfo(productList);return pageInfo;}//递归遍历子目录private void getCategoryIds(List<CategoryVO> categoryVOList, ArrayList<Integer> categoryIds) {for (int i = 0; i < categoryVOList.size(); i++) {CategoryVO categoryVO = categoryVOList.get(i);if (categoryVO != null) {categoryIds.add(categoryVO.getId());getCategoryIds(categoryVO.getChildCategory(), categoryIds);}}}

常量(排序方式接口)

package com.learn2333.mall.common;import com.google.common.collect.Sets;
import com.learn2333.mall.exception.MallException;
import com.learn2333.mall.exception.MallExceptionEnum;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.Set;/*** 描述:    常量值*/
@Component
public class Constant {public static final String MALL_USER = "mall_user";public static final String SALT = "learn2333";public static String FILE_UPLOAD_DIR;@Value("${file.upload.dir}")public void setFileUploadDir(String fileUploadDir) {FILE_UPLOAD_DIR = fileUploadDir;}public interface ProductListOrderBy {Set<String> PRICE_ASC_DESC = Sets.newHashSet("price desc", "price asc");}

ProductMapper接口

    List<Product> selectList(@Param("query") ProductListQuery query);

ProductMapper

    <select id="selectList" resultMap="BaseResultMap"parameterType="com.learn2333.mall.model.query.ProductListQuery">select<include refid="Base_Column_List"/>from mall_product<where><if test="query.keyword != null">and name like #{query.keyword}</if><if test="query.categoryIds != null">and category_id in<foreach collection="query.categoryIds" close=")" item="item" open="(" separator=",">#{item}</foreach></if><!--上架商品-->and status = 1</where>order by update_time desc</select>

排序功能、MyBatis PageHelper、枚举:order by

总结

商品的搜索、排序、目录查询

常见问题:更新和新增不要用一个接口,虽然方便,但是从长期维护角度每一个接口要明确分工;排序的时候要用常量枚举判断,不要直接传入,否则可能被黑客利用,攻击数据库。

电商生鲜网站开发(四)——后台开发:商品模块-图片上传/多条件拼接sql相关推荐

  1. 电商生鲜网站开发(二)——后台开发:用户模块

    电商生鲜网站开发(二)--后台开发:用户模块 文章目录 电商生鲜网站开发(二)--后台开发:用户模块 接口设计 开发任务与知识点 案例:注册接口 统一处理异常 Java异常体系 案例:登录接口 接口设 ...

  2. 电商生鲜网站开发(三)——后台开发:商品分类模块-Redis/Swagger/统一身份校验/IDEA技巧

    电商生鲜网站开发(三)--后台开发:商品分类模块-Redis/Swagger/统一身份校验/IDEA技巧 分类层级 在商品分类上需要继续做归类操作 分类设置成三级 层级太深的弊端:对用户不友好,不利于 ...

  3. 电商生鲜网站开发(一)——Spring Boot项目开发准备

    本系列内容完成Spring Boot框架的电商生鲜网站开发的完整案例,前后端分离开发的案例,先开发后端接口后开发前端,最后部署等待. Spring Boot项目开发准备 文章目录 Spring Boo ...

  4. SSM开发书评网29:后台二:wangEditor图片上传;(主要内容是【wangEditor图片上传的文档要求】,【Spring MVC整合FileUpload组件,以实现文件上传功能】)

    说明: (1)本篇博客内容说明:[在后台系统,我们点击新增按钮后,会弹出新增图书对话框]→[该对话框中,包含一个wangEditor富文本编辑器]→[wangEditor富文本编辑器中,可以包含图片] ...

  5. 【小程序开发原创】小程序裁剪图片上传头像,二维码源码

    微信小程序 图片裁剪工具,简单易用 项目需求 在做微信小程序的时候有个图片上传之前裁剪的需求,找过一些github中的项目,都不太理想,主要是没有办法自定义宽高,于是自己研究了一下,做了一个简单的图片 ...

  6. Flask Web开发入门(十)之图片上传(使用Flask-Upload)

    在Flask Web开发入门(八)之文件上传中,我们探讨了Flask框架下的文件上传,本章我们将使用Flask插件Flask-Uploads示例说明的图片上传与展现如何实现 开始之前,我们先简单看下F ...

  7. 微信小程序云开发之云存储(实现图片上传和下载)

    文章目录 前言 一.云存储的使用 二.使用演练 1.上传图片到云存储中 2.下载并保存图片到手机 前言 我们经常将文件(音频.图片.压缩包.文档)存储在网上,我们的云开发平台为开发者提供"云 ...

  8. 潭州课堂25班:Ph201805201 django 项目 第三十九课 后台 文章发布,图片上传到 FastDFS后端实现 七牛云讲解(课堂笔记)...

    文章发布: # 1,从前台获取参数# 2,校验参数# 3,把数据保存到数据库# 4,返回执行结果到前台,(创建成功或失败) 自定义 froms.py 校验参数 上传图片到七牛云 注册 https:// ...

  9. vue后台管理upload(图片上传)

    众所周知,在很多项目中,特别是关于商品管理类的新增功能中,都会带有新增图片的功能,上传图片是很多前端小白的噩梦,接下来我们就来讲一下上传图片的流程,以及详细代码 # 上传图片 ## 常见的图片上传的方 ...

最新文章

  1. 实战:基于深度学习的道路损坏检测
  2. linux traceroute 命令 查看路由表
  3. UA MATH571B 试验设计III 单因素试验设计2
  4. 数据库常用的基本操作
  5. Warning: mysql_real_escape_string(): Access denied for user 'nobody'@'localhost'
  6. element ui 表单验证残留提示处理
  7. android listview 滑动条显示_ListView详细介绍与使用
  8. 微信号php756,微信机器人开发者常说的“提62”是什么?微信62数据是什么意思?...
  9. jquery里判断数组内是否包含了指定的值或元素的方法
  10. WinGdi 和 GdiPlus绘图知识积累
  11. python超市管理系统实训报告_需求分析实验报告(小型超市管理系统)
  12. 局域网技术,涉及到VLAN,TRUNK,链路聚合,VLAN间路由,单臂路由,
  13. Error: Cound not create the Java Virtual Machine. Error: A fatal exception has occurred. Program wil
  14. 1厘米等于多少个像素
  15. 三国志战略版:【满红杀手】名将卡包新武将_许攸分析
  16. 【慧河网络安全组】Web基础和http协议培训题_1
  17. 使用 Gitbook 打造你的电子书
  18. 渠道分析 之 渠道分析的价值 -3
  19. Linux断开usb调试命令,Android关闭USB的ADB调试和文件传输功能(禁用USB)【转】
  20. 树的先序/中序/后序遍历

热门文章

  1. learining user's intrinsic and extrinsic interests for point of interest recommendation IJCAI17
  2. 云原生周报 | 百度开源千万级CPS压测软件 dperf;BFE Server v1.5.0 发布
  3. 浅谈Web安全技术----RBI
  4. Esper学习之十三:EPL语法(九)
  5. 车联网发展的昨天和明天
  6. [人人]在大学的第二个总结
  7. 湖南计算机专修学院20年同学聚会,“时光荏苒二十年再聚首”——机制89级校友毕业成功举办20年同学聚会...
  8. 多边形向内收缩指定距离的实现
  9. Nature Microbiology:植物根系分泌物影响菌群结构
  10. 智能门锁怎么选(3)