后台管理系统搭建2 - SpringBoot 后台数据接口

来源:https://www.bilibili.com/video/BV1ki4y147oK?p=2

上一节链接:https://blog.csdn.net/qq_40893824/article/details/106960903
下一节链接:https://blog.csdn.net/qq_40893824/article/details/106996441

源码:
https://github.com/13407196713/layui-springboot

新建工程

1 新建 springboot 项目 layui-springBoot:






用新版 idea2020 重复之前的操作会有问题

没有红框部分,只有绿框部分
我直接删除本工程,重复之前的步骤,又正常了

2 在 pom 文件中,加入代码:

		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.3.1.tmp</version>
		</dependency>

后端连数据库 - product

3 layuispringboot 中创包 entity,其内创建 实体类 Product,加入代码:
数据类型 和 数据库对应

数据库中,若 数据名是 a_b
那 idea 中实体类中,对应数据名 命名规则是:a 部分不变,去掉下划线,b 部分首字母大写 即可

package com.southwind.entity;

import lombok.Data;

@Data
public class Product {
    private Integer id;
    private String name;
    private String description;
    private float price;
    private Integer stock;//库存
    private String categoryleveloneId;// 分类1
    private String categoryleveltwoId;// 分类2
    private String categorylevelthreeId;// 分类3
    private String fileName;
}

数据名 是小驼峰形式

4 在 layuispringboot 中,创包 mapper,放接口文件,其内创建 接口 ProductMapper,加入 extends BaseMapper<Product>

5 在 resources 中,删除 application.properties
在resources 中,新建 application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mmall?serverTimezone=UTC
    username: root
    password: 123456
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

其中 ?serverTimezone=UTC 是为了保持时区一致
mysql 的时区:中国的时区
idea 连接数据库的时区:世界 “标准” 时区,它比我们的时区早 8 小时

6 在启动类 southwind/ layuispringboot/ LayuiSpringbootApplication 中加入扫包操作代码:
@MapperScan("com.southwind.layuispringboot.mapper")

单元测试:
7 进入 layuispringboot/ mapper/ ProductMapper,右键单击代码中 文件名


加入代码:

package com.southwind.mapper;

import com.southwind.layuispringboot.mapper.ProductMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class ProductMapperTest {
    @Autowired
    private ProductMapper mapper;

    @Test
    void test(){
        mapper.selectList(null).forEach(System.out::println);
    }
}

修改前端代码数据

上图 前端部分 应该和 下图的数据库 数据结构 匹配:

改成(保留 3 组 相同的数据):

{
  "code": 0
  ,"msg": ""
  ,"count": 3000000
  ,"data": [{
    "id": "733"
    ,"name": "香奈儿"
    ,"description": "好闻的香水"
    ,"price": 152
    ,"stock": 978
    ,"categorylevelone": "化妆品"
	,"categoryleveltwo": "面部护理"
	,"categorylevelthree": "少女派"
    ,"fileName": "baby_1.jpg"
  }, {
    "id": "733"
    ,"name": "香奈儿"
    ,"description": "好闻的香水"
    ,"price": 152
    ,"stock": 978
    ,"categorylevelone": "化妆品"
    ,"categoryleveltwo": "面部护理"
    ,"categorylevelthree": "少女派"
    ,"fileName": "baby_1.jpg"
  }, {
    "id": "733"
    ,"name": "香奈儿"
    ,"description": "好闻的香水"
    ,"price": 152
    ,"stock": 978
    ,"categorylevelone": "化妆品"
    ,"categoryleveltwo": "面部护理"
    ,"categorylevelthree": "少女派"
    ,"fileName": "baby_1.jpg"
  }]
}

上图是页面部分代码,也要和 数据库数据类型 匹配,变成:

<!DOCTYPE html>
<html>
	<head>
	  <meta charset="utf-8">
	  <title>Layui</title>
	  <link rel="stylesheet" href=".//layui/css/layui.css"  media="all">
	  <!-- 注意:如果你直接复制所有代码到本地,上述css路径需要改成你本地的 -->
	</head>
