這是【SpringBoot企業微信點餐系統實戰】系列第三篇
原始碼地址:github.com/cachecats/s…
SpringBoot 企業微信點餐系統實戰一:環境搭建和資料庫設計
SpringBoot 企業微信點餐系統實戰二:日誌配置、商品類目開發
一、商品資訊
1.1 商品資訊 dto
按照資料庫的欄位寫出對應的實體類 ProductInfo
。@Data
是 lombok
的註解,用於自動生成 getter
, setter
, toString
方法,不懂的可以自行查詢相關資料。
@Entity
@Data
public class ProductInfo {
@Id
private String productId;
//商品名字
private String productName;
//商品價格
private BigDecimal productPrice;
//商品庫存
private Integer productStock;
//商品描述
private String productDescription;
//商品狀態
private Integer productStatus;
//商品圖示
private String productIcon;
//商品類目編號
private Integer categoryType;
public ProductInfo() {
}
}
複製程式碼
1.2 商品資訊repository
新加了一個方法 findByProductStatus
,根據商品的狀態查詢商品列表,用於查詢所有上架商品。
package com.solo.sell.repository;
import com.solo.sell.dto.ProductInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ProductInfoRepository extends JpaRepository<ProductInfo, String>{
List<ProductInfo> findByProductStatus(Integer status);
}
複製程式碼
1.3 商品資訊 service
暫時先想到以下幾個方法,做到後面不夠了再加。加庫存和減庫存後面再實現。
package com.solo.sell.service;
import com.solo.sell.dto.ProductInfo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.util.List;
public interface ProductInfoService {
/**
* 通過id查詢單個商品
* @param id
* @return
*/
ProductInfo findById(String id);
/**
* 查詢上架的產品
* @return
*/
List<ProductInfo> findUpAll();
/**
* 查詢所有商品 帶分頁
* @param pageable
* @return
*/
Page<ProductInfo> findAll(Pageable pageable);
/**
* 儲存一個商品
* @param productInfo
* @return
*/
ProductInfo save(ProductInfo productInfo);
//加庫存
//減庫存
}
複製程式碼
實現類 ProductInfoServiceImpl
package com.solo.sell.service.impl;
import com.solo.sell.dto.ProductInfo;
import com.solo.sell.enums.ProductStatusEnum;
import com.solo.sell.repository.ProductInfoRepository;
import com.solo.sell.service.ProductInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProductInfoServiceImpl implements ProductInfoService {
@Autowired
private ProductInfoRepository repository;
@Override
public ProductInfo findById(String id) {
return repository.findById(id).get();
}
@Override
public List<ProductInfo> findUpAll() {
return repository.findByProductStatus(ProductStatusEnum.UP.getCode());
}
@Override
public Page<ProductInfo> findAll(Pageable pageable) {
return repository.findAll(pageable);
}
@Override
public ProductInfo save(ProductInfo productInfo) {
return repository.save(productInfo);
}
}
複製程式碼
二、商品資訊測試
商品資訊的 repository
和 service
都寫完了,養成好習慣,別忘了測試。
2.1 repository 測試
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductInfoRepositoryTest {
@Autowired
private ProductInfoRepository repository;
@Test
public void add(){
ProductInfo info = new ProductInfo();
info.setProductId("haha123");
info.setProductName("酸菜魚");
info.setProductPrice(new BigDecimal(36));
info.setProductDescription("好吃的酸菜魚,不可錯過");
info.setProductIcon("http://abc.png");
info.setProductStatus(0);
info.setProductStock(10);
info.setCategoryType(3);
ProductInfo result = repository.save(info);
Assert.assertNotNull(result);
}
@Test
public void findOne(){
ProductInfo info = repository.findById("haha123").get();
Assert.assertEquals("haha123", info.getProductId());
}
@Test
public void findByProductStatus() {
List<ProductInfo> list = repository.findByProductStatus(0);
Assert.assertNotEquals(0, list.size());
}
}
複製程式碼
2.2 service 測試
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductInfoServiceImplTest {
@Autowired
private ProductInfoServiceImpl service;
@Test
public void findById() {
ProductInfo info = service.findById("haha123");
Assert.assertEquals("haha123", info.getProductId());
}
@Test
public void findUpAll() {
List<ProductInfo> all = service.findUpAll();
Assert.assertNotEquals(0, all.size());
}
@Test
public void findAll() {
PageRequest pageRequest = PageRequest.of(0, 3);
Page<ProductInfo> productInfoPage = service.findAll(pageRequest);
Assert.assertNotEquals(0, productInfoPage.getTotalElements());
}
@Test
public void save() {
ProductInfo info = new ProductInfo();
info.setProductId("haha456");
info.setProductName("皮皮蝦");
info.setProductPrice(new BigDecimal(49));
info.setProductDescription("皮皮蝦我們走");
info.setProductIcon("http://abc.png");
info.setProductStatus(0);
info.setProductStock(99);
info.setCategoryType(4);
ProductInfo save = service.save(info);
Assert.assertNotNull(save);
}
}
複製程式碼
三、買家商品 api 開發
商品分類和商品資訊開發完之後,就可以開發買家 api 了。
買家最簡單的一個需求就是查詢上架商品列表,先實現這個功能。
3.1 返回結果分析
本來返回的資料格式應該是後端定的,但這個專案是先有的前端,已經規定好了資料格式,看看資料格式是什麼樣的吧
{
"code": 0,
"msg": "成功",
"data": [
{
"name": "熱榜",
"type": 1,
"foods": [
{
"id": "123456",
"name": "皮蛋粥",
"price": 1.2,
"description": "好吃的皮蛋粥",
"icon": "http://xxx.com",
}
]
},
{
"name": "好吃的",
"type": 2,
"foods": [
{
"id": "123457",
"name": "慕斯蛋糕",
"price": 10.9,
"description": "美味爽口",
"icon": "http://xxx.com",
}
]
}
]
}
複製程式碼
先約定一下所有返回給前端的物件都放在 VO
包下,物件名以 VO
結尾便於區分。猜測 VO
應該是 view object
的縮寫吧…
返回結果有三層物件,最外層應該是整個專案統一的資料結構,我們定義為 ResultVO
。data
欄位裡先是商品分類 ProdoctVO
,然後每個分類裡的 foods
欄位才是具體商品 ProductInfoVO
。
統一返回結果 ResultVO
package com.solo.sell.VO;
import lombok.Data;
/**
* 返回的統一結果格式
* @param <T>
*/
@Data
public class ResultVO<T> {
/** 狀態碼 */
private Integer code;
/** 返回資訊 */
private String msg;
/** 返回資料 */
private T data;
public ResultVO() {}
}
複製程式碼
返回商品物件 ProductVO
package com.solo.sell.VO;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* 商品資訊(包含類目)
*/
@Data
public class ProductVO {
@JsonProperty("name")
private String categoryName;
@JsonProperty("type")
private Integer categoryType;
@JsonProperty("foods")
private List<ProductInfoVO> productInfoVOList ;
}
複製程式碼
屬性名儘量起的一看就知道是什麼,不要只是叫 name
,時間久了不知道具體指哪個name
了。
但返回的資料就叫 name
怎麼辦呢?在屬性上面加個註解 @JsonProperty("name")
,這樣對應的屬性名就是 name
了。
返回的商品資訊 ProductInfoVO
package com.solo.sell.VO;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class ProductInfoVO {
@JsonProperty("id")
private String productId;
@JsonProperty("name")
private String productName;
@JsonProperty("price")
private BigDecimal productPrice;
@JsonProperty("description")
private String productDescription;
@JsonProperty("icon")
private String productIcon;
}
複製程式碼
3.2 買家商品 controller
返回結果格式知道了,就開始寫 controller
邏輯啦。
所有的 controller
都放在 controller
包下,新建 controller
包,然後新建 BuyerProductController
package com.solo.sell.controller;
import com.solo.sell.VO.ProductInfoVO;
import com.solo.sell.VO.ProductVO;
import com.solo.sell.VO.ResultVO;
import com.solo.sell.dto.ProductCategory;
import com.solo.sell.dto.ProductInfo;
import com.solo.sell.service.ProductCategoryService;
import com.solo.sell.service.ProductInfoService;
import com.solo.sell.utils.ResultVOUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/buyer/product")
@Api("買家端獲取商品")
public class BuyerProductController {
@Autowired
private ProductInfoService productInfoService;
@Autowired
private ProductCategoryService categoryService;
@ApiOperation(value = "獲取所有上架商品", notes = "獲取所有上架商品,下架商品除外")
@RequestMapping(value = "/list", method = RequestMethod.GET)
public ResultVO list() {
// 1.查詢所有上架商品
List<ProductInfo> productInfoList = productInfoService.findUpAll();
// 2.查詢類目(一次性查詢)
//用 java8 的特性獲取到上架商品的所有型別
List<Integer> categoryTypes = productInfoList.stream().map(e -> e.getCategoryType()).collect(Collectors.toList());
List<ProductCategory> productCategoryList = categoryService.findByCategoryTypeIn(categoryTypes);
List<ProductVO> productVOList = new ArrayList<>();
//資料拼裝
for (ProductCategory category : productCategoryList) {
ProductVO productVO = new ProductVO();
//屬性拷貝
BeanUtils.copyProperties(category, productVO);
//把型別匹配的商品新增進去
List<ProductInfoVO> productInfoVOList = new ArrayList<>();
for (ProductInfo productInfo : productInfoList) {
if (productInfo.getCategoryType().equals(category.getCategoryType())) {
ProductInfoVO productInfoVO = new ProductInfoVO();
BeanUtils.copyProperties(productInfo, productInfoVO);
productInfoVOList.add(productInfoVO);
}
}
productVO.setProductInfoVOList(productInfoVOList);
productVOList.add(productVO);
}
return ResultVOUtils.success(productVOList);
}
}
複製程式碼
註釋寫的比較詳細就不多解釋了,就是按照前端要求的格式把資料拼接在一起。
@Api
和 @ApiOperation
註解可以先不用管,這是整合了 swagger
, 除錯介面更加方便。下篇文章會專門講 swagger
和 Spring Boot
的整合。
3.3 驗證
開啟瀏覽器,輸入地址 http://127.0.0.1:8080/sell/buyer/product/list
可以看到正確返回了資料
以上就是本節的內容,下期見~
原始碼地址:github.com/cachecats/s…