SpringBoot 企業微信點餐系統實戰三:商品資訊及買家商品api開發

solocoder發表於2018-08-19

這是【SpringBoot企業微信點餐系統實戰】系列第三篇

原始碼地址:github.com/cachecats/s…

SpringBoot 企業微信點餐系統實戰一:環境搭建和資料庫設計

SpringBoot 企業微信點餐系統實戰二:日誌配置、商品類目開發

一、商品資訊

1.1 商品資訊 dto

按照資料庫的欄位寫出對應的實體類 ProductInfo@Datalombok 的註解,用於自動生成 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);
    }
}
複製程式碼

二、商品資訊測試

商品資訊的 repositoryservice 都寫完了,養成好習慣,別忘了測試。

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 的縮寫吧…

返回結果有三層物件,最外層應該是整個專案統一的資料結構,我們定義為 ResultVOdata 欄位裡先是商品分類 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 , 除錯介面更加方便。下篇文章會專門講 swaggerSpring Boot 的整合。

3.3 驗證

開啟瀏覽器,輸入地址 http://127.0.0.1:8080/sell/buyer/product/list 可以看到正確返回了資料

SpringBoot 企業微信點餐系統實戰三:商品資訊及買家商品api開發


以上就是本節的內容,下期見~

原始碼地址:github.com/cachecats/s…

SpringBoot 企業微信點餐系統實戰一:環境搭建和資料庫設計

SpringBoot 企業微信點餐系統實戰二:日誌配置、商品類目開發

相關文章