SpringBoot微信点餐系统—6、卖家端的开发-买家商品

 

6.1新建一个商品对象

注意productId是String类型,不用自增长

package com.imooc.sell.dataobject;

import lombok.Data;
import org.hibernate.annotations.Proxy;

import javax.persistence.Entity;
import javax.persistence.Id;
import java.math.BigDecimal;

@Entity
@Data
@Proxy(lazy = false)
public class ProductInfo {

    @Id
    private String productId;

    /** 名字. */
    private String productName;

    /** 单价. */
    private BigDecimal productPrice;

    /** 库存. */
    private Integer productStock;

    /** 描述. */
    private String productDescription;

    /** 小图. */
    private String productIcon;

    /** 状态,0正常1下架. */
    private Integer categoryStatus;

    /** 类目编号. */
    private Integer categoryType;


}

6.2Dao层

6.2.1ProductInfoRepository接口

package com.imooc.sell.repository;

import com.imooc.sell.dataobject.ProductInfo;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface ProductInfoRepository extends JpaRepository{

    List findByCategoryStatus(Integer productStatus);
}

6.2.2单元测试

package com.imooc.sell.repository;

import com.imooc.sell.dataobject.ProductInfo;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.math.BigDecimal;
import java.util.List;

import static org.junit.Assert.*;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductInfoRepositoryTest {

    @Autowired
    private ProductInfoRepository repository;

    @Test
    public void saveTest(){
        ProductInfo productInfo=new ProductInfo();
        productInfo.setProductId("123456");
        productInfo.setProductName("皮蛋粥");
        productInfo.setProductPrice(new BigDecimal(3.2));
        productInfo.setProductStock(100);
        productInfo.setProductDescription("很好喝的粥");
        productInfo.setProductIcon("http://xxxxx.jps");
        productInfo.setCategoryStatus(0);
        productInfo.setCategoryType(2);

        ProductInfo result= repository.save(productInfo);
        Assert.assertNotNull(result);
    }

    @Test
    public void findByProductStatus(){
        List productInfoList=repository.findByCategoryStatus(0);
        Assert.assertNotEquals(0,productInfoList.size());
    }
}

6.3 Service层

6.3.1 ProductService接口

package com.imooc.sell.service;

import com.imooc.sell.dataobject.ProductInfo;
import org.springframework.data.domain.Pageable;

import java.util.List;

public interface ProductService {

    /**
     * 查询所有在架商品
     * @param productId
     * @return
     */
    ProductInfo findOne(String productId);

    List findUpAll();

    //查找所有商品 需要分页 注意使用的pageable是org.springframework.data.domain.Pageable这个包的
    List findAll(Pageable pageable);

    ProductInfo save(ProductInfo productInfo);

    //加库存(后面添加)

    //减库存(后面添加)
}

6.3.2 ProductServiceImpl实现

6.3.2.1这里注意其中一个方法findUpAll查询上架商品的实现

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第1张图片

我们会发现我们传入的数值“0”,不是很容易搞清是什么值,这里我们可以使用枚举。

 

在enums包下建一个枚举ProductStatusEnum

package com.imooc.sell.enums;

import lombok.Getter;

/**
 * 商品状态
 */

@Getter //自动生成get方法
public enum ProductStatusEnum {

    UP(0, "在架"),
    DOWN(1, "下架")
    ;

    private Integer code;

    private String message;

    ProductStatusEnum(Integer code,String message) {
        this.code = code;
        this.message = message;
    }
}

之前传入的0可写为ProductStatusEnum.UP.getCode()

 

6.3.2.2注意查找所有商品这个方法

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第2张图片

由于需要分页我们传入了pageable,他返回的是一个对象而不是list,所以要将List改为page对象,同样接口也要修改

 

6.3.2.3 代码

package com.imooc.sell.service.service.impl;

import com.imooc.sell.dataobject.ProductInfo;
import com.imooc.sell.enums.ProductStatusEnum;
import com.imooc.sell.repository.ProductInfoRepository;
import com.imooc.sell.service.ProductService;
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 ProductServiceImpl implements ProductService {

    @Autowired
    private ProductInfoRepository repository;

    @Override
    public ProductInfo findOne(String productId) {
        return repository.getOne(productId);
    }

    @Override
    public List findUpAll() {
        return repository.findByCategoryStatus(ProductStatusEnum.UP.getCode());
    }

    @Override
    public Page findAll(Pageable pageable) {
        return repository.findAll(pageable);
    }

    @Override
    public ProductInfo save(ProductInfo productInfo) {

        return repository.save(productInfo);
    }
}

6.3.3单元测试

package com.imooc.sell.service;

import com.imooc.sell.dataobject.ProductInfo;
import com.imooc.sell.enums.ProductStatusEnum;
import com.imooc.sell.service.impl.ProductServiceImpl;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.junit4.SpringRunner;

import java.math.BigDecimal;
import java.util.List;

