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 - 步骤二:选择在线搭建
左侧选择Spring Initializr,右边选择 Default,点击 Next - 步骤三:初始化设置
初始化设置,如图 - 步骤四:选择依赖的jar包
Developer Tools --> Lombok;Web–>Spring Web;SQL–>H2 Database
- 步骤五:设置项目名和项目路径
- 步骤六:检查是否工程是否正常
3.2 工程目录结构
我们按照标准工程,创建目录如下:
3.3 Mybatis-plus、H2使用
按照如下结构创建或修改文件:
修改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页面修改
我们修改的就是这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右键,如图运行即可。
访问默认端口:http://127.0.0.1:8080/views/userlist.html
正常测试新增,修改,删除,批量删除均无问题
4 总结
一个模块的增删改查什么简单,这也是入门的基础。
mybatis-plus为我们做了基础操作的封装,省去了我们写增删改查基础代码,大大提高了效率。
layuiadmin十分适合管理类系统开发,拥有众多组件。