Spring Boot + Layui + Spring Data JPA 实现前后端分离下简单增删改查分页操作

Spring Boot + Layui + Spring Data JPA 实现前后端分离下简单增删改查分页操作

1.项目背景

自己搭着玩,写个小demo

2.项目构成

后端:Spring boot 2.3(2.4不支持全局跨域配置) JDK1.8

数据库:Spring Data JPA MySQL 5.7.31

前端: Layui2.5.7

3.添加依赖

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</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.12</version>
		</dependency>
	</dependencies>

4.配置文件application.yml

#服务端容器的配置
server:
  port: 8888
#数据库配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/kaitao?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: root
#jpa配置   
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update

5.导入数据库

CREATE TABLE `article`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `reader` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `content` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

创建数据库:kaitao 编码:UTF-8

6.entity包

package com.godwin.entity;

import lombok.Data;

import javax.persistence.*;

/**
 * 文章信息实体类
 * Created by admin on 2020/12/17.
 */
@Entity
@Data
@Table(name = "article")
public class Article {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;
    private String title;
    private String type;
    private String reader;
    private String content;
}

package com.godwin.entity;

/**
 *  @Description: 响应消息体
 * Created by admin on 2020/12/17.
 */
public class ResultBean<T> {
    /**响应编码*/
    private int code;
    /**响应消息*/
    private String msg;
    /**数据总量*/
    private int count;
    /**数据*/
    private T data;

    public ResultBean() {
    }

    public ResultBean(int code, String msg, int count, T data) {
        super();
        this.code = code;
        this.msg = msg;
        this.count = count;
        this.data = data;
    }

    @Override
    public String toString() {
        return "R [code=" + code + ", msg=" + msg + ", count=" + count + ", data=" + data + "]";
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}


7.repository包(操作数据库)

package com.godwin.repository;


import com.godwin.entity.Article;




import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;

import org.springframework.transaction.annotation.Transactional;




/**
 * 操作数据库
 * Created by admin on 2020/12/17.
 */
public interface ArticleRepository extends JpaRepository<Article,Integer> {
    //批量删除
    @Transactional
    @Modifying
    @Query(value="delete from article where id in ?1 ",nativeQuery=true)
    int deletes(Integer[] ids);





}

8.service包

package com.godwin.service;

import com.godwin.entity.Article;
import org.springframework.data.domain.Page;

import java.util.List;


/**
 * Created by admin on 2020/12/17.
 */
public interface ArticleService {
    Article save(Article article);
    Article edit(Article article);
    void deletes(Integer[] ids);
    List<Article> findAll();
    Page<Article> getPager(Integer page, Integer limit);
}

package com.godwin.service;


import com.godwin.entity.Article;
import com.godwin.repository.ArticleRepository;
import org.springframework.beans.factory.annotation.Autowired;


import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;



import java.util.List;



/**
 * Created by admin on 2020/12/17.
 */
@Service
public class ArticleServiceImpl implements ArticleService {


    @Autowired
    private ArticleRepository repository;

    @Override
    public Article save(Article article) {
        return repository.save(article);
    }

    @Override
    public Article edit(Article article) {
        return repository.save(article);
    }

    @Override
    public void deletes(Integer[] ids) {
        repository.deletes(ids);
    }

    @Override
    public List<Article> findAll() {
        return repository.findAll();
    }

    @Override
    public Page<Article> getPager(Integer page, Integer limit) {
        Pageable pageable = PageRequest.of(page-1,10);
        return repository.findAll(pageable);


    }
}

9.controller包

package com.godwin.controller;




import com.godwin.entity.Article;
import com.godwin.entity.ResultBean;
import com.godwin.service.ArticleService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;



import java.util.List;



/**
 * Created by admin on 2020/12/17.
 */
@RestController
@RequestMapping("/kaitao")
public class ArticleController {

    @Autowired
    private ArticleService articleService;

    @GetMapping("/list")
    public ResultBean list1(@RequestParam(defaultValue = "1") Integer page,
                            @RequestParam(defaultValue = "10") Integer limit){

        List<Article> data = articleService.getPager(page,limit).getContent();
        int count = articleService.findAll().size();

        ResultBean result = new ResultBean(0,"",count,data);

        return result;
    }


    @PostMapping("/save")
    public ResultBean save(@RequestBody Article article){
        // 判断是新增还是修改
        if(article.getId()!=null){
            articleService.edit(article);
        }else{
            articleService.save(article);
        }
        return new ResultBean(200,"",0,"");
    }

    @PostMapping("/remove")
    public ResultBean remove(@RequestBody Integer[] ids){
        articleService.deletes(ids);
        return new ResultBean(200,"",0,"");
    }



}

10.config(配置全局跨域)

package com.godwin.config;

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

/**
 * 添加全局跨域配置
 * Created by admin on 2020/12/18.
 */
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

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

}