import static org.junit.Assert.*;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductServiceImplTest {

    @Autowired
    private ProductServiceImpl productService;

    @Test
    public void findOne() {
        ProductInfo productInfo=productService.findOne("123456");
        Assert.assertEquals("123456",productInfo.getProductId());
    }

    @Test
    public void findUpAll() {
        List list=productService.findUpAll();
        Assert.assertNotEquals(0,list.size());
    }

    @Test
    public void findAll() {
        PageRequest request=new PageRequest(0,2);
        Page productInfoPage=productService.findAll(request);
        //System.out.print(productInfoPage.getTotalElements());
        Assert.assertNotEquals(0,productInfoPage.getTotalElements());
    }

    @Test
    public void save() {
        ProductInfo productInfo=new ProductInfo();
        productInfo.setProductId("12345");
        productInfo.setProductName("皮皮虾");
        productInfo.setProductPrice(new BigDecimal(3.2));
        productInfo.setProductStock(100);
        productInfo.setProductDescription("很好吃的虾");
        productInfo.setProductIcon("http://xxxxx.jps");
        productInfo.setCategoryStatus(ProductStatusEnum.DOWN.getCode());
        productInfo.setCategoryType(2);

        ProductInfo result=productService.save(productInfo);
        Assert.assertNotNull(result);
    }

6.4 Controller层

根据API需要先配置下包名

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第3张图片

在appliction.yml中添加如下配置

 

6.4.1 BuyerProductController

6.4.1.1API

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第4张图片

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第5张图片

6.4.1.2根据API我们在VO(ViewObject视图对象)包中创建一个resultVO接收最外层对象

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第6张图片

package com.imooc.sell.VO;

import lombok.Data;

/**
 * http请求返回的最外层对象
 * @param 
 */
@Data
public class ResultVO {

    /** 错误码. */
    private Integer code;

    /** 提示信息. */
    private String msg;

    /** 具体内容.
     * 返回的是对象,用泛型来接收
     * */ 
    private T data;
}

测试一下

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第7张图片

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第8张图片

报错:The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the

 

原因:远程数据库没启

https://blog.csdn.net/txwtech/article/details/80795633

6.4.1.3 ProductVO

再起一个对象ProductVO。注意ProductVO跟ProductInfo属性是不大一样的。

为什么不用ProductInfo这个对象?其实原则上前端需要几个字段你就给它返回几个字段,不要返回那么多的内容。原因上呢是出于安全以及引资上的一些考虑。

例如商品对象ProductInfo的库存返回给前端,你的竞争对手就可以看到你有多少库存了。这个其实对自己的产品是一个很危险的行为。或者是上下架,总之都是一些不安全的行为。不光是技术上,还有产品、引资上都是不安全的。这就是为什么我们要重新建一个对象的原因。

package com.imooc.sell.VO;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.util.List;

/**
 * 商品(包含类目)
 */
@Data
public class ProductVO {

    @JsonProperty("name")//返回给前端,这样子再把对象序列化的时候返回给前端它就是一个name了。
    private String categoryName;

    @JsonProperty("type")//明确是什么名字,类目的名字那就是categoryName
    private Integer categoryType;

    @JsonProperty("foods")
    private List productInfoVOList;
}

6.4.1.4ProductInfoVO

package com.imooc.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;
}

测试一下(在浏览器上安装JsonView格式可查看json格式)

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第9张图片

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第10张图片

6.4.1.5查询数据库

我们看一下如果要从数据库中查出来并展示要做什么事呢

 

第一点,我们应该能想到查询所有上架的商品,因为这个地方不需要分页,所以我们直接查询所有的

第二点,是查询类目,注意一点是我们肯定查询的是我们需要的,注意一定要一次性查询,你不能查询出十条商品,进行一个for循环,再去查10次的类目,你那样查询耗时就久了。为了性能的提升,一定要一次性的查询。

第三点,那就是数据拼装了,我们要把数据拼装成跟演示的JSON格式那样子。

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第11张图片

下面进行逐一的编写

 

查询商品,用到ProductService。

 

查询类目,用到CategoryService。lambda表达式很强大,它可以做很多很多事情。比如说如果要进行一些过滤的话,那么这个用起来也是特别的爽。现在Java 9都出来了,所以我觉得Java 8你在生产环境上都可以用了。作者的公司就在用Java 8,并且项目里面也会有lambda表达式。

 

productInfoVO要设置五个值,代码不够优雅,有点啰嗦。Spring提供了一个BeanUtils这个类,可以把productInfo的值拷贝到productInfoVO。

package com.imooc.sell.controller;

import com.imooc.sell.VO.ProductInfoVO;
import com.imooc.sell.VO.ProductVO;
import com.imooc.sell.VO.ResultVO;
import com.imooc.sell.dataobject.ProductCategory;
import com.imooc.sell.dataobject.ProductInfo;
import com.imooc.sell.service.CategoryService;
import com.imooc.sell.service.ProductService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 买家商品
 * Created by zhongzh
 * 2018-05-28 14:42
 *
 */
@RestController//返回的是JSON格式,所以这里写@RestController
@RequestMapping("/buyer/product")//给它一个URL的前缀,我这个URL前缀其实跟类名很相似
public class BuyerProductController {

