1 概述

通过Java基础的学习,我们进行一个实战项目:实现一个用户模块的增删改查。

2 技术选型

后台框架:SpringBoot 2.4.3
数据库:H2内置数据库
ORM:Mybatis-Plus 参考文档:https://mp.baomidou.com/guide/
前端:Layui 2.5.7 参考文档:https://www.layui.com/doc/
开发工具:IDEA2020.3

3 开发步骤

3.1 SpringBoot框架搭建

使用idea在线方式直接搭建。

  • 步骤一:新建工程
    File --> New -->Projet
  • springboot 增删改查 redis springboot+layui增删改查_数据库

  • 步骤二:选择在线搭建
    左侧选择Spring Initializr,右边选择 Default,点击 Next
  • springboot 增删改查 redis springboot+layui增删改查_layui_02

  • 步骤三:初始化设置
    初始化设置,如图
  • springboot 增删改查 redis springboot+layui增删改查_数据库_03

  • 步骤四:选择依赖的jar包
    Developer Tools --> Lombok;Web–>Spring Web;SQL–>H2 Database
  • springboot 增删改查 redis springboot+layui增删改查_User_04

springboot 增删改查 redis springboot+layui增删改查_User_05

springboot 增删改查 redis springboot+layui增删改查_数据库_06

  • 步骤五:设置项目名和项目路径
  • springboot 增删改查 redis springboot+layui增删改查_layui_07

  • 步骤六:检查是否工程是否正常
  • springboot 增删改查 redis springboot+layui增删改查_spring_08

3.2 工程目录结构

我们按照标准工程,创建目录如下:

springboot 增删改查 redis springboot+layui增删改查_layui_09

3.3 Mybatis-plus、H2使用

按照如下结构创建或修改文件:

springboot 增删改查 redis springboot+layui增删改查_数据库_10

修改pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.aiowang</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sml</name>
    <description>springboot+mybatis-plus+Layui</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

修改配置文件:

# DataSource Config
spring:
  datasource:
    driver-class-name: org.h2.Driver
    schema: classpath:db/schema-h2.sql
    data: classpath:db/data-h2.sql
    url: jdbc:h2:./data/test
    username: root
    password: 123456
    initialization-mode: always
  h2:
    console:
      path: /h2-console
      enabled: true

新增数据库初始脚本
data-h2.sql:

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

schema-h2.sql:

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
    id VARCHAR(32) NOT NULL COMMENT '主键ID',
    name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    age INT(11) NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
);

控制层controller:

package com.aiowang.sml.controller;

