• 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', 80, fixed: 'left',  sort: true, totalRowText: '合计'}
    								,{field:'name', title:'文章作者', 150,}      
    								,{field:'title', title:'文章标题', 260}
    								,{field:'type', title:'文章类型', 150}
    								,{field:'reader', title:'登入次数', 100, sort: true, totalRow: true}
    								,{field:'content', title:'文章内容', 500}
    								,{fixed: 'right', title:'操作', toolbar: '#barDemo', 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数据库名称.用户和密码

    有什么问题可以后台留言

  • 相关阅读:
    组合模式
    MySQL8.0 下载安装启动(Windows10)
    OI如逆旅,我亦是行人——省选
    闲话—江湖痴情浅,信步余生。平剑红烛,青丝微绾,却话奁中。
    此时彼方
    CSP 2019游记 & 退役记
    西狂 杨过
    SDOI 2019 Round1 游记
    NOIP2018游记
    未来可期,不知所终
  • 原文地址:https://www.cnblogs.com/XING-ZHI-JI-DA-XUE/p/14169437.html
Copyright © 2020-2023  润新知