一、买家端类目
1、创立实体类
首先创立实体类,这里先创立买家类目表的实体类。
@Data
@Entity
@DynamicUpdate
public class ProductCategory {
// 类目 id
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer categoryId;
// 类目名称
private String categoryName;
// 类目品种
private Integer categoryType;
// 类目创立工夫
private Date createTime;
// 类目更新工夫
private Date updateTime;
public ProductCategory(Integer categoryId, String categoryName, Integer categoryType) {
this.categoryId = categoryId;
this.categoryName = categoryName;
this.categoryType = categoryType;
}
public ProductCategory() {}
@Override
public String toString() {
return "ProductCategory{" +
"categoryId=" + categoryId +
", categoryName='" + categoryName + '\'' +
", categoryType=" + categoryType +
", createTime=" + createTime +
", updateTime=" + updateTime +
'}';
}
}
这里留神类名及属性名要与数据库表一一对应,这个类中为了晓得创立及更新工夫,退出了工夫参数,然而不是手动上传,而是自动更新的,所以要加上注解 @DynamicUpdate。
所以理论须要写的只有两个一个类目名称、一个类目类型,主键自增,写好这三个参数的构造方法,加上 Getter 和 Setter 办法,toString 办法,把他们用 @Entity 设置成实体类,在竹简上加上 @Id,并且设置为自增。
2、创立 dao 并测试
Dao 写成接口继承 Jpa 的接口。这样就能够间接应用 Jpa 中的办法了。
这里就要留神事实当中的业务场景了,查问类目类型,能够查问到所须要类型的 List 汇合了。(就相当于把所有类目都查出来,然而也可能只查一部分)
public interface ProductCategoryRepository extends JpaRepository<ProductCategory,Integer> {List<ProductCategory> findByCategoryTypeIn(List<Integer> categoryTypeList);
}
测试。点击类目右键 GO TO TEST 间接生成测试方法,如果不及时测试,报错都不晓得是哪个环节有问题。
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductCategoryRepositoryTest {
@Autowired
private ProductCategoryRepository repository;
// 测试保留
@Test
public void testSave(){ProductCategory productCategory = new ProductCategory();
productCategory.setCategoryName("增肌必备");
productCategory.setCategoryType(3);
ProductCategory pro = repository.save(productCategory);
Assert.assertNotEquals(0,pro);
}
// 测试查找一个
@Test
public void testFind(){ProductCategory productCategory = repository.findById(1).get();
Assert.assertNotNull(productCategory);
}
// 测试更新
@Test
public void testUpdate(){ProductCategory productCategory = new ProductCategory();
productCategory.setCategoryId(8);
productCategory.setCategoryName("丰胸必备");
productCategory.setCategoryType(6);
ProductCategory pro = repository.save(productCategory);
Assert.assertNotEquals(0,pro);
}
// 测试查找多个
@Test
public void testFindByCategoryTypeIn(){List<Integer> categoryTypeList = new ArrayList<>();
categoryTypeList.add(2);
categoryTypeList.add(3);
categoryTypeList.add(4);
categoryTypeList.add(5);
List<ProductCategory> byCategoryTypeIn = repository.findByCategoryTypeIn(categoryTypeList);
for (ProductCategory productCategory:byCategoryTypeIn){System.out.println(productCategory);
}
}
3、买家端 service 层
这里就是业务相干了, 查问所有类目用于卖家后盾操作,新增类目、更新类目同理,查问一条类目前面可用于显示所有商品等等,查问多条类目能够用于给买家展现以后有什么流动等等,如男生最爱,热销榜等等类目。
先写个 service 接口。
/**
* 类目表的 service 层接口
*/
public interface ProductCategoryService {
// 查问一条
ProductCategory findOne(Integer categoryId);
// 查问所有
List<ProductCategory> findAll();
// 查问多条
List<ProductCategory> findByCategoryTypeIn(List<Integer> categoryTypeList);
// 新增和更新
ProductCategory save(ProductCategory productCategory);
}
再写其实现类。
@Service
// 类目表的 service 层实现类
public class ProductCategoryServiceImpl implements ProductCategoryService {
@Autowired
private ProductCategoryRepository repository;
@Override
public ProductCategory findOne(Integer categoryId) {return repository.findById(categoryId).get();}
@Override
public List<ProductCategory> findAll() {return repository.findAll();
}
@Override
public List<ProductCategory> findByCategoryTypeIn(List<Integer> categoryTypeList) {return repository.findByCategoryTypeIn(categoryTypeList);
}
@Override
public ProductCategory save(ProductCategory productCategory) {return repository.save(productCategory);
}
}
最初进行测试。
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductCategoryRepositoryTest {
@Autowired
private ProductCategoryRepository repository;
@Test
public void testSave(){ProductCategory productCategory = new ProductCategory();
productCategory.setCategoryName("增肌必备");
productCategory.setCategoryType(3);
ProductCategory pro = repository.save(productCategory);
Assert.assertNotEquals(0,pro);
}
@Test
public void testFind(){ProductCategory productCategory = repository.findById(1).get();
Assert.assertNotNull(productCategory);
}
@Test
public void testUpdate(){ProductCategory productCategory = new ProductCategory();
productCategory.setCategoryId(8);
productCategory.setCategoryName("丰胸必备");
productCategory.setCategoryType(6);
ProductCategory pro = repository.save(productCategory);
Assert.assertNotEquals(0,pro);
}
@Test
public void testFindByCategoryTypeIn(){List<Integer> categoryTypeList = new ArrayList<>();
categoryTypeList.add(2);
categoryTypeList.add(3);
categoryTypeList.add(4);
categoryTypeList.add(5);
List<ProductCategory> byCategoryTypeIn = repository.findByCategoryTypeIn(categoryTypeList);
for (ProductCategory productCategory:byCategoryTypeIn){System.out.println(productCategory);
}
}
}
二、买家端商品
1、创立实体类
买家端商品也一样,次要是商品的增删改查。
生成产品的实体类
@Data
@Entity
public class ProductInfo {
// 商品 id
@Id
private String productId;
// 商品名称
private String productName;
// 商品价格
private BigDecimal productPrice;
// 商品库存
private Integer productStock;
// 商品形容
private String productDescription;
// 商品小图
private String productIcon;
// 商品类型
private Integer productStatus;
// 所属类目类型
private Integer categoryType;
/*// 创立工夫
private Date createTime;
// 更新工夫
private Date updateTime;*/
}
因为它是 String 类型的 id,所以不能自增。创立工夫和更新工夫先不写,加上 @Entity 注解和 id。
2、创立 dao 并测试
而后就是写 Dao 测试。
public interface ProductInfoRepository extends JpaRepository<ProductInfo,String> {
// 查问上架的商品
List<ProductInfo> findByProductStatus(Integer productStatus);
}
测试。
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductInfoRepositoryTest {
@Autowired
private ProductInfoRepository repository;
@Test
public void testSave(){ProductInfo productInfo = new ProductInfo();
productInfo.setProductId("123458");
productInfo.setProductName("鱼翅炒饭");
productInfo.setProductPrice(new BigDecimal(100.00));
productInfo.setProductStock(12);
productInfo.setProductDescription("鱼翅炒饭,尉迟炒的饭");
productInfo.setProductIcon("http://xxx.jpg");
productInfo.setCategoryType(3);
ProductInfo prod = repository.save(productInfo);
Assert.assertNotEquals(null,prod);
}
@Test
public void findByProductStatus() {List<ProductInfo> productInfos = repository.findByProductStatus(2);
productInfos.forEach(productInfo -> System.out.println(productInfo));
}
}
3、买家端商品 service 层
接口。
public interface ProductInfoService {
// 查问一个
ProductInfo findOne(String productId);
// 查问所有的商品
Page<ProductInfo> findAll(Pageable pageable);
// 查问所有在架的商品
List<ProductInfo> findUpAll();
// 保留
ProductInfo save(ProductInfo productInfo);
// 加库存
// 减库存
}
接口实现类。
@Service
public class ProductInfoServiceImpl implements ProductInfoService {
@Autowired
private ProductInfoRepository repository;
@Override
public ProductInfo findOne(String productId) {return repository.findById(productId).get();}
@Override
public Page<ProductInfo> findAll(Pageable pageable) {return repository.findAll(pageable);
}
@Override
public List<ProductInfo> findUpAll() {return repository.findByProductStatus(ProductStatusEnum.UP.getCode());
}
@Override
public ProductInfo save(ProductInfo productInfo) {return repository.save(productInfo);
}
}
测试方法。
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductInfoServiceImplTest {
@Autowired
private ProductInfoServiceImpl service;
@Test
public void findOne() {ProductInfo productInfo = service.findOne("123456");
Assert.assertEquals("123456",productInfo.getProductId());
}
@Test
public void findAll() {PageRequest request = PageRequest.of(0,2);
Page<ProductInfo> productInfos = service.findAll(request);
Assert.assertNotEquals(0,productInfos.getSize());
}
@Test
public void findUpAll() {List<ProductInfo> pr = service.findUpAll();
pr.forEach(productInfo -> System.out.println(productInfo));
}
@Test
public void save() {ProductInfo productInfo = new ProductInfo();
productInfo.setProductId("123459");
productInfo.setProductName("减肥餐");
productInfo.setProductPrice(new BigDecimal(20.9));
productInfo.setProductStock(100);
productInfo.setProductDescription("减肥餐,一顿减 10 斤");
productInfo.setProductIcon("http://xxxxxxx.jpg");
productInfo.setProductStatus(0);
productInfo.setCategoryType(0);
ProductInfo productInfo1 = service.save(productInfo);
Assert.assertNotEquals(null,productInfo1);
}
}
三、api
写完这两层就该写前后端接口的对应了,本示例前端提供了商品的对应 api,如果想实现前后端对应的话,就要依照这个形式来传递数据。
GET /sell/buyer/product/list
{
"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",
}
]
}
]
}
这里剖析一下,外层一个 code、msg、还有一个 data 的数组。data 中蕴含类目名称、类目类型、还有该类目下的所有商品、商品又包含 id 编号、名称、价格、形容和图片。所以依照这个写即可。
1、最外层
最外层也就是 code、msg、data 的数据。为了不便传输,创立一个返回前端的对象。这里如果一下子都写了太麻烦了,一层一层逻辑不好分清,所以先写个最外层 ResultVO 类(VO 就是 view object 的简写)。
/**
* http 申请返回的最外层对象
*/
@Data
public class ResultVO<T> {
//code 错误码
private Integer code;
//msg
private String msg;
// 对象
private T data;
}
而后写个 controller 并拜访。
@RestController
@RequestMapping("/buyer/product")
public class BuyerProductController {@RequestMapping("/list")
public ResultVO list(){ResultVO resultVO = new ResultVO();
return resultVO;
}
}
因为 api 中说了要拜访 /sell/buyer/product/list 地址,controller 中少了一层 /sell,所以咱们在 yaml 中配置一下后面的门路。
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://192.168.1.9:3306/sell?characterEncoding=utf-8&userSSL=false
jpa:
show-sql: true
server:
port: 8081
servlet:
context-path: /sell #次要是配置这个
这样启动并测试。为了让浏览器解析数据为 json 格局能够下载相干插件。
2、中间层
这样最外层就有了,上面该写中间层了,看一下下面 Json 格局中间层是我的项目的类目层。
中间层是类目层。还是老规矩,写个 ProductVo 类。
/**
* 其实是商品蕴含类目层
*/
@Data
public class ProductVO {@JsonProperty("name")
private String categoryName;
@JsonProperty("type")
private Integer categoryType;
@JsonProperty("food")
private List<ProductInfoVO> productInfoVOList;
}
3、最内层
/**
* 商品详情
*/
@Data
public class ProductInfoVO {@JsonProperty("id")
private String productId;
@JsonProperty("name")
private String productName;
@JsonProperty("price")
private BigDecimal productPrice;
@JsonProperty
private String productDescription;
@JsonProperty("icon")
private String productIcon;
}
这样写完当前,把他们关联起来并测试。
原代码改良如下:增加了一些数据进行测试。
@RequestMapping("/list")
public ResultVO list(){ResultVO resultVO = new ResultVO();
ProductVO productVO = new ProductVO();
ProductInfoVO productInfoVO = new ProductInfoVO();
productInfoVO.setProductId("123456");
productInfoVO.setProductName("皮蛋瘦肉粥");
productInfoVO.setProductPrice(new BigDecimal(11.00));
productInfoVO.setProductDescription("赵谦孙李, 粥无阵亡");
productInfoVO.setProductIcon("http:xxxx.jsp");
resultVO.setCode(0);
resultVO.setMsg("胜利");
resultVO.setData(productVO);
productVO.setCategoryName("热销榜");
productVO.setCategoryType(2);
productVO.setProductInfoVOList(Arrays.asList(productInfoVO));
return resultVO;
}
测试后果如下(忘了截图了,根本就是这个样子):
这样测试实现后阐明咱们能够通过这个进行传递 json 数据给前端了。
4、查询数据库传递给 json 对象
json 的路线搭建好之后,就该传递真正的数据了,也就是把数据传递给 controller。
@RestController
@RequestMapping("/buyer/product")
public class BuyerProductController {
@Autowired
private ProductInfoService productInfoService;
@Autowired
private ProductCategoryService productCategoryService;
@RequestMapping("/list")
public ResultVO list(){
//1、查问所有的上架商品
List<ProductInfo> productInfoUpAll = productInfoService.findUpAll();
//2、查问类目(要一次性查问)List<Integer> categoryTypeList = productInfoUpAll.stream().map(e -> e.getCategoryType()).collect(Collectors.toList());
List<ProductCategory> productCategoryList = productCategoryService.findByCategoryTypeIn(categoryTypeList);
//3、数据拼装
List<ProductVO> productVOList = new ArrayList<>();
for (ProductCategory productCategory:productCategoryList){ProductVO productVO = new ProductVO();
productVO.setCategoryName(productCategory.getCategoryName());
productVO.setCategoryType(productCategory.getCategoryType());
List<ProductInfoVO> productInfoVOList = new ArrayList<>();
for (ProductInfo productInfo:productInfoUpAll){
// 上面这步要好好了解
if (productInfo.getCategoryType().equals(productCategory.getCategoryType())) {ProductInfoVO productInfoVO = new ProductInfoVO();
//productInfoVO.setProductId(productInfo.getProductId());
//productInfoVO.setProductName(productInfo.getProductName());
//productInfoVO.setProductPrice(productInfo.getProductPrice());
//productInfoVO.setProductDescription(productInfo.getProductDescription());
//productInfoVO.setProductIcon(productInfo.getProductIcon());
BeanUtils.copyProperties(productInfo,productInfoVO);
productInfoVOList.add(productInfoVO);
}
}
productVO.setProductInfoVOList(productInfoVOList);
productVOList.add(productVO);
}
ResultVO resultVO = ResultVOUtil.success(productVOList);
return resultVO;
}
}
分层查问数据,并拼装起来传给 json。这里为了不便不必每次都创立 ResultVO 对象(因为没什么区别,步骤一样),创立了 ResultVOUtils 工具类。
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){ResultVO resultVO = new ResultVO();
resultVO.setCode(code);
resultVO.setMsg(msg);
return resultVO;
}
}
别离创立了它的传递胜利办法、传递失败办法。
查问果然查到了,如下面那张图。
5、和前端连贯显示页面
这里就须要以前连贯的虚拟机了,虚拟机 ip 地址是 192.168.1.9,连贯这个网址,能够连上,然而会立即跳转到失败页面,因为这时相当于没有登陆。
这里如果想登陆须要传递 openid 的值,所以轻易传递一个即可,先登陆一个不跳转的页面,192.168.1.9/#/order,在 console 控制台中写 document.cookie=‘openid=abc123’, 这样就传递了一个值用来证实曾经登陆。
这时再登陆 192.168.1.9,发现显示了页面。
这时候拜访不到是因为拜访的是虚拟机的地址,在虚拟机中批改 nginx 为本人本机电脑的 ip 地址。
vim /usr/local/nginx/conf/nginx.conf
在配置文件中批改。
这样就能够拜访了。