import com.aiowang.sml.domain.User;
import com.aiowang.sml.service.UserService;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * @author aiowang
 * @description:
 * @date 2021/3/11 22:04
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;


    /**
     * 新增
     *
     * @param user 对象
     * @return 返回
     */
    @PostMapping(value = "")
    public Boolean add(@RequestBody User user) {

        try {
            user.setId(UUID.randomUUID().toString().replaceAll("-",""));
            userService.save(user);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据id删除
     *
     * @param id 实体id
     * @return 成功标识
     */
    @DeleteMapping(value = "/{id}")
    public Boolean delete(@PathVariable("id") String id) {
        try {
            userService.removeById(id);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @DeleteMapping(value = "")
    public Boolean delete(@RequestBody User[] users) {
        try {
            List<String> ids = new ArrayList<>();
            Arrays.stream(users).forEach(s->{
                ids.add(s.getId());
            });
            userService.removeByIds(ids);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 更新
     *
     * @param user 对象
     * @return 成功标识
     */
    @PutMapping(value = "")
    public Boolean edit( @RequestBody User user) {
        try {
            userService.updateById(user);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据id查询
     *
     * @param id 实体id
     * @return 成功标识
     */
    @GetMapping(value = "/{id}")
    public User key(@PathVariable("id") String id) {
        try {
            return userService.getById(id);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 分页查询
     *
     * @return ResponseVO-分页实体
     */
    @GetMapping(value = "")
    public IPage<User> page(Integer offset,Integer limit,String name) {
        Page<User> page = new Page<>(offset,limit);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(name!=null, "name", name);
        return userService.page(page,queryWrapper);

    }
}

实体层domain:

package com.aiowang.sml.domain;

import lombok.Data;

/**
 * @author aiowang
 * @description:
 * @date 2021/3/10 22:38
 */
@Data
public class User {
    private static final long serialVersionUID = 1L;
    private String id;
    private String name;
    private Integer age;
    private String email;
}

mapper层:

package com.aiowang.sml.mapper;

import com.aiowang.sml.domain.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * @author aiowang
 * @description:
 * @date 2021/3/10 22:38
 */
public interface UserMapper extends BaseMapper<User> {

}

service层

package com.aiowang.sml.service;

import com.aiowang.sml.domain.User;
import com.baomidou.mybatisplus.extension.service.IService;

/**
 * @author aiowang
 * @description:
 * @date 2021/3/11 21:56
 */
public interface UserService extends IService<User> {
}

service实现层

package com.aiowang.sml.service.impl;

import com.aiowang.sml.domain.User;
import com.aiowang.sml.mapper.UserMapper;
import com.aiowang.sml.service.UserService;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Map;
import java.util.function.Function;

/**
 * @author aiowang
 * @description:
 * @date 2021/3/11 21:56
 */
@Service
public  class  UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

}

config:

package com.aiowang.sml.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author aiowang
 * @description:
 * @date 2021/3/11 22:28
 */
@Configuration
@MapperScan("com.aiowang.sml.mapper")
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
        return interceptor;
    }

}

修改启动类SmlApplication

package com.aiowang.sml;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.aiowang.sml.mapper")
public class SmlApplication {

    public static void main(String[] args) {
        SpringApplication.run(SmlApplication.class, args);
    }

}

此时,后台业务代码已开发完毕,可以使用postman进行接口测试了。

3.4 前端Layuiadmin前端实现

我们使用layuiadmin,需要实现下载好layuiadmin。我们以其中的user页面修改

springboot 增删改查 redis springboot+layui增删改查_java_11

我们修改的就是这3个文件,其中userform-add.html是新增的。
list.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>layuiAdmin 网站用户</title>
  <meta name="renderer" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <link rel="stylesheet" href="../../../layuiadmin/layui/css/layui.css" media="all">
  <link rel="stylesheet" href="../../../layuiadmin/style/admin.css" media="all">
</head>
<body>

  <div class="layui-fluid">
    <div class="layui-card">
      <div class="layui-form layui-card-header layuiadmin-card-header-auto">
        <div class="layui-form-item">

          <div class="layui-inline">
            <label class="layui-form-label">用户名</label>
            <div class="layui-input-block">
              <input type="text" id="name" name="name" placeholder="请输入" autocomplete="off" class="layui-input">
            </div>
          </div>

          <div class="layui-inline">
            <button class="layui-btn layuiadmin-btn-useradmin" lay-submit lay-filter="LAY-user-front-search">
              <i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
            </button>
          </div>
        </div>
      </div>
      
      <div class="layui-card-body">
        <div style="padding-bottom: 10px;">
          <button class="layui-btn layuiadmin-btn-useradmin" data-type="batchdel">删除</button>
          <button class="layui-btn layuiadmin-btn-useradmin" data-type="add">添加</button>
        </div>
        
        <table id="LAY-user-manage" lay-filter="LAY-user-manage"></table>
        <script type="text/html" id="imgTpl"> 
          <img style="display: inline-block; width: 50%; height: 100%;" src= {{ d.avatar }}>
        </script> 
        <script type="text/html" id="table-useradmin-webuser">
          <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i class="layui-icon layui-icon-edit"></i>编辑</a>
          <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i>删除</a>
        </script>
      </div>
    </div>
  </div>

  <script src="../../../layuiadmin/layui/layui.js"></script>  
  <script>
    var json;
  layui.config({
    base: '../../../layuiadmin/' //静态资源所在路径
  }).extend({
    index: 'lib/index' //主入口模块
  }).use(['index', 'table'], function(){
    var $ = layui.$
    ,form = layui.form
    ,table = layui.table;

    //表格初始化
    table.render({
      elem: "#LAY-user-manage"
      , method: 'get'
      , request: {
        pageName: 'offset' //页码的参数名称,默认:page
        , limitName: 'limit' //每页数据量的参数名,默认:limit
      }
      , url: '/user'
      //, contentType: 'application/json'
      , where: {
          'name': $('#name').val()
      }
      , cols: [[
        {type: "checkbox", fixed: "left"}
        , {field: 'id', width: '15%', title: '编号'}
        , {field: 'name', width: '15%', title: '姓名'}
        , {field: 'age', width: '15%', title: '年龄'}
        , {field: 'email', title: '邮箱'}
        , {
          title: "操作",
          width: 150,
          align: "center",
          fixed: "right",
          toolbar: "#table-useradmin-webuser"
        }
      ]]
      , parseData: function (res) { //res 即为原始返回的数据
               console.log(res)
        return {
          "code": 0, //解析接口状态
         // "msg": res.msg, //解析提示文本
          "count": res.total, //解析数据长度
          "data": res.records //解析数据列表
        };
      }
      , even: true
      , page: !0
      , limit: 30
      , height: "full-220"
      , text: "对不起,加载出现异常!"
    });


    table.on('tool(LAY-user-manage)', function (obj) {
      let data = obj.data;
      if (obj.event === 'edit') {
        json = JSON.stringify(data);
        layer.open({
          type: 2,
          title: "编辑用户",
          content: "../../../views/user/user/userform.html",
          maxmin: !0,
          area: ["500px", "450px"],
          btn: ["确定", "取消"],
          yes: function (e, t) {
            var l = window["layui-layer-iframe" + e], r = "LAY-user-front-submit",
                    n = t.find("iframe").contents().find("#" + r);
            l.layui.form.on("submit(" + r + ")", function (t) {
              t.field;

              $.ajax({
                type: 'PUT',
                dataType: "json",
                contentType: "application/json;charset=utf-8",
                url: '/user',
                data: JSON.stringify(t.field),
                success: function(data){
                  if (data) {
                    layer.msg('编辑成功');

                  } else {
                    layer.msg('编辑失败');
                  }
                  table.reload('LAY-user-manage');
                  layer.close(e)
                },
                error: function(msg){
                  alert("提交失败!");
                }
              });


            }), n.trigger("click")
          },
          success: function (e, t) {
          }
        })
      } else if (obj.event === 'del') {
        layer.confirm('确定删除选中数据?', function (index) {
          $.ajax({
            url:  "/user/" + data.id,
            type: "DELETE",
           // contentType: 'application/json',
            success: function (data) {
              if (data) {
                layer.msg('删除成功');
              } else {
                layer.msg('删除失败');
              }
              table.reload('LAY-user-manage'); //数据刷新
              layer.close(index) //关闭弹层
            }
          });
        });
      }
    });

    //监听搜索
    form.on('submit(LAY-user-front-search)', function(data){
      var field = data.field;
      
      //执行重载
      table.reload('LAY-user-manage', {
        where: field
      });
    });

    //事件
    var active = {
      batchdel: function(){
        var checkStatus = table.checkStatus('LAY-user-manage')
        ,checkData = checkStatus.data; //得到选中的数据

        if(checkData.length === 0){
          return layer.msg('请选择数据');
        }

        layer.confirm('确定删除吗?', function(index) {

          //执行 Ajax 后重载
          /*
          admin.req({
            url: 'xxx'
            //,……
          });
          */
          $.ajax({
            url:  "/user",
            type: "DELETE",
            data: JSON.stringify(checkData),
            contentType: 'application/json',
            success: function (data) {
              if (data) {
                layer.msg('删除成功');
              } else {
                layer.msg('删除失败');
              }
              table.reload('LAY-user-manage'); //数据刷新
              layer.close(index) //关闭弹层
            }
          });
        });
      }
      ,add: function(){
        layer.open({
          type: 2
          ,title: '添加用户'
          ,content: 'userform-add.html'
          ,maxmin: true
          ,area: ['500px', '450px']
          ,btn: ['确定', '取消']
          ,yes: function(index, layero){
            var iframeWindow = window['layui-layer-iframe'+ index]
            ,submitID = 'LAY-user-front-submit'
            ,submit = layero.find('iframe').contents().find('#'+ submitID);

            //监听提交
            iframeWindow.layui.form.on('submit('+ submitID +')', function(data){
              var field = data.field; //获取提交的字段
              
              //提交 Ajax 成功后,静态更新表格中的数据
              //$.ajax({});

              $.ajax({
                type: 'POST',
                dataType: "json",
                contentType: "application/json;charset=utf-8",
                url: '/user',
                data: JSON.stringify(field),
                success: function(data){
                  if (data) {
                    layer.msg('编辑成功');

                  } else {
                    layer.msg('编辑失败');
                  }
                  table.reload('LAY-user-manage'); //数据刷新
                  layer.close(index) //关闭弹层
                },
                error: function(msg){
                  alert("提交失败!");
                }
              });
            });  
            
            submit.trigger('click');
          }
        }); 
      }
    };
    
    $('.layui-btn.layuiadmin-btn-useradmin').on('click', function(){
      var type = $(this).data('type');
      active[type] ? active[type].call(this) : '';
    });
  });
  </script>
</body>
</html>

usrform.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>layuiAdmin 网站用户 iframe 框</title>
  <meta name="renderer" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <link rel="stylesheet" href="../../../layuiadmin/layui/css/layui.css" media="all">
</head>
<body>

  <div class="layui-form" lay-filter="layuiadmin-form-useradmin" id="layuiadmin-form-useradmin" style="padding: 20px 0 0 0;">
    <div class="layui-form-item">
      <label class="layui-form-label">用户名</label>
      <div class="layui-input-inline">
        <input type="hidden" name="id">
        <input type="text" name="name" lay-verify="required" placeholder="请输入用户名" autocomplete="off" class="layui-input">
      </div>
    </div>
    <div class="layui-form-item">
      <label class="layui-form-label">年龄</label>
      <div class="layui-input-inline">
        <input type="text" name="age"  placeholder="请输入年龄" autocomplete="off" class="layui-input">
      </div>
    </div>
    <div class="layui-form-item">
      <label class="layui-form-label">邮箱</label>
      <div class="layui-input-inline">
        <input type="text" name="email" lay-verify="email" placeholder="请输入邮箱" autocomplete="off" class="layui-input">
      </div>
    </div>

    <div class="layui-form-item layui-hide">
      <input type="button" lay-submit lay-filter="LAY-user-front-submit" id="LAY-user-front-submit" value="确认">
    </div>
  </div>

  <script src="../../../layuiadmin/layui/layui.js"></script>  
  <script>
  layui.config({
    base: '../../../layuiadmin/' //静态资源所在路径
  }).extend({
    index: 'lib/index' //主入口模块
  }).use(['index', 'form'], function(){
    var $ = layui.$
    ,form = layui.form;

    $(function () {
      //从父层获取值,json是父层的全局js变量。eval是将该string类型的json串变为标准的json串
      var parent_json = eval('('+parent.json+')');
      console.log(parent_json);
      //给表单赋值
      form.val("layuiadmin-form-useradmin", { //formTest 即 class="layui-form" 所在元素属性 lay-filter="" 对应的值
        "id": parent_json.id
        ,"name": parent_json.name // "name": "value"
        ,"age": parent_json.age
        ,"email":  parent_json.email
      });
    });



  })
  </script>
</body>
</html>

usrform-add.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>layuiAdmin 网站用户 iframe 框</title>
  <meta name="renderer" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <link rel="stylesheet" href="../../../layuiadmin/layui/css/layui.css" media="all">
</head>
<body>

  <div class="layui-form" lay-filter="layuiadmin-form-useradmin" id="layuiadmin-form-useradmin" style="padding: 20px 0 0 0;">
    <div class="layui-form-item">
      <label class="layui-form-label">用户名</label>
      <div class="layui-input-inline">
        <input type="text" name="name" lay-verify="required" placeholder="请输入用户名" autocomplete="off" class="layui-input">
      </div>
    </div>
    <div class="layui-form-item">
      <label class="layui-form-label">年龄</label>
      <div class="layui-input-inline">
        <input type="text" name="age"  placeholder="请输入年龄" autocomplete="off" class="layui-input">
      </div>
    </div>
    <div class="layui-form-item">
      <label class="layui-form-label">邮箱</label>
      <div class="layui-input-inline">
        <input type="text" name="email" lay-verify="email" placeholder="请输入邮箱" autocomplete="off" class="layui-input">
      </div>
    </div>

    <div class="layui-form-item layui-hide">
      <input type="button" lay-submit lay-filter="LAY-user-front-submit" id="LAY-user-front-submit" value="确认">
    </div>
  </div>

  <script src="../../../layuiadmin/layui/layui.js"></script>  
  <script>
  layui.config({
    base: '../../../layuiadmin/' //静态资源所在路径
  }).extend({
    index: 'lib/index' //主入口模块
  }).use(['index', 'form'], function(){
    var $ = layui.$
    ,form = layui.form;


  })
  </script>
</body>
</html>

3.5 运行测试

对SmlApplication右键,如图运行即可。

springboot 增删改查 redis springboot+layui增删改查_layui_12

访问默认端口:http://127.0.0.1:8080/views/userlist.html

springboot 增删改查 redis springboot+layui增删改查_java_13

正常测试新增,修改,删除,批量删除均无问题

4 总结

一个模块的增删改查什么简单,这也是入门的基础。
mybatis-plus为我们做了基础操作的封装,省去了我们写增删改查基础代码,大大提高了效率。
layuiadmin十分适合管理类系统开发,拥有众多组件。