文章目录
学习+总结不易,提供给各位学习参考,共同进步,谢谢参考
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>
<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)"><上一页</a>-->
<a href="javascript:;" class="page" disabled @click="pagePart(page-1)"><上一页</a>
<a href="javascript:;" class="page" v-for="indexpage in totalPage" @click="pagePart(indexpage)"> {{indexpage}} </a>
<!--<a href="javascript:;" class="page" v-if="page<totalPage" @click="pagePart(page+1)">下一页&></a>-->
<a href="javascript:;" class="page" @click="pagePart(page+1)">下一页></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静态文件说明
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