<body>
 
	<table class="layui-hide" id="test" lay-filter="test"></table>
 
	<script type="text/html" id="toolbarDemo">
	  <div class="layui-btn-container">
		<button class="layui-btn layui-btn-sm" lay-event="getCheckData">获取选中行数据</button>
		<button class="layui-btn layui-btn-sm" lay-event="getCheckLength">获取选中数目</button>
		<button class="layui-btn layui-btn-sm" lay-event="isAll">验证是否全选</button>
	  </div>
	</script>
	<script type="text/html" id="barDemo">
	  <a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
	  <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
	</script>
              
          
	<script src=".//layui/layui.js" charset="utf-8"></script>
	<!-- 注意:如果你直接复制所有代码到本地,上述js路径需要改成你本地的 --> 
 
	<script>
	layui.use('table', function(){
	  var table = layui.table;
	  
	  //温馨提示:默认由前端自动合计当前行数据。从 layui 2.5.6 开始: 若接口直接返回了合计行数据,则优先读取接口合计行数据。
	  //详见:https://www.layui.com/doc/modules/table.html#totalRow
	  table.render({
		elem: '#test'
		,url:'data.json'
		,toolbar: '#toolbarDemo'
		,title: '用户数据表'
		,totalRow: true
		,cols: [[
		  {type: 'checkbox', fixed: 'left'}
		  ,{field:'id', title:'商品ID', width:100, fixed: 'left', unresize: true, sort: true, totalRowText: '合计'}
		  ,{field:'name', title:'用户名称', width:120, edit: 'text'}
		  ,{field:'description', title:'商品描述', width:150}
		  ,{field:'price', title:'商品价格', width:120, sort: true, totalRow: true}
		  ,{field:'stock', title:'商品库存', width:120, edit: 'text', sort: true}
		  ,{field:'categorylevelone', title:'1级分类', width:150}
		  ,{field:'categoryleveltwo', title:'2级分类', width:150}
		  ,{field:'categorylevelthree', title:'3级分类', width:150}
		  ,{field:'fileName', title:'商品图片'}
		  ,{fixed: 'right', title:'操作', toolbar: '#barDemo', width:150}
		]]
		,page: true
	  });
	  
	  //工具栏事件
	  table.on('toolbar(test)', function(obj){
		var checkStatus = table.checkStatus(obj.config.id);
		switch(obj.event){
		  case 'getCheckData':
			var data = checkStatus.data;
			layer.alert(JSON.stringify(data));
		  break;
		  case 'getCheckLength':
			var data = checkStatus.data;
			layer.msg('选中了:'+ data.length + ' 个');
		  break;
		  case 'isAll':
			layer.msg(checkStatus.isAll ? '全选': '未全选')
		  break;
		};
	  });
	  
	  //监听工具条
	    table.on('tool(test)', function(obj){
	      var data = obj.data;
	      if(obj.event === 'del'){
	        layer.confirm('真的删除行么', function(index){
	          obj.del();
	          layer.close(index);
	        });
	      } else if(obj.event === 'edit'){
	        layer.alert('编辑行:<br>'+ JSON.stringify(data))
	      }
	    });
	});
	</script>

</body>
</html>

后端连数据库 - product_category

1 在 entity 中新建 实体类 ProductCategory,加入代码:

package com.southwind.layuispringboot.entity;

import lombok.Data;

@Data
public class ProductCategory {
    private Integer id;
    private String name;
}

2 在 mapper 中新建 接口 ProductCategoryMapper,加入代码:
extends BaseMapper<ProductCategory>

3 测试接口,新建测试类 ProductCategoryMapperTest

ProductCategoryMapperTest 中,加入代码:

package com.southwind.layuispringboot.mapper;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class ProductCategoryMapperTest {
    @Autowired
    private ProductCategoryMapper mapper;

    @Test
    void test(){
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("id",655);
        System.out.println(mapper.selectOne(wrapper));
    }
}
查询成功!

后端创建 json 格式的数据

前端是 json 的数据,所以后端给前端的数据也要是 json 格式,而不是实体类 Product 格式,vo 上场
json 格式:

{
  "code": 0
  ,"msg": ""
  ,"count": 3000000
  ,"data": [{
    "id": "733"
    }]
}
code状态码
0 是正常
msg为空
表示:查询成功
count总数据量
data这里 类似 实体类 Product,但不完全相同!
123级分类 的名称 不对应相同

这就应该是 vo 的实体类!

1 在 layuispringboot 中 创包 vo,其内创建 实体类 DataVO,加入代码:

package com.southwind.layuispringboot.vo;

import lombok.Data;
import java.util.List;

@Data
public class DataVO<T> {
    private Integer code;
    private String msg;
    private Integer count;
    private List<T> data;
}

2 在 vo 中,新建 实体类 ProductVO,加入代码:

package com.southwind.layuispringboot.vo;

import lombok.Data;

@Data
public class ProductVO {
    private Integer id;
    private String name;
    private String description;
    private float price;
    private Integer stock;
    private String categorylevelone;
    private String categoryleveltwo;
    private String categorylevelthree;
    private String fileName;
}

3 在 layuispringboot 中,创包 service,其内 新建接口 ProductService,加入代码:

package com.southwind.layuispringboot.service;

import com.southwind.layuispringboot.vo.DataVO;
import com.southwind.layuispringboot.vo.ProductVO;

public interface ProductService {
    public DataVO<ProductVO> findData();
}

4 service 中,创包 impl,其内 创建实现类 ProductServiceImpl,加入代码:

