vue+springboot前后端分离开发学习综合案例及代码crud

学习+总结不易,提供给各位学习参考,共同进步,谢谢参考

vue结合前端springboot前后端分离开发综合案例crud

项目结构图

在这里插入图片描述

最终效果图
在这里插入图片描述

sql

自行添加更多的数据

/*
SQLyog Ultimate v12.3.1 (64 bit)
MySQL - 5.7.20-log : Database - stu_newest
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`stu_newest` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `你的数据库`;

/*Table structure for table `v_user` */

DROP TABLE IF EXISTS `v_user`;

CREATE TABLE `v_user` (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(40) DEFAULT NULL COMMENT '名字',
  `age` int(3) DEFAULT NULL COMMENT '年龄',
  `salary` double(7,2) DEFAULT NULL COMMENT '薪资',
  `phoneCode` varchar(11) DEFAULT NULL COMMENT '电话',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

/*Data for the table `v_user` */

insert  into `v_user`(`id`,`name`,`age`,`salary`,`phoneCode`) values 

(1,'admin',15,50000.00,'15545853564'),

(2,'xiangti',21,99999.00,'15368485275'),

(3,'tizi',20,10000.00,'17666663959'),

(4,'小花',19,17000.00,'18588745952'),

(5,'阿名',23,19000.00,'16859267368'),

(6,'girl',20,20000.00,'16815964211'),

(7,'boy',24,2603.00,'13842156415'),

(8,'华哥',20,15151.00,'16484232515');

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

application.yml 配置

server:
  port: 8989 #端口号8989
  servlet:
    context-path: /user #默认访问路径/user

spring:
  application:
    name: vue-crud
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/stu_newest?characterEncoding=utf-8
    username: root
    password: 12345678


mybatis:
  mapper-locations: classpath:/mybatis/mapper/*.xml
  type-aliases-package: com.lemon.bean

User 实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Accessors(chain = true)//开启链式写法
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private Double salary;
    private String phoneCode;
}

UserMapper 数据访问接口

@Mapper
public interface UserMapper {
    //查询所有信息
    List<User> findAll();
    //添加用户
    void save(User user);
    //删除用户
    void del(int id);

    //根据id查当前信息
    User findOne(Integer id);
    //修改信息
    void update(User user);

    //根据姓名或电话模糊搜索
    List<User> findNameOrPhoneCode(@Param("name") String name,@Param("phoneCode") String phoneCode);
}

PageMapper 分页数据访问接口

@Mapper
public interface PageMapper<T, K> {
    /**
     *
     * @param start 当前页
     * @param rows 页大小
     * @return
     */

    public List<T> findByPage(@Param("start") Integer start, @Param("rows") Integer rows);

    /**
     * 总条数
     * @return
     */
    public Integer findTotals();
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=绑定一个指定的dao/mapper接口-->
<mapper namespace="com.lemon.mapper.UserMapper">

    <!--处理模糊搜索-->
    <select id="findNameOrPhoneCode" resultType="user">
        select id,name,age,salary,phoneCode from v_user
        <where>
            <if test="name != ''">
                name like concat(#{name},'%')
            </if>

            <if test="phoneCode != ''">
                or phoneCode like concat('%',#{phoneCode},'%')
            </if>
        </where>
    </select>

    <!--根据id修改当前信息-->
    <update id="update" parameterType="user">
        update v_user set name=#{name},age=#{age},salary=#{salary},phoneCode=#{phoneCode} where id = #{id}
    </update>
    <!--根据id查询当前信息-->
    <select id="findOne" resultType="user" >
        select id,name,age,salary,phoneCode from v_user where id = #{id}
    </select>
    <!--根据id删除一条信息-->
    <delete id="del" parameterType="Integer">
        delete from v_user where id = #{id}
    </delete>

    <!--开启自增 id,不设置也可以,数据库已经设置自增-->
    <!--<insert id="save" parameterType="user" useGeneratedKeys="true" keyProperty="id">-->
    <insert id="save" parameterType="user">
        insert into v_user values (#{id},#{name},#{age},#{salary},#{phoneCode})
    </insert>

    <!--查询所有数据-->
    <select id="findAll" resultType="user">
        select id,name,age,salary,phoneCode from v_user
    </select>
</mapper>

PageMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=绑定一个指定的dao/mapper接口-->
<mapper namespace="com.lemon.mapper.PageMapper">
    <!--分页查询所有-->
    <select id="findByPage" resultType="user">
        select id,
        name,
        age,
        salary,
        phoneCode
        from v_user
        order by id ASC
        limit #{start},#{rows}
    </select>

    <!--查询总条数-->
    <select id="findTotals" resultType="integer">
        select count(id) from v_user
    </select>
</mapper>

UserService

public interface UserService {
    //查询所有信息
    List<User> findAll();
    //添加用户
    void save(User user);
    //删除用户
    void del(int id);

    //根据id查当前信息
    User findOne(Integer id);
    //修改信息
    void update(User user);

    //根据姓名或电话模糊搜索
    List<User> findNameOrPhoneCode(@Param("name") String name, @Param("phoneCode") String phoneCode);
}

UserServiceImpl

@Service
public class UserServiceImpl implements UserService{

    @Resource
    private UserMapper userMapper;

    @Override
    public List<User> findAll() {
        return userMapper.findAll();
    }

    @Override
    public void save(User user) {
        userMapper.save(user);
    }

    @Override
    public void del(int id) {
        userMapper.del(id);
    }

    @Override
    public User findOne(Integer id) {
        return userMapper.findOne(id);
    }

    @Override
    public void update(User user) {
        userMapper.update(user);
    }

    @Override
    public List<User> findNameOrPhoneCode(String name, String phoneCode) {
        return userMapper.findNameOrPhoneCode(name,phoneCode);
    }
}

PageService

public interface PageService {
    /**
     * @param page  当前页
     * @param rows  每页显示的记录数
     * @return
     */
    public List<User> findByPage(Integer page,Integer rows);

    /**
     * 查询总条数
     * @return
     */
    public Integer findTotals();
}

PageServiceImpl

@Service
public class PageServiceImpl implements PageService {

    @Resource
    private PageMapper pageMapper;

    @Override
    public List<User> findByPage(Integer page, Integer rows) {
        //页码计算公式 (当前页-1) * 页大小
        int start = (page - 1) * rows;
        //!
        return pageMapper.findByPage(page, rows);
    }

    @Override
    public Integer findTotals() {
        return pageMapper.findTotals();
    }
}

UserController

@Controller
@RestController
@CrossOrigin//允许跨域处理
public class UserController {
    @Resource
    private UserService userService;

    //模糊搜索
    @GetMapping("/findLike")
    public List<User> findNameOrPhoneCode(String name,String code){
        System.out.println("前端模糊搜索  name值:"+name+"  |  phone值: " +code);
        return userService.findNameOrPhoneCode(name,code);
    }

    @GetMapping(value = "/findOne")
    //根据id查询当前信息
    public User findOne(int id){
        System.out.println("前端查询当前信息id:" +id);
        return userService.findOne(id);
    }

    @PostMapping(value = "/del")
    //删除用户
    public Map<String,Object> del(int id){
        System.out.println("前端删除id值:"+id);
        Map<String, Object> map = new HashMap<>();
        try {
            //前端传的值为string类型,定义的值为integer,强制string类型转integer
            // Integer num = Integer.parseInt(id);
            userService.del(id);
            map.put("state",true);
        } catch (Exception e) {
            map.put("state",false);
        }
        return map;
    }

    @PostMapping(value = "/save")
    //保存用户_修改用户
    public Map<String, Object> save(@RequestBody User user) {
        System.out.println("前端save信息(有id修改 无id添加): " + user);
        Map<String, Object> map = new HashMap<>();
        if (!user.equals("") && user!=null) {
            //如果没有id执行的是添加操作
            if (StringUtils.isEmpty(user.getId())){
                userService.save(user);
                map.put("state", true);
                map.put("msg","添加成功");
            }else{
                //如果有id执行的是修改操作
                userService.update(user);
                map.put("state", true);
                map.put("msg","修改成功");
            }
        } else {
            map.put("state", false);
            map.put("msg", "保存或修改失败");
        }
        return map;
    }

    //查询所有信息(已无作用,后期加了分页查询数据)
    @GetMapping("/findAll")
    public List<User> findAll() {
        List<User> userList = userService.findAll();
        return userList;
    }
}

PageController

@Controller
@CrossOrigin//允许跨域处理
public class PageController {
    @Resource
    private PageService pageService;

    @GetMapping("/findByPage")
    @ResponseBody
    public Map<String,Object> findByPage(Integer page,Integer rows){
        System.out.println("前端页码:"+ page);

        //page=null 页面为1
        page = page==null?1:page;
        //rows=null 每页展示五条数据
        rows = rows==null?5:rows;

        HashMap<String, Object> map = new HashMap<>();
        //分页处理
        List<User> userList = pageService.findByPage(page, rows);
        //计算总页数
        Integer totals = pageService.findTotals();
        //总页数  count%rows==0 如果等于0执行 count/rows  否则执行count/rows+1
        Integer totalPage = totals%rows==0?totals/rows:totals/rows+1;
        if(page>totalPage){
            map.put("state",true);
            map.put("msg","已经是最后一页了 没有更多的数据啦~");
        }

        map.put("userList",userList);//放入用户id集合
        map.put("totals",totals);//放入总条数的方法
        map.put("totalPage",totalPage);//放入总页数
        map.put("page",page);//放入当前页
        return map;
    }
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>User Manager</title>
    <!--引入bootstrap中css的样式-->
    <link rel="stylesheet" href="../static/css/bootstrap.min.css">
    <style type="text/css">
        tr th {
            text-align: center;
        }

        td {
            text-align: center;
        }

    </style>
</head>
<body>

<!--导航-->
<nav class="navbar navbar-default">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <a class="navbar-brand" href="#">简易用户管理系统</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">

            <ul class="nav navbar-nav navbar-right">
                <li><a href="#">x</a></li>
            </ul>
        </div>
    </div>
</nav>

<div id="app">
    <!--中心布局-->
    <div class="container-fluid">
        <!--搜索框-->
        <div class="row">
            <div class="col-md-8 col-md-offset-1">
                <form class="form-inline">
                    <div class="form-group">
                        <label for="exampleInputName2">姓名</label>
                        <input type="text" placeholder="输入搜索姓名的关键字" v-model="searchName" class="form-control"
                               id="searchName">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputEmail2">电话</label>
                        <input type="email" placeholder="输入电话的关建数" v-model="searchPhone" class="form-control"
                               id="searchEmail">
                    </div>
                    <button type="submit" class="btn btn-info" @click.prevent="searchLike">搜索</button>
                </form>
            </div>
        </div>

        <div class="row">
            <div class="col-md-8" style="margin-top: 50px">
                <table class="table table-striped table-bordered table-hover">
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>姓名</th>
                        <th>年龄</th>
                        <th>薪资</th>
                        <th>电话</th>
                        <th>操作</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="user,index in users" :key="user.id">
                        <td>{{user.id}}</td>
                        <td>{{user.name}}</td>
                        <td>{{user.age}}</td>
                        <td>{{user.salary}}</td>
                        <td>{{user.phoneCode}}</td>
                        <td>
                            <button class="btn btn-danger" @click="delRow(user.id)">删除</button>&nbsp;
                            <button class="btn btn-primary" @click="findOneUserInfo(user.id)">修改</button>
                        </td>
                    </tr>
                    </tbody>
                </table>
            </div>

            <div class="col-md-4">
                <div class="form-group" style="margin: 0px" align="center">
                    <span><h3>添加 | 修改 模块</h3></span><br>
                    <span>表单默认为添加数据不携带id / 点修改自动获取id 携带id进行修改</span>
                </div>
                <span></span>
                <form>
                    <div class="form-group">
                        <label for="username">姓名</label>
                        <input type="text" class="form-control" required id="username" v-model="userparameter.name"
                               placeholder="请输入姓名">
                    </div>
                    <div class="form-group">
                        <label for="password">年龄</label>
                        <input type="text" class="form-control" id="password" v-model="userparameter.age"
                               placeholder="请输入年龄">
                    </div>
                    <div class="form-group">
                        <label for="salary">薪资</label>
                        <input type="text" class="form-control" id="salary" v-model="userparameter.salary"
                               placeholder="请输入薪资">
                    </div>
                    <div class="form-group">
                        <label for="phoneCode">电话</label>
                        <input type="text" class="form-control" id="phoneCode" v-model="userparameter.phoneCode"
                               placeholder="请输入电话号码">
                    </div>

                    <button type="submit" class="btn btn-warning" @click="saveUserInfo">提交</button>
                    <button type="reset" class="btn btn-info">重置</button>
                </form>
            </div>
        </div>
    </div>

    <!--分页 未添加样式版-->
    <div id="pages" style="margin-left: 270px;">
        <!--此处注释掉的代码为控制首页 和 尾页的 上一页和下一页标签隐藏-->
        <!--<a href="javascript:;" class="page" v-if="page!=1" disabled @click="pagePart(page-1)">&lt;上一页</a>-->
        <a href="javascript:;" class="page"  disabled @click="pagePart(page-1)">&lt;上一页</a>
        &nbsp;&nbsp;
        <a href="javascript:;" class="page" v-for="indexpage in totalPage" @click="pagePart(indexpage)">&nbsp;&nbsp;{{indexpage}}&nbsp;&nbsp;</a>
        <!--<a href="javascript:;" class="page" v-if="page<totalPage" @click="pagePart(page+1)">下一页&&gt;</a>-->
        <a href="javascript:;" class="page"  @click="pagePart(page+1)">下一页&gt;</a>
    </div>


</div>

<!--引入Vue.js-->
<script src="../static/js/vue.js"></script>
<!--引入axios.js-->
<script src="../static/js/axios.min.js"></script>
<script>
    const app = new Vue({
        el: "#app",
        data: {
            users: [],//数据赋值来源于后端服务接口,在页面加载完成前完成赋值
            userparameter: {},//定义添加数据的双向绑定,此处如为[]会报错
            searchName: "",//处理搜索名字的数据绑定
            searchPhone: "",//处理搜索电话的数据绑定

            page: 1,//当前页 默认1
            rows: 5,//行数 默认5
            totalPage: 0,
            totals: 0,
        },
        methods: {
            //查询所有数据 并进行分页
            pagePart(indexpage) {//查询所有
                if (indexpage) {
                    this.page = indexpage;
                }
                axios.get("http://localhost:8989/user/findByPage?page=" + this.page).then((res) => {
                    // console.log(res.data.userList);
                    if (res.data.state) {
                        //当处于最后一页时,再点击下一页响应后台msg信息
                        alert(res.data.msg);
                        //刷新页面
                        location.reload();
                    }
                    this.users = res.data.userList;
                    this.page = res.data.page;
                    this.totalPage = res.data.totalPage;
                    this.totals = res.data.totals;
                });
            },
            searchLike() {
                //模糊搜索
                axios.get("http://localhost:8989/user/findLike?name=" + this.searchName + "&code=" + this.searchPhone).then((res) => {
                    console.log(res.data);
                    this.users = res.data;
                })
            },
            //根据id查询当前的信息(修改)
            findOneUserInfo(id) {
                axios.get("http://localhost:8989/user/findOne?id=" + id).then((res) => {
                    console.log(res.data);
                    //根据双向绑定原理,后台直接赋值给userparameter
                    this.userparameter = res.data;
                });
            },
            //根据id删除信息
            delRow(id) {
                if (confirm("确认删除id为 " + id + "信息吗")) {
                    axios.post("http://localhost:8989/user/del?id=" + id).then((res) => {
                        if (res.data.state) {
                            alert("删除id " + id + " 信息成功");
                            location.reload(); //刷新当前页
                        } else {
                            alert("删除失败");
                        }
                    });
                }
            },
            //添加信息
            saveUserInfo() {
                axios.post("http://localhost:8989/user/save", this.userparameter).then((res) => {
                    if (res.data.state) {
                        alert(res.data.state + " " + res.data.msg);
                        //添加完成后刷新当前页 location.reload()或调取 this.findAll
                        location.reload();
                        //清空文本框的信息
                        this.userparameter = "";
                    } else {
                        alert("后台:" + res.data.state + " " + res.data.msg);
                    }
                }).catch((err) => {
                    alert("添加失败 错误信息: " + err);
                });
            },
            //查询所有用户信息的函数 (后期已加入分页查数据,当前无用)
            // findAll() {
            //     //已简写为以下的箭头函数
            //     axios.get("http://localhost:8989/user/findAll").then((res) => {
            //         // console.log(res.data);
            //         this.users = res.data;
            //     }).catch((err) => {
            //         console.log("查询所有错误信息:" + err);
            //     })
            // },
        },
        //生命周期相关函数 页面加载直接调用
        created() {
            //调用查询所有信息函数
            // this.findAll();
            this.pagePart();
        }
    })
</script>
</body>
</html>

static静态文件说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I2xjGNfT-1616588168047)(D:/typora/Typora/img/vue/1616572927067.png)]

static静态文件为 bootstrap vue.js vue.min.axios 此处没有放入这些文件,可以尝试在inedx.html删除现有的link和script 导入在线的cdn

test测试类

@SpringBootTest
class VueTest {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PageService pageService;
    
    @Test
    void findAll() {
        userMapper.findAll().forEach(user -> System.out.println("user = " + user));
    }

    //分页测试
    @Test
    public void testFindByPage() {
        List<User> list = pageService.findByPage(1, 3);
        //jdk8的新特性
        list.forEach(province -> {
            System.out.println(province);
        });
    }

}

综合案例内容提供完结,学习+总结特别不易,提供给各位学习参考,共同进步,谢谢参考 还有bug待修复,有问题需要参考资料请留言提出,点赞评论支持一下~ thank

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值