    @Autowired
    private ProductService productService;

    @Autowired
    private CategoryService categoryService;

    @GetMapping("/list")//Get请求,list,返回为null
    public ResultVO list(){
        //1. 查询所有的上架商品
        List productInfoList = productService.findUpAll();

        //2. 查询类目(一次性查询)
        //List categoryTypeList = new ArrayList<>();
        //传统方法
          /*for (ProductInfo productInfo : productInfoList) {
              categoryTypeList.add(productInfo.getCategoryType());
          }*/
        //精简方法(java8, lambda表达式)
        List categoryTypeList = productInfoList.stream()
                .map(e -> e.getCategoryType())
                .collect(Collectors.toList());
        List productCategoryList = categoryService.findByCategoryTypeIn(categoryTypeList);

        //3. 数据拼装
        List productVOList = new ArrayList<>();
        for(ProductCategory productCategory : productCategoryList){
            ProductVO productVO = new ProductVO();
            productVO.setCategoryType(productCategory.getCategoryType());
            productVO.setCategoryName(productCategory.getCategoryName());
            //productVO.setProductInfoVOList();

            List productInfoVOList = new ArrayList<>();
            //遍历商品详情
            for(ProductInfo productInfo : productInfoList) {
                if(productInfo.getCategoryType().equals(productCategory.getCategoryType())){
                    //根据类目的Type来判断是否相等,相等才做
                    ProductInfoVO productInfoVO = new ProductInfoVO();
                    //productInfoVO.set
                    //一般是要设置五个值
//                    productInfoVO.setProductId(productInfo.getProductId());
//                    productInfoVO.setProductName(productInfo.getProductName());
//                    productInfoVO.setProductPrice(productInfo.getProductPrice());
//                    productInfoVO.setProductIcon(productInfo.getProductIcon());
//                    productInfoVO.setProductDescription(productInfo.getProductDescription());
                    //精简方法
                    BeanUtils.copyProperties(productInfo,productInfoVO);
                    productInfoVOList.add(productInfoVO);
                }
            }
            productVO.setProductInfoVOList(productInfoVOList);
            productVOList.add(productVO);
        }


        ResultVO resultVO = new ResultVO();
        resultVO.setCode(0);
        resultVO.setMsg("成功");
        /**
         ProductVO productVO = new ProductVO();
         ProductInfoVO productInfoVO = new ProductInfoVO();
         productVO.setProductInfoVOList(Arrays.asList(productInfoVO));
         */
        //resultVO.setData(productVO);
        //resultVO.setData(Arrays.asList(productVO));
        resultVO.setData(productVOList);
        return resultVO;
    }

}

测试一下

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第12张图片

第一步和第二步都是数据库的查询,我们把数据库查出来之后呢,然后再在代码里面把它拼装。最需要提醒大家的一点是,不要把数据库的查询放到for循环里面去。这样子你一旦循环的数目过大,比如说你要循环一万条,那么能进行一万次数据库的查询,这个时间开销是很大的,承受不起。你一个接口返回ResultVO对象都要这样来写,先new然后再set进去。这样写有点麻烦,把它封装一下。写一个utils包。ResultVOUtil写几个静态方法吧。

package com.imooc.sell.utils;

import com.imooc.sell.VO.ResultVO;

public class ResultVOUtil {
    public static ResultVO success(Object object){
        ResultVO resultVO=new ResultVO();
        resultVO.setCode(0);
        resultVO.setMsg("成功");
        resultVO.setData(object);
        return  resultVO;
    }

    public static  ResultVO success(){ //有可能什么数据都不传
        return success(null);
    }

    public  static  ResultVO error(Integer code,String msg){ //出错时,调用error方法
        ResultVO resultVO=new ResultVO();
        resultVO.setMsg(msg);
        resultVO.setCode(code);
        return resultVO;
    }
}

之前的代码就简单一些了,你也不需要new和set

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第13张图片

6.4.1.5尝试访问

没有问题。现在跟前端联调起来。现在访问一下虚拟机,发现它会跳转

 

 

 

 

 

为什么会做这么个逻辑,到后面的微信授权会讲到,现在只要设置一下cookie,让他能正常访问,我们看一下api是否生效就好了

 

我们可以先这么来做

先访问192.168.204.128/#/order,这一页没有对cookie的判断

 

在控制台设置一下cookie

cookie的值随便写(推荐用谷歌浏览器)

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第14张图片

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第15张图片

再访问下虚拟机

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第16张图片

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第17张图片

 

 
 

访问的url为虚拟机地址,需要改为本机地址

 

修改虚拟机ngin配置

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第18张图片

nginx -s reload 重启一下

 

刷新页面

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第19张图片

将地址改为域名

还是更改nginx配置

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第20张图片

修改hosts文件(使用SwitchHosts工具)

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第21张图片

重新访问,地址sell.com

SpringBoot微信点餐系统—6、卖家端的开发-买家商品_第22张图片

Tips:快捷键ctrl + alt + v 自动填充变量

 

 

欢迎进群交流258897306或关注公众号“IT群英汇

你可能感兴趣的:(springboot)