3.11商品模块实现

分类: 搭建单体商城服务

商品模块实现

商品模块是商城系统的核心模块,包括商品管理、商品查询、商品搜索等功能。本节将学习如何实现完整的商品模块。

本节将学习:商品列表查询、商品详情查询、商品搜索,以及商品分类。

商品列表查询

分页查询实现

package com.example.ecommerce.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.ecommerce.entity.Product; import com.example.ecommerce.mapper.ProductMapper; import com.example.ecommerce.service.ProductService; import org.springframework.stereotype.Service; @Service public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService { @Override public Page<Product> getProductList(Integer current, Integer size, Long categoryId) { Page<Product> page = new Page<>(current, size); LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>(); // 按分类筛选 if (categoryId != null) { wrapper.eq(Product::getCategoryId, categoryId); } // 只查询上架商品 wrapper.eq(Product::getStatus, 1); // 按创建时间倒序 wrapper.orderByDesc(Product::getCreateTime); return page(page, wrapper); } }

Controller 实现

@RestController @RequestMapping("/api/products") public class ProductController { @Autowired private ProductService productService; @GetMapping public Result<Page<Product>> getProductList( @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size, @RequestParam(required = false) Long categoryId ) { Page<Product> page = productService.getProductList(current, size, categoryId); return Result.success(page); } }

商品详情查询

详情查询实现

@Override public Product getProductDetail(Long id) { Product product = getById(id); if (product == null) { throw new BusinessException("Product not found"); } if (product.getStatus() == 0) { throw new BusinessException("Product is off-shelf"); } return product; }

Controller 实现

@GetMapping("/{id}") public Result<Product> getProductDetail(@PathVariable Long id) { Product product = productService.getProductDetail(id); return Result.success(product); }

商品搜索

搜索流程

搜索实现

@Override public Page<Product> searchProducts(String keyword, Long categoryId, String sortBy, Integer current, Integer size) { Page<Product> page = new Page<>(current, size); LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>(); // 关键词搜索 if (keyword != null && !keyword.isEmpty()) { wrapper.and(w -> w.like(Product::getName, keyword) .or() .like(Product::getDescription, keyword)); } // 分类筛选 if (categoryId != null) { wrapper.eq(Product::getCategoryId, categoryId); } // 只查询上架商品 wrapper.eq(Product::getStatus, 1); // 排序 if ("price_asc".equals(sortBy)) { wrapper.orderByAsc(Product::getPrice); } else if ("price_desc".equals(sortBy)) { wrapper.orderByDesc(Product::getPrice); } else { wrapper.orderByDesc(Product::getCreateTime); } return page(page, wrapper); }

Controller 实现

@GetMapping("/search") public Result<Page<Product>> searchProducts( @RequestParam(required = false) String keyword, @RequestParam(required = false) Long categoryId, @RequestParam(required = false) String sortBy, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size ) { Page<Product> page = productService.searchProducts(keyword, categoryId, sortBy, current, size); return Result.success(page); }

商品分类

分类树结构

分类实体类

package com.example.ecommerce.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.time.LocalDateTime; import java.util.List; @Data @TableName("category") public class Category { @TableId(type = IdType.AUTO) private Long id; private String name; private Long parentId; private Integer level; private Integer sortOrder; private LocalDateTime createTime; private LocalDateTime updateTime; // 子分类(不映射到数据库) @TableField(exist = false) private List<Category> children; }

分类查询实现

package com.example.ecommerce.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.ecommerce.entity.Category; import com.example.ecommerce.mapper.CategoryMapper; import com.example.ecommerce.service.CategoryService; import org.springframework.stereotype.Service; import java.util.List; import java.util.stream.Collectors; @Service public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService { @Override public List<Category> getCategoryTree() { // 查询所有分类 List<Category> allCategories = list(); // 构建分类树 return allCategories.stream() .filter(category -> category.getParentId() == 0) .map(category -> { category.setChildren(getChildren(category.getId(), allCategories)); return category; }) .collect(Collectors.toList()); } private List<Category> getChildren(Long parentId, List<Category> allCategories) { return allCategories.stream() .filter(category -> category.getParentId().equals(parentId)) .map(category -> { category.setChildren(getChildren(category.getId(), allCategories)); return category; }) .collect(Collectors.toList()); } }

Controller 实现

@RestController @RequestMapping("/api/categories") public class CategoryController { @Autowired private CategoryService categoryService; @GetMapping("/tree") public Result<List<Category>> getCategoryTree() { List<Category> tree = categoryService.getCategoryTree(); return Result.success(tree); } @GetMapping("/{id}/products") public Result<Page<Product>> getProductsByCategory( @PathVariable Long id, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size ) { Page<Product> page = productService.getProductList(current, size, id); return Result.success(page); } }

商品管理

商品创建

@Override @Transactional(rollbackFor = Exception.class) public Product createProduct(Product product) { // 验证分类是否存在 Category category = categoryService.getById(product.getCategoryId()); if (category == null) { throw new BusinessException("Category not found"); } // 设置默认状态 product.setStatus(1); // 保存商品 save(product); return product; }

商品更新

@Override @Transactional(rollbackFor = Exception.class) public Product updateProduct(Long id, Product product) { Product existProduct = getById(id); if (existProduct == null) { throw new BusinessException("Product not found"); } product.setId(id); updateById(product); return product; }

完整商品模块示例

ProductService 接口

package com.example.ecommerce.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.example.ecommerce.entity.Product; public interface ProductService extends IService<Product> { Page<Product> getProductList(Integer current, Integer size, Long categoryId); Product getProductDetail(Long id); Page<Product> searchProducts(String keyword, Long categoryId, String sortBy, Integer current, Integer size); Product createProduct(Product product); Product updateProduct(Long id, Product product); }

ProductController 完整示例

package com.example.ecommerce.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.example.ecommerce.common.Result; import com.example.ecommerce.entity.Product; import com.example.ecommerce.service.ProductService; import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/products") public class ProductController { @Autowired private ProductService productService; @GetMapping public Result<Page<Product>> getProductList( @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size, @RequestParam(required = false) Long categoryId ) { Page<Product> page = productService.getProductList(current, size, categoryId); return Result.success(page); } @GetMapping("/{id}") public Result<Product> getProductDetail(@PathVariable Long id) { Product product = productService.getProductDetail(id); return Result.success(product); } @GetMapping("/search") public Result<Page<Product>> searchProducts( @RequestParam(required = false) String keyword, @RequestParam(required = false) Long categoryId, @RequestParam(required = false) String sortBy, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size ) { Page<Product> page = productService.searchProducts(keyword, categoryId, sortBy, current, size); return Result.success(page); } @PostMapping public Result<Product> createProduct(@RequestBody @Valid Product product) { Product created = productService.createProduct(product); return Result.success("Product created successfully", created); } @PutMapping("/{id}") public Result<Product> updateProduct(@PathVariable Long id, @RequestBody @Valid Product product) { Product updated = productService.updateProduct(id, product); return Result.success("Product updated successfully", updated); } }

官方资源

本节小结

在本节中,我们实现了:

第一个是商品列表查询。 支持分页查询和分类筛选。

第二个是商品详情查询。 根据 ID 查询商品详情。

第三个是商品搜索。 支持关键词搜索、分类筛选和价格排序。

第四个是商品分类。 实现分类树结构查询。

这就是商品模块实现。商品模块提供了完整的商品管理功能,是商城系统的核心。

在下一节,我们将学习如何实现订单模块,包括订单创建、订单查询等功能。