本文主要是想通过后端 Spring Boot 技术和前端 Vue 技术来简单开发一个增删改查demo,该demo以简单、方便理解的方式来记录前后端结合使用的过程,方便正式开发复杂项目时能提前整体理解流程,资源链接链接:https://pan.baidu.com/s/1xQ3R-IoGRK7KxAZEgENhUg
提取码:vase
复制这段内容后打开百度网盘手机App,操作更方便哦
demo最终实现的效果如下图:
一,后台
server.port=8080
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/db01?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
#扫描xml
mybatis.mapper-locations= classpath:mapper/*.xml
#分页
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.pageSizeZero=true
pagehelper.params=countSql
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.1version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.21version>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelper-spring-boot-starterartifactId>
<version>1.2.3version>
dependency>
public class Dept {
private Integer deptno;
private String dname;
private String loc;
@Override
public String toString() {
return "Dept{" +
"deptno=" + deptno +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
'}';
}
public Integer getDeptno() {
return deptno;
}
public void setDeptno(Integer deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
}
@Mapper
public interface DeptMapper {
int addDept(Dept dept);
int deleteById(Integer deptno);
int updateDeptById(Dept dept);
List<Dept> findAllDept(@Param("keywords") String keywords);
}
public interface DeptService {
int addDept(Dept dept);
int deleteById(Integer id);
int updateDeptById(Dept dept);
List<Dept> findAllDept(String keywords);
}
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public int addDept(Dept dept) {
return deptMapper.addDept(dept);
}
@Override
public int deleteById(Integer id) {
return deptMapper.deleteById(id);
}
@Override
public int updateDeptById(Dept dept) {
return deptMapper.updateDeptById(dept);
}
@Override
public List<Dept> findAllDept(String keywords) {
return deptMapper.findAllDept(keywords);
}
}
@RestController
@RequestMapping("/dept")
public class DeptController {
@Autowired
private DeptService deptService;
/**
* 分页查询
* @param page
* @param size
* @param keywords
* @return
*/
@GetMapping("/")
public RespPageBean findAll(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer size, String keywords){
PageHelper.startPage(page, size);
List<Dept> list = deptService.findAllDept(keywords);
PageInfo pageInfo = new PageInfo(list);
RespPageBean bean = new RespPageBean();
bean.setData(pageInfo.getList());
bean.setTotal(pageInfo.getTotal());
return bean;
}
/**
* 删除
* @param deptno
* @return
*/
@DeleteMapping("/{deptno}")
public RespBean deleteDept(@PathVariable Integer deptno){
if(deptService.deleteById(deptno)==1){
return RespBean.DELETE_SUCCESS;//删除成功
}
return RespBean.DELETE_ERROR;//删除失败
}
/**
* 添加
* @param dept
* @return
*/
@PostMapping("/")
public RespBean addDept(@RequestBody Dept dept){
if(deptService.addDept(dept)==1){
return RespBean.ADD_SUCCESS;//添加成功
}
return RespBean.ADD_ERROR;//添加失败
}
/**
* 更新
* @param dept
* @return
*/
@PutMapping("/")
public RespBean updateDept(@RequestBody Dept dept){
if(deptService.updateDeptById(dept)==1){
return RespBean.UPDATE_SUCCESS;//添加成功
}
return RespBean.UPDATE_ERROR;//添加失败
}
public class RespBean {
private Integer status;
private String msg;
private Object obj;
public RespBean(Integer status, String msg) {
this.status = status;
this.msg = msg;
}
public static final RespBean DELETE_SUCCESS = new RespBean(200,"删除成功");
public static final RespBean DELETE_ERROR = new RespBean(-1,"删除失败");
public static final RespBean ADD_SUCCESS = new RespBean(200,"添加成功");
public static final RespBean ADD_ERROR = new RespBean(-1,"添加失败");
public static final RespBean UPDATE_SUCCESS = new RespBean(200,"更新成功");
public static final RespBean UPDATE_ERROR = new RespBean(-1,"更新失败");
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
private RespBean(Integer status, String msg, Object obj) {
this.status = status;
this.msg = msg;
this.obj = obj;
}
private RespBean() {
}
}
public class RespPageBean {
private Long total;
private List<?> data;
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public List<?> getData() {
return data;
}
public void setData(List<?> data) {
this.data = data;
}
}
<mapper namespace="com.song.mapper.DeptMapper">
<insert id="addDept" parameterType="com.song.entity.Dept">
insert into dept(dname,loc)values (#{dname},#{loc})
insert>
<delete id="deleteById">
delete from dept where deptno=#{deptno}
delete>
<update id="updateDeptById" parameterType="com.song.entity.Dept">
update dept set dname=#{dname},loc=#{loc} where deptno=#{deptno}
update>
<select id="findAllDept" resultType="com.song.entity.Dept" >
select*from dept where 1=1
<if test="keywords!=null">
and dname like concat('%',#{keywords},'%')
if>
select>
mapper>
二 前端,首先构建vue项目
效果图
安装axiox(npm i axios)
安装element-ui
在 main.js 中写入以下内容:
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';
Vue.use(ElementUI);
new Vue({
el: '#app',
render: h => h(App)
});
//跨域代理
let proxyObj={};
proxyObj['/']={
ws: false, //webstock
target:'http://localhost:8080',//代理对象
changeOrigin: true,
pathRewrite: {
'^/': ''
}
}
//vue项目启动端口
module.exports={
devServer:{
host: 'localhost',
port: 8085,
proxy: proxyObj
}
}
3.添加api.js封装 get,put,post,delete请求
import axios from 'axios'
import {Message} from 'element-ui';
//结果拦截
axios.interceptors.response.use(success => {
//data.msg 是后端RespBean中响应的信息
if (success.status && success.status == -1 && success.data.status == 500) {
Message.error({message: success.data.msg})
return;
}
//data.msg 是后端RespBean中响应的信息
if (success.data.msg) {
Message.success({message: success.data.msg})
}
return success.data;
}, error => {
//data.msg 是后端RespBean中响应的信息
if (error.response.data.msg) {
Message.error({message: error.response.data.msg})
} else {
Message.error({message: '未知错误!'})
}
return;
})
/**
* post请求
* @param url 请求地址
* @param params 请求参数
* @returns {AxiosPromise}
*/
export const postRequest=(url,params)=>{
return axios({
method:'post',
url:`${url}`,
data:params
})
}
/**
* get请求
* @param url 请求地址
* @param params 请求参数
* @returns {AxiosPromise}
*/
export const getRequest=(url,params)=>{
return axios({
method:'get',
url:`${url}`,
data:params
})
}
/**
* put请求
* @param url 请求地址
* @param params 请求参数
* @returns {AxiosPromise}
*/
export const putRequest=(url,params)=>{
return axios({
method:'put',
url:`${url}`,
data:params
})
}
/**
* delete请求
* @param url 请求地址
* @param params 请求参数
* @returns {AxiosPromise}
*/
export const deleteRequest=(url,params)=>{
return axios({
method:'delete',
url:`${url}`,
data:params
})
}
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
}
]
const router = new VueRouter({
routes
})
export default router
<template>
<div class="home">
<div>
<el-input placeholder="请输入部门进行搜索,可以直接回车搜索..."
@clear="initAllDept"
prefix-icon="el-icon-search"
style="width: 350px;margin-right: 10px"
clearable
:clear="initAllDept"
v-model="keywords"
@keydown.enter.native="initAllDept"
>
el-input>
<el-button icon="el-icon-search" size="small" type="primary" @click="initAllDept" >
搜索
el-button>
<div style="display: flex;justify-content: space-between">
<el-button type="primary" icon="el-icon-plus" size="small" @click="addDept">添加部门el-button>
div>
div>
<div style="margin-top: 8px">
<el-table
:data="depts"
border
style="width: 100%">
<el-table-column
prop="deptno"
label="编号"
width="180">
el-table-column>
<el-table-column
prop="dname"
label="部门名称"
width="180">
el-table-column>
<el-table-column
prop="loc"
label="地址">
el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="small" @click="updateDept(scope.row)">编辑el-button>
<el-button size="small" type="danger" @click="deleteDept(scope.row)">删除el-button>
template>
el-table-column>
el-table>
<div style="display:flex;justify-content:flex-end ">
<el-pagination
background
layout="sizes, prev, pager, next, jumper, ->, total, slot"
@current-change="currentChange"
@size-change="sizeChange"
:total="total">
el-pagination>
div>
div>
<el-dialog
:title="dialogTitle"
:visible.sync="dialogVisible"
width="50%">
<el-form ref="form" :model="dept" label-width="80px">
<el-form-item label="部门名称">
<el-input v-model="dept.dname">el-input>
el-form-item>
<el-form-item label="部门地址">
<el-input v-model="dept.loc">el-input>
el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">提交el-button>
el-form-item>
el-form>
el-dialog>
div>
template>
<script>
// 导入封装的请求
import {getRequest} from "../uitls/api";
import {postRequest} from "../uitls/api";
import {putRequest} from "../uitls/api";
import {deleteRequest} from "../uitls/api";
export default {
name: 'Home',
data() {
return {
keywords:'',
depts:[],//显示数据
total:0,
dialogTitle:"添加",
dialogVisible:false,
size:10,//分页每页10条数据
page:1,//从第一页开始
dept:{
dname:'',
loc:''
}
}
},
methods:{
//分页
currentChange(currentChange){
this.page=currentChange
this.initAllDept()
},
sizeChange(sizeChange){
this.size=sizeChange
this.initAllDept()
},
/**
* /dept 请求地址
*/
initAllDept(){
//调用get请求
getRequest("/dept/?keywords="+this.keywords+"&page="+this.page+"&size="+this.size).then(res=>{
if(res){
this.depts=res.data
this.total=res.total
}
})
},
onSubmit(){
if(this.dept.deptno){//this.dept.deptno有值就是修改,否则就是删除
//修改
//调用put请求
putRequest("/dept/",this.dept).then(res=>{
if(res){
this. dialogVisible=false
//修改成功刷新数据
this.initAllDept()
//清空弹出层数据
this.dept.dname='';
this.dept.loc='';
}
})
}else{
//添加
//调用post请求
postRequest("/dept/",this.dept).then(res=>{
if(res){
this. dialogVisible=false
//添加成功刷新数据
this.initAllDept()
//清空弹出层数据
this.dept.dname='';
this.dept.loc='';
}
})
}
},
addDept(){
//打开弹出层
this.dialogVisible=true
//改变弹出成title
this.dialogTitle="添加"
//清空弹出层数据
this.dept.dname='';
this.dept.loc='';
},
updateDept(data){
//填充数据 数据回显
this.dept=data
//打开弹出层
this.dialogVisible=true
//改变弹出成title
this.dialogTitle="修改"
},
deleteDept(data){
this.$confirm('此操作将永久删除【' + data.dname + '】, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//调用delete请求
deleteRequest("/dept/"+data.deptno).then(res=>{
if(res){
this.initAllDept()
}
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
}
},
//初始化数据
mounted(){
this.initAllDept();
}
}
script>
<style>
.home{
width: 800px;
margin: 20px auto;
}
style>