11.前端页面

<!DOCTYPE html>
<html>

	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
		<title>开淘网后台管理系统</title>
		<link rel="stylesheet" href="layui/css/layui.css">
	</head>

	<body class="layui-layout-body">
		<div class="layui-layout layui-layout-admin">
			<div class="layui-header">
				<div class="layui-logo">开淘网后台管理系统</div>
				<!-- 头部区域(可配合layui已有的水平导航) -->
				<ul class="layui-nav layui-layout-left">
					<li class="layui-nav-item">
						<a href="">控制台</a>
					</li>
					<li class="layui-nav-item">
						<a href="">商品管理</a>
					</li>
					<li class="layui-nav-item">
						<a href="">用户</a>
					</li>
					<li class="layui-nav-item">
						<a href="javascript:;">其它系统</a>
						<dl class="layui-nav-child">
							<dd>
								<a href="">邮件管理</a>
							</dd>
							<dd>
								<a href="">消息管理</a>
							</dd>
							<dd>
								<a href="">授权管理</a>
							</dd>
						</dl>
					</li>
				</ul>
				<ul class="layui-nav layui-layout-right">
					<li class="layui-nav-item">
						<a href="javascript:;">
							<img src="" class="layui-nav-img"> admin
						</a>
						<dl class="layui-nav-child">
							<dd>
								<a href="">基本资料</a>
							</dd>
							<dd>
								<a href="">安全设置</a>
							</dd>
						</dl>
					</li>
					<li class="layui-nav-item">
						<a href="">退出</a>
					</li>
				</ul>
			</div>

			<div class="layui-side layui-bg-black">
				<div class="layui-side-scroll">
					<!-- 左侧导航区域(可配合layui已有的垂直导航) -->
					<ul class="layui-nav layui-nav-tree" lay-filter="test">
						<li class="layui-nav-item layui-nav-itemed">
							<a class="" href="javascript:;">文章管理</a>
							<dl class="layui-nav-child">
								<dd class="layui-this">
									<a href="javascript:;">文章信息</a>
								</dd>
								<dd >
									<a href="javascript:;">文章评论</a>
								</dd>																	
							</dl>
						</li>
						<li class="layui-nav-item">
							<a href="javascript:;">广告管理</a>
							<dl class="layui-nav-child">
								<dd>
									<a href="javascript:;">广告信息</a>
								</dd>
								<dd>
									<a href="javascript:;">广告评论</a>
								</dd>							
							</dl>
						</li>						
					</ul>
				</div>
			</div>

			<div class="layui-body">
				<!-- 内容主体区域 -->
				<div style="padding: 15px;">
					

					<table id="tb-article" lay-filter="tb-article"></table>

				</div>
			</div>

			<!--编辑表单-->
			<div class="layui-row" id="editArticle" style="display:none;">
				<div class="layui-col-md10">
					<form class="layui-form layui-from-pane" id="saveArticle" style="margin-top:20px">

						<div class="layui-form-item">
							<label class="layui-form-label">文章作者</label>
							<div class="layui-input-block">
								<input type="text" name="name" id="name" required lay-verify="required" autocomplete="off" class="layui-input">
							</div>
						</div>

						<input type="hidden" name="id" id="id">

						<div class="layui-form-item">
							<label class="layui-form-label">文章标题</label>
							<div class="layui-input-block">
								<input type="text" name="title" id="title" required lay-verify="required" autocomplete="off" class="layui-input">
							</div>
						</div>
						
						<div class="layui-form-item">
							<label class="layui-form-label">文章类型</label>
							<div class="layui-input-block">
								<input type="text" name="type" id="type" required lay-verify="required" autocomplete="off" class="layui-input">
							</div>
						</div>
						
						<div class="layui-form-item">
							<label class="layui-form-label">登入次数</label>
							<div class="layui-input-block">
								<input type="text" name="reader" id="reader" required lay-verify="required" autocomplete="off" class="layui-input">
							</div>
						</div>

						<div class="layui-form-item">
							<label class="layui-form-label">文章内容</label>
							<div class="layui-input-block">
								<input type="text" name="content" id="content" required lay-verify="required" autocomplete="off" class="layui-input">
							</div>
						</div>

						<div class="layui-form-item" style="margin-top:40px" id="check">
							<div class="layui-input-block">
								<button class="layui-btn  layui-btn-submit " lay-submit="" lay-filter="saveArticle">保存</button>
								<!--<button type="reset" class="layui-btn layui-btn-primary">重置</button>-->
							</div>
						</div>
					</form>
				</div>
			</div>

			<script type="text/html" id="toolbarDemo">
				<div class="layui-btn-container">
            <button class="layui-btn layui-btn-sm" lay-event="add"><i class="layui-icon">&#xe608;</i>新增</button>
            <button class="layui-btn layui-btn-sm layui-btn-danger" lay-event="remove"><i class="layui-icon">&#xe640;</i>删除</button>
        </div>
        
    </script>

			<script type="text/html" id="barDemo">
				<a class="layui-btn layui-btn-sm" lay-event="edit"><i class="layui-icon">&#xe642;</i>修改</a>
    </script>

			<div class="layui-footer">
				<!-- 底部固定区域 -->
				© kaitao.com
			</div>
		</div>
		<script src="js/jquery.js"></script>
		<script src="layui/layui.all.js"></script>
		<script>
			var element, layer, table, form;

			$(function() {
				// 使用模块
				layui.use(['element', 'layer',  'table', 'form'], function() {
					element = layui.element;
					layer = layui.layer;
					table = layui.table;
					form = layui.form;
				});

			

				//第一个实例
				var userTable = table.render({
					elem: '#tb-article',
					height: 585,
					url: 'http://localhost:8888/kaitao/list' ,//数据接口					
					page: true ,//开启分页					
					toolbar: '#toolbarDemo',										
					cols: [[ 
						//表头							
								 {type: 'checkbox', fixed: 'left'}
								,{field:'id', title:'ID', width:80, fixed: 'left',  sort: true, totalRowText: '合计'}
								,{field:'name', title:'文章作者', width:150,}      
								,{field:'title', title:'文章标题', width:260}
								,{field:'type', title:'文章类型', width:150}
								,{field:'reader', title:'登入次数', width:100, sort: true, totalRow: true}
								,{field:'content', title:'文章内容', width:500}
								,{fixed: 'right', title:'操作', toolbar: '#barDemo', width:150}
						]]					
				});

				//监听表单提交
				// 修改
				form.on('submit(saveArticle)', function(data) {
					layer.alert(JSON.stringify(data.field));
					$.ajax({
						url: 'http://localhost:8888/kaitao/save',
						type: 'POST',
						contentType: "application/json",
						dataType: "json",
						data: JSON.stringify(data.field),
						success: function(result) {
							if (result.code == 200) {
								// layer.msg("修改成功!", {icon: 6});
								setTimeout(function() {
									layer.closeAll(); //关闭所有的弹出层
									userTable.reload();
								}, 300);
							} else {
								layer.msg("操作失败!", {
									icon: 5
								});
							}
						}
					});

					return false;

				});

				//工具栏事件
				table.on('toolbar(tb-article)', function(obj) {
					var checkStatus = table.checkStatus(obj.config.id);
					var checkData = checkStatus.data;
					var ids = [];
					switch (obj.event) {
						// 新增
						case 'add':
						    $("#id").val('');
							$("#name").val('');
							$("#title").val('');
							$("#type").val('');
							$("#reader").val('');
							$("#content").val('');														
							layer.open({
								type: 1,
								offset: '10px',
								title: "新增文章",
								area: ['500px', '450px'],
								content: $("#editArticle")
							});


							break;
							// 删除
						case 'remove':
							if (checkData.length == 0) {
								layer.alert('请选择要操作的行');
							} else {
								layer.confirm('确定要删除吗?', function(index) {
									for (var i = 0; i < checkData.length; i++) {
										ids.push(checkData[i].id);
									}
									//layer.alert(JSON.stringify(ids));
									$.ajax({
										url: 'http://localhost:8888/kaitao/remove',
										type: 'POST',	
										contentType: "application/json",
										dataType: "json",
										data: JSON.stringify(ids),
										success: function(result) {
											if (result.code == 200) {
												setTimeout(function() {
													layer.closeAll(); //关闭所有的弹出层
													userTable.reload();
												}, 300);
											}else {
                                        layer.msg("操作失败!", {icon: 5});
										}
										}
									});
								});
							}
							break;
						case 'getCheckData':

							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(tb-article)', function(obj) {
					var data = obj.data;
					// 修改
					if (obj.event === 'edit') {
						$("#id").val(data.id);
						$("#name").val(data.name);
						$("#title").val(data.title);
						$("#type").val(data.type);
						$("#reader").val(data.reader);
						$("#content").val(data.content);
						

						layer.open({
							type: 1,
							offset: '10px',
							title: "修改文章",
							area: ['500px', '450px'],
							content: $("#editArticle")
						});
					}
				});
			});
		</script>
	</body>

</html>

总结:过程中遇到的问题。

  1. 前后端分离,前后端用JSON交互,所以要写一个工具类,用来放“code,msg,count,data”,方便后端传JSON数据给前端。
  2. 要配置全局跨域,否者前端拿不到后端数据
  3. 要写一个批量删除,所以自己在repository写了一个sql语句
  4. 用的layui框架,要遵循layui的规则,前端页面复制前记得导入layui静态文件
  5. 记得改yml数据库名称.用户和密码

有什么问题可以后台留言

posted @ 2020-12-21 19:09  Godwin_Zhang  阅读(656)  评论(2编辑  收藏  举报