springboot + vue3实现增删改查分页操作
- 环境
- 最终实现效果
- 实现功能
- 主要框架
- 代码实现
- 数据库
- 后端
- 前端
- 注意事项
环境
jdk17 vue3
最终实现效果
实现功能
添加用户,禁用,启用,删除,编辑,分页查询
主要框架
后端
springboot mybatis-plus
前端
element-plus axios
代码实现
数据库
数据库中就一个 user表主要就包含以下字段
后端
yml配置文件
server:port: 8000
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/java-db1?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: 123456type: com.alibaba.druid.pool.DruidDataSourcejackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT-8thymeleaf:cache: false
mybatis-plus:global-config:db-config:id-type: assign_idconfiguration:map-underscore-to-camel-case: true
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>3.2.1</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><description>demo</description><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</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><!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.11</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.5</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-crypto --><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-crypto</artifactId><version>6.2.1</version></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>
User实体类
package com.example.demo.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;import java.sql.Timestamp;@Data
@AllArgsConstructor
public class User {@TableId(value = "id",type = IdType.AUTO)private Integer id;private String username;private String password;private String nickname;private String email;private Timestamp add_time;private Integer disabled;}
UserService接口中我们需要添加一个方法
Page<User> getPage(Page<User> page, QueryWrapper<User> queryWrapper);
UserServiceImple实现类中实现这个方法
这个方法主要用来实现分页
@Autowiredprivate UserMapper userMapper;@Overridepublic Page<User> getPage(Page<User> page, QueryWrapper<User> queryWrapper) {return userMapper.selectPage(page,queryWrapper);}
UserMapper类和 我们平时写的mapper类一样,没有区别
在config包下添加Mybatis-plus分页插件
package com.example.demo.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 向MyBatis-Plus的过滤器链中添加分页拦截器,需要设置数据库类型(主要用于分页方言)interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));// 添加乐观锁拦截器interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}
UserController控制器类
package com.example.demo.controller;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import com.example.demo.util.Res;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;import java.sql.Timestamp;
import java.util.Date;@RestController
@RequestMapping("/user")
public class UserController{@Autowiredprivate UserService userService;@PostMapping("/add")public Res<User> add (@RequestBody User user){//判断用户是否存在QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("username",user.getUsername());User u = userService.getOne(queryWrapper);if(u!=null){return Res.error("用户已存在");}//设置添加时间Timestamp timestamp = new Timestamp(new Date().getTime());user.setAdd_time(timestamp);//加密密码BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();String hash_password =bCryptPasswordEncoder.encode(user.getPassword());user.setPassword(hash_password);boolean res = userService.save(user);if(!res){return Res.error("添加失败");}return Res.success("添加用户成功",user);}@PostMapping("/edit")public Res<User> edit(@RequestBody User user){boolean res = userService.updateById(user);if(!res){return Res.error("编辑用户信息失败");}return Res.success("编辑用户信息成功",user);}@DeleteMapping("/delete/{id}")public Res<Object> delete(@PathVariable int id){boolean res = userService.removeById(id);if(!res){return Res.error("删除失败");}return Res.success("删除成功",id);}@GetMapping("/getid/{id}")public Res<User> getId(@PathVariable int id){User user = userService.getById(id);if(user!=null){return Res.success("获取数据成功",user);}return Res.error("获取数据失败");}@GetMapping("/page")public Res<Object> page(@RequestParam(defaultValue = "1") int page,@RequestParam(defaultValue = "10") int pageSize,@RequestParam(defaultValue = "") String username,@RequestParam(defaultValue = "") String nickname){Page<User> userPage = new Page<>(page,pageSize);QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.like("username",username).or().like("nickname",nickname);return Res.success("获取数据成功",userService.getPage(userPage,queryWrapper));}@PostMapping("/disabled")public Res<Object> disabledById(@RequestBody User user){boolean res =userService.updateById(user);if(res){return Res.success("禁用成功",user);}return Res.error("禁用失败");}@PostMapping("/enable")public Res<Object> enableById(@RequestBody User user){boolean res = userService.updateById(user);if(res){return Res.success("启用成功",user);}return Res.error("启用失败");}
}
在UserController控制器中Res是我们自己封装的返回类
package com.example.demo.util;import lombok.Data;
import org.springframework.stereotype.Component;@Data
public class Res<T> {private Integer code;private String msg;private T data;public static <T> Res<T> success(String msg,T data){Res<T> res = new Res<T>();res.code = 200;res.msg = msg;res.data = data;return res;}public static <T> Res<T> error(String msg){Res<T> res = new Res<T>();res.code = 400;res.msg = msg;res.data = null;return res;}
}
配置跨域请求
在config包下配置
package com.example.demo.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**")
// .allowedOrigins("*").allowedOriginPatterns("*").allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS").allowCredentials(true).maxAge(3600).allowedHeaders("*").exposedHeaders("*");}
}
前端
依赖
"dependencies": {"axios": "^1.6.4","element-plus": "^2.4.4","pinia": "^2.1.7","sass": "^1.69.7","vue": "^3.3.11","vue-router": "^4.2.5"},
这里我给axios添加了一个baseUrl可以根据我们自己的需要添加请求头
import axios from "axios"const http = axios.create({baseURL:"http://127.0.0.1:8000",timeout:5000
});export default http
实现代码
由于功能不是很多我只写了一个页面
下面是全部实现代码
<script setup>
import { onMounted, ref } from 'vue';
import http from "@/http/http.js"
import { ElMessage, ElMessageBox } from 'element-plus'const currentPage = ref(1)
const pageSize = ref(10)const total = ref(0)const dialogVisible = ref(false)const addDialogVisible = ref(false)const tableData = ref([])const form = ref({})const keyword = ref("")const addForm =ref({username:"",password:"",email:"",nickname:""
})const addFormRef = ref(null)const rules = ref({username: [{ required: true, message: 'Please input username', trigger: 'blur' },{ min: 5, max: 14, message: 'Length should be 5 to 14', trigger: 'blur' },],password: [{ required: true, message: 'Please input password', trigger: 'blur' },{ min: 5, max: 15, message: 'Length should be 5 to 15', trigger: 'blur' },]
})const handleSizeChange = (size) => {pageSize.value = sizecurrentPage.value = 1getPage()
}const handleCurrentChange = (page) => {currentPage = pagegetPage()
}const getPage = async () => {const { data: res } = await http.get(`/user/page?page=${currentPage.value}&pageSize=${pageSize.value}&username=${keyword.value}&nickname=${keyword.value}`)total.value = res.data.totaltableData.value = res.data.records
}const disabledById = async (row) => {const { data: res } = await http.post("/user/disabled", {id: row.id,disabled: 1});if (res.code == 200) {ElMessage.success("禁用成功");getPage()} else {ElMessage.error("禁用失败");}
}const enableById = async (row) => {const { data: res } = await http.post("/user/enable", {id: row.id,disabled: 0});if (res.code == 200) {ElMessage.success("启用成功");getPage()} else {ElMessage.error("启用失败");}
}const openDialogVisible = (row) => {dialogVisible.value = trueform.value = row
}const edit = async () => {const { data: res } = await http.post("user/edit",form.value)if (res.code !== 200) {dialogVisible.value = falsereturn ElMessage.error("编辑失败")}ElMessage.success("编辑成功");dialogVisible.value = falsegetPage()
}const deleteById = (row) => {ElMessageBox.confirm('此操作将永久删除该项,是否继续?','警告',{confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning',}).then(async () => {const { data: res } = await http.delete(`/user/delete/${row.id}`)if (res.code !== 200) {return ElMessage.error("删除失败");}ElMessage({type: 'success',message: '删除成功!',})getPage()}).catch(() => {ElMessage({type: 'info',message: '已取消删除!',})})
}const openAddDialogVisible = () => {addDialogVisible.value = true
}const addUser = async () =>{const {data:res} = await http.post("/user/add",addForm.value)if(res.code!==200){addDialogVisible.value =falsereturn ElMessage.error("添加用户失败");}ElMessage.success("添加用户成功");addDialogVisible.value = falsegetPage()
}const findUser = () =>{getPage()
}const handleClose = () =>{addFormRef.value.resetFields()
}onMounted(() => {getPage()
})
</script><template><div class="index"><el-row :gutter="20"><el-col :span="4"><el-button type="primary" @click="openAddDialogVisible">添加用户</el-button></el-col><el-col :span="6"><el-input v-model="keyword" class="w-50 m-2" placeholder="请输入用户名或昵称"><template #append><el-button @click="findUser">查找用户</el-button></template></el-input></el-col></el-row><el-table :data="tableData" border style="width: 100%" stripe><el-table-column prop="id" label="ID" /><el-table-column prop="username" label="用户名" /><el-table-column prop="nickname" label="昵称" /><el-table-column prop="email" label="邮箱" /><el-table-column prop="add_time" label="添加时间" /><el-table-column label="状态"><template v-slot="scoped"><el-tag v-if="scoped.row.disabled == 1" type="danger">禁用</el-tag><el-tag v-else type="success">启用</el-tag></template></el-table-column><el-table-column label="操作"><template v-slot="scoped"><el-button size="small" type="info" @click="disabledById(scoped.row)">禁用</el-button><el-button size="small" type="success" @click="enableById(scoped.row)">启用</el-button><el-button size="small" type="warning" @click="openDialogVisible(scoped.row)">编辑</el-button><el-button size="small" type="danger" @click="deleteById(scoped.row)">删除</el-button></template></el-table-column></el-table><el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[1, 2, 3, 4]":small="small" :disabled="disabled" :background="background" layout="total, sizes, prev, pager, next, jumper":total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange" /><el-dialog v-model="dialogVisible" title="编辑" width="30%" :before-close="handleClose"><el-form :model="form" label-width="120px"><el-form-item label="id"><el-input v-model="form.id" disabled /></el-form-item><el-form-item label="昵称"><el-input v-model="form.nickname" /></el-form-item><el-form-item label="邮箱"><el-input v-model="form.email" /></el-form-item></el-form><template #footer><span class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="edit">确定</el-button></span></template></el-dialog><el-dialog v-model="addDialogVisible" title="添加用户" width="30%" @close="handleClose" ><el-form :model="addForm" label-width="120px" :rules="rules" ref="addFormRef"><el-form-item label="用户名" prop="username"><el-input v-model="addForm.username" /></el-form-item><el-form-item label="密码" prop="password"> <el-input v-model="addForm.password" /></el-form-item><el-form-item label="邮箱"><el-input v-model="addForm.email" placeholder="选填" /></el-form-item><el-form-item label="昵称"><el-input v-model="addForm.nickname" placeholder="选填" /></el-form-item></el-form><template #footer><span class="dialog-footer"><el-button @click="addDialogVisible = false">取消</el-button><el-button type="primary" @click="addUser">添加</el-button></span></template></el-dialog></div>
</template><style lang="scss" scoped>
.index {width: auto;height: auto;padding: 30px;.el-pagination {margin-top: 25px;}.el-row {margin-bottom: 25px;}
}
</style>
注意事项
后端使用mybatis-plus分页记得添加分页插件
记得配置跨域请求文件
springboot3.2.1 搭配的mybatis-plus 要使用3.5.5,其他的会报错