package com.southwind.layuispringboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.southwind.layuispringboot.entity.Product;
import com.southwind.layuispringboot.entity.ProductCategory;
import com.southwind.layuispringboot.mapper.ProductCategoryMapper;
import com.southwind.layuispringboot.mapper.ProductMapper;
import com.southwind.layuispringboot.service.ProductService;
import com.southwind.layuispringboot.vo.DataVO;
import com.southwind.layuispringboot.vo.ProductVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class ProductServiceImpl implements ProductService {
    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductCategoryMapper productCategoryMapper;

    @Override
    public DataVO<ProductVO> findData() {
        DataVO dataVO = new DataVO();
        dataVO.setCode(0);
        dataVO.setMsg("");
        dataVO.setCount(productMapper.selectCount(null));

        List<Product> productList = productMapper.selectList(null);
        List<ProductVO> productVOList = new ArrayList<>();
        for (Product product : productList) {
            ProductVO productVO = new ProductVO();
            BeanUtils.copyProperties(product, productVO);// 参数1 赋给 参数2

            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("id", product.getCategoryleveloneId());
            ProductCategory productCategory = productCategoryMapper.selectOne(wrapper);
            if(productCategory != null){
                productVO.setCategorylevelone(productCategory.getName());
            }

            wrapper = new QueryWrapper();
            wrapper.eq("id", product.getCategoryleveltwoId());
            productCategory = productCategoryMapper.selectOne(wrapper);
            if(productCategory != null){
                productVO.setCategoryleveltwo(productCategory.getName());
            }

            wrapper = new QueryWrapper();
            wrapper.eq("id", product.getCategorylevelthreeId());
            productCategory = productCategoryMapper.selectOne(wrapper);
            if(productCategory != null){
                productVO.setCategorylevelthree(productCategory.getName());
            }

            productVOList.add(productVO);
        }
        dataVO.setData(productVOList);
        return dataVO;
    }
}

步骤:
code、msg、count 赋值
再用
BeanUtils.copyProperties(product, productVO);// 参数1 赋给 参数2
其中 1、2、3级分类 的名称有不同,要手动赋值
还要判断有无空的数据(连不上的数据,如 product 中分类 id 是1,去找分类数据表,发现 1 没有对应的分类名称,这就是空数据)

5 测试接口 ProductService:ProductServiceTest

加入代码:

package com.southwind.layuispringboot.service;

import com.southwind.layuispringboot.vo.DataVO;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class ProductServiceTest {
    @Autowired
    private ProductService service;

    @Test
    void findData(){
        DataVO dataVO = service.findData();
        int i = 0;
    }
}

int i = 0; 处,打上断点,debug 一下


是 json 格式的数据!

6 layuispringboot 中,创包 controller,其内 创建控制类 ProductController,加入代码:

package com.southwind.layuispringboot.controller;

import com.southwind.layuispringboot.service.ProductService;
import com.southwind.layuispringboot.vo.DataVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProductController {
    @Autowired
    private ProductService productService;

    @RequestMapping("/list")
    public DataVO list(){
        return productService.findData();
    }
}

解决跨域

layuispringboot 中,创包 config,其内 创建配置类 CrosConfig,加入代码:

ctrl + o

package com.southwind.layuispringboot.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CrosConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/*")
                .allowedOrigins("*")
                .allowCredentials(true)
                .allowedMethods("GET", "POST", "DELETE", "PUT","PATCH")
                .maxAge(3600);
    }
}

@Configuration 标注在类上,相当于把该类作为 xml 配置文件中的<beans>,作用为:配置spring容器(应用上下文)

启动 layuispringboot/ LayuiSpringbootApplication
进入:http://localhost:8080/list

这时候因为解决了跨域问题,Hbuild 中,前端页面就可以来调用 后端提供的 json 数据了

table.html 中:
url:'data.json' 改为 url:'http://localhost:8080/list'



红框部分是没有查到的,因为分类数据表中没有对应分类

分页

装一个 json 可视化插件

进入 http://localhost:8080/list

F12:

再 F5 刷新:

看到了分页:http://localhost:8080/list?page=1&limit=10

所以分页的 2 个 参数:page、limit

1 service/ ProductService 中,加入Integer page, Integer limit

2 DataVO 中:

这一步是为下一步中dataVO.setCount( Long result.getTotal()); 类型匹配

3 service/ impl/ ProductServiceImpl 中:

红框1、3 处,代码删除
加上红框2 处 的代码:

        IPage<Product> productIPage = new Page<>(page, limit);
        IPage<Product> result =  productMapper.selectPage(productIPage, null);
        dataVO.setCount(result.getTotal());
        List<Product> productList = result.getRecords();

4 拦截器:config 中,新建 配置类 MyBatisPlusConfig,加入代码:

package com.southwind.layuispringboot.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisPlusConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        return new PaginationInterceptor();
    }
}

5 controller/ ProductController 中:
Integer page, Integer limit

6 测试类 ProductServiceTest 中:
注释掉:

7 重启 layuispringboot/ LayuiSpringbootApplication
进入 http://localhost:8080/list?page=1&limit=2

成功分页!

上一节链接:https://blog.csdn.net/qq_40893824/article/details/106960903
下一节链接:https://blog.csdn.net/qq_40893824/article/details/106996441

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_1403034144

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值