本文主要是介绍乐优商城(三)品牌管理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 1. 品牌的新增
- 1.1 url 异步请求
- 1.2 实现品牌新增
- 1.2.1 Controller
- 1.2.2 Service
- 1.2.3 Mapper
- 1.2.4 测试
- 1.2.5 解决问题
- 2. 实现图片上传
- 2.1 搭建工程
- 2.1.1 创建 leyou-upload
- 2.1.2 添加依赖
- 2.1.3 配置文件
- 2.1.4 引导类
- 2.2 实现图片上传
- 2.2.1 Controller
- 2.2.2 Service
- 2.2.3 测试
- 2.2.4 通过浏览器访问图片
- 2.3 绕过网关
- 2.3.1 nginx 反向代理
- 2.3.2 跨域问题
- 2.3.3 测试
- 2.3.4 文件上传的缺陷
- 3. FastDFS
- 3.1 什么是分布式文件系统
- 3.2 什么是 FastDFS
- 3.3 FastDFS 的架构
- 3.3.1 架构图
- 3.3.2 上传和下载流程
- 3.4 安装 FastDFS
- 3.5 使用 FastDFS 客户端
- 3.5.1 添加依赖
- 3.5.2 引入配置类
- 3.5.3 配置文件
- 3.5.4 配置 host 文件
- 3.5.5 测试
- 3.5.6 使用 FastDFS 改造项目
- 3.5.7 再次测试
- 4. 品牌的修改
- 4.1 品牌的回显
- 4.1.1 前端部分
- 4.1.2 实现品牌的回显
- 4.1.2.1 Controller
- 4.1.2.2 Service
- 4.1.2.3 Mapper
- 4.1.2.4 测试
- 4.2 品牌的修改
- 4.2.1 前端部分
- 4.2.2 实现品牌的修改
- 4.2.2.1 Controller
- 4.2.2.2 Service
- 4.2.2.3 Mapper
- 4.2.2.4 测试
- 5. 品牌的删除
- 5.1 前端部分
- 5.2 实现品牌的删除
- 5.2.1 Controller
- 5.2.2 Service
- 5.2.3 测试
1. 品牌的新增
1.1 url 异步请求
-
点击品牌管理下的新增品牌,填写品牌信息后提交
-
打开浏览器控制台
由此可以得知:
- 请求方式:POST
- 请求路径:/item/brand
- 请求参数:{name: “测试品牌”, image: “”, cids: “76,327”, letter: “C”}
- 返回参数:无
1.2 实现品牌新增
1.2.1 Controller
分析四个参数:
- 请求方式:POST
- 请求路径:/item/brand
- 请求参数:brand 对象,外加商品分类的 id 数组 cids
- 返回参数:无
/*** 新增品牌* @param cids* @param brand * @return*/
@PostMapping
public ResponseEntity<Void> saveBrand(@RequestParam("cids") List<Long> cids, Brand brand) {brandService.saveBrand(cids,brand);// 响应 201return ResponseEntity.status(HttpStatus.CREATED).build();
}
1.2.2 Service
我们不仅要新增品牌,还要新增品牌和商品分类的中间表。由于是新增操作,所以还需要加上事务管理。
/*** 新增品牌* @param cids* @param brand* @return*/
@Transactional
public void saveBrand(List<Long> cids, Brand brand) {// 先新增 BrandbrandMapper.insertSelective(brand);// 再新增中间表for (Long cid : cids) {brandMapper.insertCategoryAndBrand(cid, brand.getId());}
}
1.2.3 Mapper
通用 Mapper 只能处理单表,因此我们要手写新增商品分类和品牌的中间表数据的方法
/*** 新增商品分类和品牌的中间表数据* @param cid 商品分类 id* @param bid 品牌 id*/
@Insert("INSERT INTO tb_category_brand(category_id, brand_id) VALUES(#{cid}, #{bid})")
void insertCategoryAndBrand(@Param("cid") Long cid, @Param("bid") Long bid);
1.2.4 测试
响应状态码 400,请求参数不合法,那我们再看看请求体的内容
{name: "测试品牌", image: "", cids: "76,327", letter: "C"}
发现请求体的数据格式是 JSON 格式。
但我们 Controller 中接受参数是以 String 类型接受的,那么现在解决办法有两个:
- 将 Controller 中接受参数改为以 JSON 类型接受
- 将请求体内容改为以 String 类型发送
这两种方法都是可行的。第一种,如果将 Controller 中接受参数改为以 JSON 类型接受,我们就需要创建一个 Java 实体类,好用来反序列化,但这样为了一个方法去创建一个实体类,显然成本太大。
所以我们就采用第二种方法了。
1.2.5 解决问题
找到前端发送请求的代码
修改参数转换为以 String 类型发送
再次测试,新增品牌成功
打开控制台,可以看到请求体已经是以字符串形式发送了
2. 实现图片上传
刚才在实现品牌的新增中,我们并没有上传图片,接下来完成图片上传。
2.1 搭建工程
文件的上传并不只是在品牌管理中有需求,以后的其它服务也可能需要,因此我们创建一个独立的微服务,专门处理各种上传。
2.1.1 创建 leyou-upload
-
右键 leyou 项目 --> New Module --> Maven --> Next
-
填写项目信息 --> Next
-
填写保存的位置 --> Finish
2.1.2 添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>leyou</artifactId><groupId>com.leyou.parent</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><groupId>com.leyou.upload</groupId><artifactId>leyou-upload</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency></dependencies></project>
2.1.3 配置文件
server:port: 8082
spring:application:name: upload-serviceservlet:multipart:max-file-size: 5MB
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eurekainstance:lease-renewal-interval-in-seconds: 5lease-expiration-duration-in-seconds: 10
注意:我们添加了限制文件大小的配置
2.1.4 引导类
@SpringBootApplication
@EnableDiscoveryClient
public class LeyouUploadApplication {public static void main(String[] args) {SpringApplication.run(LeyouUploadApplication.class, args);}
}
2.2 实现图片上传
2.2.1 Controller
参考自定义组件中的文件上传组件可以知道以下内容:
- 请求方式:上传肯定是 POST
- 请求路径:/upload/image
- 请求参数:参数名是 file,SpringMVC 会封装为一个接口:MultipartFile
- 返回结果:上传成功后得到的文件的 url 路径,返回类型 String
@RestController
@RequestMapping("/upload")
public class UploadController {@Autowiredprivate UploadService uploadService;/*** 图片上传* @param file* @return*/@PostMapping("/image")public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile file) {String url = uploadService.uploadImage(file);if(StringUtils.isBlank(url)) {return ResponseEntity.badRequest().build();}return ResponseEntity.status(HttpStatus.CREATED).body(url);}
}
2.2.2 Service
在上传文件过程中,我们需要对文件进行检验:
- 检验文件类型
- 检验文件内容
@Service
public class UploadService {// 图片类型private static final List<String> IMAGE_CONTENT_TYPES = Arrays.asList("image/png", "image/jpeg");// 日志private static final Logger LOGGER = LoggerFactory.getLogger(UploadService.class);/*** 图片上传** @param file* @return*/public String uploadImage(MultipartFile file) {// 获取文件名String filename = file.getOriginalFilename();// 获取文件类型String contentType = file.getContentType();// 文件类型不合法,直接返回 nullif (!IMAGE_CONTENT_TYPES.contains(contentType)) {LOGGER.info("文件类型不合法:{}", filename);return null;}try {BufferedImage bufferedImage = ImageIO.read(file.getInputStream());// 如果文件内容不合法,直接返回 nullif (bufferedImage == null) {LOGGER.info("文件内容不合法:{}", filename);return null;}// 保存文件到服务器file.transferTo(new File("C:\\Users\\admin\\Desktop\\img\\" + filename));// 返回 urlreturn "http://image.leyou.com/" + filename;} catch (IOException e) {e.printStackTrace();LOGGER.info("服务器内部错误:{}", filename);}return null;}
}
注意:这里图片地址使用了另外的 url,原因如下:
- 图片不能保存在服务器内部,这样会对服务器产生额外的加载负担
- 一般静态资源都应该使用独立域名,这样访问静态资源时不会携带一些不必要的 cookie,减小请求的数据量
2.2.3 测试
-
打开 Postman 接口测试工具
-
选择 Post 请求方式,输入请求地址
-
填写 Headers
-
填写 Body,选择文件
-
发送请求,得到响应的 url
-
去目录查看一下
2.2.4 通过浏览器访问图片
现在我们返回了图片的 url,但这个 url 浏览器还不能访问到,也就无法做到图片的回显。
通过 nginx 代理图片路径
-
打开 nginx 配置文件,添加如下配置
server {listen 80;server_name image.leyou.com;proxy_set_header X-Forwarded-Host $host;proxy_set_header X-Forwarded-Server $host;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;location / {root C:\\Users\\admin\\Desktop\\img;} }
-
重启 nginx
配置 host 文件
通过浏览器访问图片
2.3 绕过网关
图片上传是文件的传输,如果也经过 Zuul 网关的代理,文件就会经过多次网路传输,造成不必要的网络负担。在高并发时,可能导致网络阻塞,Zuul 网关不可用。这样我们的整个系统就瘫痪了。所以,我们上传文件的请求就不经过网关来处理了。
2.3.1 nginx 反向代理
这里可以看到请求路径为:api/upload/image,那么肯定会经过 Zuul 网关。如果要绕过 Zuul 网关,可以使用 nginx 反向代理到图片上传的服务地址,步骤如下:
-
修改 nginx 配置文件,将以 /api/upload 开头的请求拦截下来,转交到图片上传的服务地址
server {listen 80;server_name api.leyou.com;proxy_set_header X-Forwarded-Host $host;proxy_set_header X-Forwarded-Server $host;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;location /api/upload {proxy_pass http://127.0.0.1:8082;proxy_connect_timeout 600;proxy_read_timeout 600;}location / {proxy_pass http://127.0.0.1:10010;proxy_connect_timeout 600;proxy_read_timeout 600;} }
这样请求路径变为了:http://127.0.0.1:8002/api/upload/image,但还是多了一个 /api。
nginx 提供了 rewrite 指令,用于对地址进行重写,格式如下:
rewrite "用来匹配路径的正则" 重写后的路径 [指令];
-
修改 nginx 配置文件,重写地址
server {listen 80;server_name api.leyou.com;proxy_set_header X-Forwarded-Host $host;proxy_set_header X-Forwarded-Server $host;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;location /api/upload {proxy_pass http://127.0.0.1:8082;proxy_connect_timeout 600;proxy_read_timeout 600;rewrite "^/api/(.*)$" /$1 break; }location / {proxy_pass http://127.0.0.1:10010;proxy_connect_timeout 600;proxy_read_timeout 600;} }
- 首先,我们映射路径是 /api/upload,而下面一个映射路径是 / ,根据最长路径匹配原则,/api/upload 优先级更高。也就是说,凡是以 /api/upload 开头的路径,都会被第一个配置处理
proxy_pass
:反向代理,这次我们代理到 8082 端口,也就是 upload-service 服务rewrite "^/api/(.*)$" /$1 break
,路径重写:"^/api/(.*)$"
:匹配路径的正则表达式,用了分组语法,把/api/
以后的所有部分当做1组/$1
:重写的目标路径,这里用$1引用前面正则表达式匹配到的分组(组编号从1开始),即/api/
后面的所有。这样新的路径就是除去/api/
以外的所有,就达到了去除/api
前缀的目的break
:指令,常用的有2个,分别是:last、break- last:重写路径结束后,将得到的路径重新进行一次路径匹配
- break:重写路径结束后,不再重新匹配路径。
-
重启 nginx 服务器
2.3.2 跨域问题
原来在网关的服务中添加了跨域过滤器,解决了跨域问题。现在不经过网关了,那么同样需要在图片上传的服务中添加了跨域过滤器。
@Configuration
public class LeyouCorsConfigration {@Beanpublic CorsFilter corsFilter() {// 初始化 cors 配置对象CorsConfiguration config = new CorsConfiguration();config.addAllowedOrigin("http://manage.leyou.com"); //允许的域config.setAllowCredentials(true); //是否发送 Cookie 信息config.addAllowedMethod("*"); //允许的请求方式config.addAllowedHeader("*"); //允许的头信息//初始化 cors 配置源对象UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();configSource.registerCorsConfiguration("/**", config); //添加映射路径,拦截一切请求return new CorsFilter(configSource); //返回 CorsFilter}
}
2.3.3 测试
-
重启 leyou-upload 服务
-
再次上传图片,成功回显
-
点击提交,成功新增品牌
2.3.4 文件上传的缺陷
上传本身没有任何问题,问题出在保存文件的方式,我们是保存在服务器机器,就会有下面的问题:
- 单机器存储,存储能力有限
- 无法进行水平扩展,因为多台机器的文件无法共享,会出现访问不到的情况
- 数据没有备份,有单点故障风险
- 并发能力差
这个时候,最好使用分布式文件存储来代替本地文件存储。
3. FastDFS
3.1 什么是分布式文件系统
分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连。
通俗来讲:
- 传统文件系统管理的文件就存储在本机。
- 分布式文件系统管理的文件存储在很多机器,这些机器通过网络连接,要被统一管理。无论是上传或者访问文件,都需要通过管理中心来访问
3.2 什么是 FastDFS
FastDFS 是由淘宝的余庆先生所开发的一个轻量级、高性能的开源分布式文件系统。用纯 C 语言开发,功能丰富:
- 文件存储
- 文件同步
- 文件访问(上传、下载)
- 存取负载均衡
- 在线扩容
适合有大容量存储需求的应用或系统。同类的分布式文件系统有谷歌的 GFS、HDFS(Hadoop)、TFS(淘宝)等。
3.3 FastDFS 的架构
3.3.1 架构图
FastDFS 两个主要的角色:Tracker Server 和 Storage Server 。
- Tracker Server:跟踪服务器,主要负责调度 storage 节点与 client 通信,在访问上起负载均衡的作用,和记录 storage 节点的运行状态,是连接 client 和 storage 节点的枢纽。
- Storage Server:存储服务器,保存文件和文件的 meta data(元数据),每个 storage server 会启动一个单独的线程主动向 Tracker cluster 中每个 tracker server 报告其状态信息,包括磁盘使用情况,文件同步情况及文件上传下载次数统计等信息
- Group:文件组,多台 Storage Server 的集群。上传一个文件到同组内的一台机器上后,FastDFS 会将该文件即时同步到同组内的其它所有机器上,起到备份的作用。不同组的服务器,保存的数据不同,而且相互独立,不进行通信。
- Tracker Cluster:跟踪服务器的集群,有一组 Tracker Server(跟踪服务器)组成。
- Storage Cluster :存储集群,有多个 Group 组成。
3.3.2 上传和下载流程
上传
- Client 通过 Tracker server 查找可用的 Storage server。
- Tracker server 向 Client 返回一台可用的 Storage server 的 IP 地址和端口号。
- Client 直接通过 Tracker server 返回的 IP 地址和端口与其中一台 Storage server 建立连接并进行文件上传。
- 上传完成,Storage server 返回 Client 一个文件 ID,文件上传结束。
下载
- Client 通过 Tracker server 查找要下载文件所在的的 Storage server。
- Tracker server 向 Client 返回包含指定文件的某个 Storage server 的 IP 地址和端口号。
- Client 直接通过 Tracker server 返回的 IP 地址和端口与其中一台 Storage server 建立连接并指定要下载文件。
- 下载文件成功。
3.4 安装 FastDFS
参考下载的 FastDFS 资料
注意:配置 FastDFS 服务器 ip 是你自己虚拟机的 ip
3.5 使用 FastDFS 客户端
3.5.1 添加依赖
在父工程中,我们已经锁定了依赖的版本:
<fastDFS.client.version>1.26.1-RELEASE</fastDFS.client.version>
所以直接在 leyou-upload 工程中直接引入依赖即可:
<dependency><groupId>com.github.tobato</groupId><artifactId>fastdfs-client</artifactId>
</dependency>
3.5.2 引入配置类
@Configuration
@Import(FdfsClientConfig.class)
// 解决jmx重复注册bean的问题
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FastClientImporter {}
3.5.3 配置文件
在 leyou-upload 工程中添加 FastDFS 配置
fdfs:so-timeout: 1501 # 超时时间connect-timeout: 601 # 连接超时时间thumb-image: # 缩略图width: 60height: 60tracker-list: # tracker地址:你的虚拟机服务器地址+端口(默认是22122)- 192.168.222.132:22122
3.5.4 配置 host 文件
将来通过 image.leyou.com 这个域名访问 fastDFS 服务器上的图片资源。所以需要配置 hosts 文件,将 image.leyou.com 代理到虚拟机地址。
192.168.222.132 image.leyou.com
3.5.5 测试
注意:测试的时候虚拟机上 FastDFS 和 Nginx 需要是启动的,并且防火请要是关闭的。
编写测试类
@SpringBootTest
@RunWith(SpringRunner.class)
public class FastDFSTest {@Autowiredprivate FastFileStorageClient storageClient;@Autowiredprivate ThumbImageConfig thumbImageConfig;@Testpublic void testUpload() throws FileNotFoundException {// 上传的文件File file = new File("C:\\Users\\admin\\Desktop\\1.jpg");// 上传并保存图片,参数:1-上传的文件流 2-文件的大小 3-文件的后缀 4-可以不写StorePath storePath = this.storageClient.uploadFile(new FileInputStream(file), file.length(), "jpg", null);// 带分组的路径System.out.println(storePath.getFullPath());// 不带分组的路径System.out.println(storePath.getPath());}@Testpublic void testUploadAndCreateThumb() throws FileNotFoundException {File file = new File("C:\\Users\\admin\\Desktop\\1.jpg");// 上传并且生成缩略图StorePath storePath = this.storageClient.uploadImageAndCrtThumbImage(new FileInputStream(file), file.length(), "jpg", null);// 带分组的路径System.out.println(storePath.getFullPath());// 不带分组的路径System.out.println(storePath.getPath());// 获取缩略图路径String path = thumbImageConfig.getThumbImagePath(storePath.getPath());System.out.println(path);}
}
testUpload 运行结果
group1/M00/00/00/wKjehF5bzsuAab4AAADSZYQEtvY842.jpg
M00/00/00/wKjehF5bzsuAab4AAADSZYQEtvY842.jpg
testUploadAndCreateThumb 运行结果
group1/M00/00/00/wKjehF5b0u-AAX-AAADSZYQEtvY315.jpg
M00/00/00/wKjehF5b0u-AAX-AAADSZYQEtvY315.jpg
M00/00/00/wKjehF5b0u-AAX-AAADSZYQEtvY315_60x60.jpg
访问第一组第一个路径(正常上传的图片)
访问第二组第三个路径(上传的缩略图)
3.5.6 使用 FastDFS 改造项目
修改 leyou-upload 项目中的 UploadService,将文件上传到本地改为文件上传到 FastDFS
@Service
public class UploadService {// 图片类型private static final List<String> IMAGE_CONTENT_TYPES = Arrays.asList("image/png", "image/jpeg");// 日志private static final Logger LOGGER = LoggerFactory.getLogger(UploadService.class);@Autowiredprivate FastFileStorageClient storageClient;/*** 图片上传** @param file* @return*/public String uploadImage(MultipartFile file) {// 获取文件名String filename = file.getOriginalFilename();// 获取文件类型String contentType = file.getContentType();// 文件类型不合法,直接返回 nullif (!IMAGE_CONTENT_TYPES.contains(contentType)) {LOGGER.info("文件类型不合法:{}", filename);return null;}try {BufferedImage bufferedImage = ImageIO.read(file.getInputStream());// 如果文件内容不合法,直接返回 nullif (bufferedImage == null) {LOGGER.info("文件内容不合法:{}", filename);return null;}// 获取文件名后缀String type = StringUtils.substringAfterLast(filename, ".");// 保存文件到 FastDFS 服务器StorePath storePath = this.storageClient.uploadFile(file.getInputStream(), file.getSize(), type, null);// 返回 urlreturn "http://image.leyou.com/" + storePath.getFullPath();} catch (IOException e) {e.printStackTrace();LOGGER.info("服务器内部错误:{}", filename);}return null;}
}
3.5.7 再次测试
新增品牌完成后,可以看到原来上传到本地的图片已经无法显示了,而上传到 FastDFS 上的图片可以显示
4. 品牌的修改
4.1 品牌的回显
要修改品牌信息,首先要让品牌信息回显。
4.1.1 前端部分
我们找到前端中的修改品牌方法
可以看到这里有一个根据品牌信息查询商品分类的请求,可以得到以下信息:
- 请求方式:GET
- 请求参数:品牌 id,这里用的是 Rest 风格的占位符
- 请求地址:/item/category/bid
- 返回参数:商品分类的集合
4.1.2 实现品牌的回显
4.1.2.1 Controller
在 CategoryController 中编写方法
/*** 根据品牌 Id 查询品牌分类* @param bid* @return*/
@GetMapping("/bid/{bid}")
public ResponseEntity<List<Category>> queryCategoryByBrandId(@PathVariable("bid") Long bid) {if (bid == null || bid.longValue() < 0) {return ResponseEntity.badRequest().build(); // 响应 400}List<Category> categories = categoryService.queryCategoryByBrandId(bid);if(CollectionUtils.isEmpty(categories)) {return ResponseEntity.notFound().build(); // 响应 404}return ResponseEntity.ok(categories);
}
4.1.2.2 Service
在 CategoryService 中编写方法
/*** 根据品牌 Id 查询品牌分类* @param bid* @return*/
public List<Category> queryCategoryByBrandId(Long bid) {List<Category> categories = categoryMapper.queryCategoryByBrandId(bid);return categories;
}
4.1.2.3 Mapper
在 CategoryMapper 中编写方法
/*** 根据品牌 Id 查询品牌分类* @param bid* @return*/
@Select("SELECT * FROM tb_category WHERE id IN (SELECT category_id FROM tb_category_brand WHERE brand_id = #{bid})")
List<Category> queryCategoryByBrandId(Long bid);
4.1.2.4 测试
-
点击修改按钮
-
品牌信息回显成功
4.2 品牌的修改
4.2.1 前端部分
找到前端提交表单的方法
可以看到当 isEdit 值为 true 时,发送 put 请求。
而在修改品牌方法中已经把 isEdit 值赋值为 true 了
于是可以得出四个参数:
- 请求方式:PUT
- 请求路径:/item/brand
- 请求参数:brand 对象,外加商品分类的 id 数组 cids
- 返回参数:无
4.2.2 实现品牌的修改
4.2.2.1 Controller
在 BrandController 编写方法
/*** 更新品牌* @param cids* @param brand* @return*/
@PutMapping
public ResponseEntity<Void> updateBrand(@RequestParam("cids") List<Long> cids, Brand brand) {brandService.updateBrand(cids,brand);// 响应 204return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}
4.2.2.2 Service
在 BrandService 编写方法
/*** 更新品牌* @param cids* @param brand*/
@Transactional
public void updateBrand(List<Long> cids, Brand brand) {// 先更新 BrandbrandMapper.updateByPrimaryKey(brand);// 通过品牌 id 删除中间表brandMapper.deleteCategoryAndBrandByBid(brand.getId());// 再新增中间表for (Long cid : cids) {brandMapper.insertCategoryAndBrand(cid, brand.getId());}
}
4.2.2.3 Mapper
在 BrandMapper 编写方法
/*** 通过品牌 id 删除中间表* @param bid*/
@Delete("DELETE FROM tb_category_brand WHERE brand_id = #{bid}")
void deleteCategoryAndBrandByBid(Long bid);
4.2.2.4 测试
-
修改品牌名称
-
点击提交,修改成功
5. 品牌的删除
5.1 前端部分
前端代码里没有删除函数,我就自己定义了一个,删除成功后重新加载数据
可以看到这里有一个删除品牌的请求,可以得到以下信息:
- 请求方式:DELETE
- 请求参数:品牌 id,这里用的是 Rest 风格的占位符
- 请求地址:/item/brand/bid
- 返回参数:无
5.2 实现品牌的删除
5.2.1 Controller
在 BrandController 中编写
/*** 删除品牌* @param bid* @return*/
@DeleteMapping("/bid/{bid}")
public ResponseEntity<Void> deleteBrand(@PathVariable("bid") Long bid) {brandService.deleteBrand(bid);// 响应 204return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}
5.2.2 Service
在 BrandService 中编写
/*** 删除品牌* @param bid*/
@Transactional
public void deleteBrand(Long bid) {// 通过品牌 id 删除中间表brandMapper.deleteCategoryAndBrandByBid(bid);// 删除品牌brandMapper.deleteByPrimaryKey(bid);
}
5.2.3 测试
点击删除按钮,删除成功
这篇关于乐优商城(三)品牌管理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!