要求:SpringToolSuite4,Postman测试工具,VsCode,数据库等,
为了方便小伙伴们可以更快的掌握,代码注释很详细。
控制器:
1.接收HTTP请求
2.调用业务逻辑或数据操作(Model)
3.返回视图名(View)
4.返回数据(application/json/xml)
数据库:
create table customers(
id int primary key auto_increment,
name varchar(64) not null,
area enum('东北','华北','华东','西北','华南','西南','中南') not null,
principal varchar(64) not null,
level enum('普通客户','大客户','合作伙伴','重点开发客户') not null
);
SpringToolSuite4工程目录
application.properties
#数据源
spring.datasource.url=jdbc:mysql://阿里云ip:3306/a
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.http.log-request-details=true
logging.level.web=debug
Customer.java
package com.newer.test.pojo;
/**
* 实体(POJO - 简单的 Java 对象 / JavaBean) JavaBean 组件(规范) 1)无参数构造器 2)getters、setters
* 访问方法 3)有访问方法的字段(成员变量)才称属性
* @author Admin
*
*/
public class Customer {
int id;
String name;
String area;
String principal;
String level;
public Customer() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
public String getPrincipal() {
return principal;
}
public void setPrincipal(String principal) {
this.principal = principal;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
@Override
public String toString() {
return "Customer [id=" + id + ", name=" + name + ", area=" + area + ", principal=" + principal + ", level="
+ level + "]";
}
}
CustomerMapper.java
package com.newer.test.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.jdbc.SQL;
import com.newer.test.pojo.Customer;
/**
* MyBatis 是一个 Java 的 SQL 映射框架(ORM - 对象关系映射) 1)类属性映射表字段 2)类与类的关系映射表与表的关系
* @author Admin
*
*/
@Mapper
public interface CustomerMapper {
/**
* 添加客户
*
* @param customer
* @return 是否成功
*/
@Insert("insert into customers(name,area,principal,level) values(#{name},#{area},#{principal},#{level})")
@Options(useGeneratedKeys = true, keyProperty = "id")
boolean save(Customer customer);
/**
* 显示所有客户信息
*
* @return 客户列表
*/
@Select("select * from customers")
List<Customer> findAll();
/**
* 删除客户
*/
@Delete("delete from customers where id=#{id}")
void remove(int id);
/**
* 更新客户
*/
@Update("update customers set name=#{name},area=#{area},principal=#{principal},level=#{level} where id=#{id} ")
void updata(Customer customer);
/**
* 条件查询(基于动态 SQL)
*
* @param customer
* @return
*/
@SelectProvider(type = CustomerProvider.class, method = "find")
List<Customer> search(Customer customer);
/**
* 动态 SQL 定义
*
* @author wtao
*
*/
static class CustomerProvider {
/**
* 字段是否有值
*
* @param field
* @return
*/
static boolean isExist(String field) {
return field != null && field.trim().length() > 0;
}
/**
* 条件查询
*
* @param customer
* @return
*/
public String find(Customer customer) {
return new SQL() {
{
SELECT("*");
FROM("customers");
if (customer != null) {
if (isExist(customer.getName())) {
WHERE("name like concat('%',#{name},'%')");
}
if (isExist(customer.getArea())) {
WHERE("area like #{area}");
}
if (isExist(customer.getPrincipal())) {
WHERE("principal like #{principal}");
}
if (isExist(customer.getLevel())) {
WHERE("level like #{level}");
}
}
ORDER_BY("id");
}
}.toString();
}
}
}
CustomerController.java
package com.newer.test.controller;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.newer.test.mapper.CustomerMapper;
import com.newer.test.pojo.Customer;
/**
* 控制器
* 1)接收 HTTP 请求
* 2)调用业务逻辑或数据操作(Model
* 3)返回视图名(View
* 4)返回数据(application/json/xml
*
* @author
*
*/
@Controller
public class CustomerController {
/**
* 控制器依赖数据操作(自动注入/装配
*/
@Autowired
CustomerMapper customerMapper;
// 返回视图名
@GetMapping("/")
public String index() {
return "index.html";
}
/**
* GET /api/search
*
* @param customer HTTP GET,HTTP 请求中的字符串查询参数,不是 payload(@RequestBody)
* @return
*/
@GetMapping("/api/search")
@ResponseBody
public List<Customer> search(Customer customer) {
// 约定由于配置
// 使用约定好的规则,则很简单
return customerMapper.search(customer);
}
// HTTP 字符串查询参数名称任意命名
// 1)映射请求参数和方法参数
// 2)设置是否必须(required
// 3)可以设置默认值(defaultValue)
@GetMapping("/api/search2")
@ResponseBody
public List<Customer> search(
@RequestParam(name = "n", required = false) String name,
@RequestParam(name = "a", required = false) String area,
@RequestParam(name = "p", required = false) String principal,
@RequestParam(name = "l", defaultValue = "", required = false) String level
) {
// 参数名不一致,手动装配
Customer c = new Customer();
c.setName(name);
c.setArea(area);
c.setPrincipal(principal);
c.setLevel(level);
return customerMapper.search(c);
}
/**
* POST /api/customer
*
* @param customer HTTP 请求中的负载(payload),格式为 application/json,必须指定 @RequestBody 注解
*
* @return 存储在数据库中的客户对象
*/
@ResponseBody
@PostMapping("/api/customer")
public Customer create(@RequestBody Customer customer) {
// 存入数据库前 customer 状态成为:瞬时,没有主键值(PK)
// 存储存储库
customerMapper.save(customer);
// 存入数据库后 customer 状态成为:持久化,存在主键值
return customer;
}
/**
* GET /api/customer
*
* @return 客户列表
*/
@GetMapping("/api/customer")
// @ResponseBody
public @ResponseBody List<Customer> findAll() {
return customerMapper.findAll();
}
/**
* delete
*/
@DeleteMapping("/api/customer/{id}")
@ResponseBody
public void remove(@PathVariable int id) {
customerMapper.remove(id);
}
/**
* put
*/
@PutMapping("/api/customer/{id}")
@ResponseBody
public void updata(@PathVariable int id,@RequestBody Customer customer) {
customer.setId(id);
customerMapper.updata(customer);
}
}
index.html
<!doctype html>
<html lang="en">
<head>
<title>客户关系管理平台</title>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="bootstrap.min.css">
<!-- axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- vue -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<!-- 标题 -->
<div class="jumbotron jumbotron-fluid p-3">
<div class="container">
<h1 class="display-3">客户关系管理平台</h1>
<p class="lead"><span class="badge badge-pill badge-danger">牛耳教育</span></p>
</div>
</div>
<!-- 主体 -->
<div id="app" class="container-fluid">
<div class="row">
<div class="col-lg-3 col-sm-12">
<div class="card">
<div class="card-body">
<h4 class="card-title">添加客户资料</h4>
<!-- 表单 添加新客户 -->
<!-- <form action=""> -->
<div class="form-group">
<label for="">客户名称</label>
<input v-model="name" type="text" class="form-control" name="" required placeholder="客户名称">
</div>
<div class="form-group ">
<label for="">地区</label>
<select class="form-control" v-model="area">
<option>请选择</option>
<option>北京</option>
<option>华北</option>
<option>华东</option>
<option>中南</option>
</select>
</div>
<div class="form-group">
<label for="">客户经理</label>
<select class="form-control" v-model="principal">
<option>请选择</option>
<option>小明</option>
<option>旺财</option>
<option>球球</option>
<option>孙小美</option>
</select>
</div>
<div class="form-group ">
<label for="">客户等级</label>
<select class="form-control" v-model="level">
<option>请选择</option>
<option>普通客户</option>
<option>大客户</option>
<option>合作伙伴</option>
<option>重点开发客户</option>
</select>
</div>
<button @click="create" type="submit" class="btn btn-block btn-success">保存</button>
<!-- </form> -->
</div>
</div>
</div>
<div class="col-lg-9 col-sm-12">
<div class="card">
<div class="card-body">
<!-- 条件查询 -->
<form class="form-inline" action="" method="">
<!-- 整排查询框 -->
<label>客户名称:</label>
<input type="text" v-model="sName">
<label>地区:</label>
<select v-model="sArea" @change="search">
<option value="">所有</option>
<option>东北</option>
<option>华北</option>
<option>华东</option>
<option>中南</option>
</select>
<label>客户经理:</label>
<select v-model="sPrinicpal" @change="search">
<option value="">所有</option>
<option>小明</option>
<option>旺财</option>
<option>球球</option>
<option>孙小美</option>
</select>
<label>客户等级:</label>
<select v-model="sLevel" @change="search">
<option value="">所有</option>
<option>普通客户</option>
<option>大客户</option>
<option>合作伙伴</option>
<option>重点开发客户</option>
</select>
<button @click="search" class="btn-primary" type="button">
查询
</button>
</form>
</div>
</div>
<!-- 显示数据 -->
<table class="table table-bordered">
<thead>
<tr>
<th>编号</th>
<th>客户名称</th>
<th>地区</th>
<th>客户经理</th>
<th>客户等级</th>
<th style="width:30%">操作</th>
</tr>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in customerList" :key="index">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.area}}</td>
<td>{{item.principal}}</td>
<td>{{item.level}}</td>
<td>
<!-- 按钮 -->
<div class="row">
<div class="col">
<button @click="edit(index)" type="button" name="" id=""
class="btn btn-primary btn-block" data-toggle="modal"
data-target="#modelId">编辑</button>
<!-- 模态框 -->
<!-- Button trigger modal -->
<!-- Modal -->
<div class="modal fade" id="modelId" tabindex="-1" role="dialog"
aria-labelledby="modelTitleId" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">修改客户资料</h5>
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="">客户名称</label>
<input v-model="editItem.name" type="text"
class="form-control" name="" required
placeholder="客户名称">
</div>
<div class="form-group ">
<label for="">地区</label>
<select class="form-control" v-model="editItem.area">
<option>请选择</option>
<option>北京</option>
<option>华北</option>
<option>华东</option>
<option>中南</option>
</select>
</div>
<div class="form-group">
<label for="">客户经理</label>
<select class="form-control" v-model="editItem.principal">
<option>请选择</option>
<option>小明</option>
<option>旺财</option>
<option>球球</option>
<option>孙小美</option>
</select>
</div>
<div class="form-group ">
<label for="">客户等级</label>
<select class="form-control" v-model="editItem.level">
<option>请选择</option>
<option>普通客户</option>
<option>大客户</option>
<option>合作伙伴</option>
<option>重点开发客户</option>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
data-dismiss="modal">取消</button>
<button @click="updata" type="button" class="btn btn-primary"
data-dismiss="modal">确定</button>
</div>
</div>
</div>
</div>
</div>
<div class="col">
<button @click="remove(item.id)" type="button" name="" id=""
class="btn btn-danger btn-block">删除</button>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
// 加载
customerList: [],
// 创建
name: '',
area: '请选择',
level: '普通客户',
principal: '请选择',
// 条件查询
sName: undefined,
sArea: '所有',
sLevel: '所有',
sPrinicpal: '所有',
// 编辑
editItem: {},
editIndex: 0
},
methods: {
// 编辑的方法
edit: function (i) {
// 获取编辑的索引
this.editIndex = i;
this.editItem = {};
this.editItem.id = this.customerList[i].id;
this.editItem.name = this.customerList[i].name;
this.editItem.area = this.customerList[i].area;
this.editItem.principal = this.customerList[i].principal;
this.editItem.level = this.customerList[i].level;
},
// 更新
updata: function () {
// console.log(this.editItem);
let url = `/api/customer/${this.editItem.id}`;
let params = this.editItem;
axios.put(url, params)
.then(res => {
console.log(res)
axios.get("/api/customer")
.then(res => {
console.log(res)
this.customerList = res.data;
})
.catch(err => {
console.error(err);
})
})
.catch(err => {
console.error(err);
})
},
// 条件查询
search: function () {
// 请求路径 RESTful API
let url = '/api/search2';
// 字符串查询参数(键值对),编码后追加在 URL 后面的
// 参数键的名称,可以自定义,最好与实体一致
// 约定的参数名
let params = {
name: this.sName,
area: this.sArea === '所有' ? undefined : this.sArea,
level: this.sLevel === '所有' ? undefined : this.sLevel,
principal: this.sPrinicpal === '所有' ? undefined : this.sPrinicpal
};
// 参数名不匹配(任意的
let params2 = {
n: this.sName,
a: this.sArea === '所有' ? undefined : this.sArea,
l: this.sLevel === '所有' ? undefined : this.sLevel,
p: this.sPrinicpal === '所有' ? undefined : this.sPrinicpal
};
// GET
// 1) 请求路径
// 2)字符串查询参数
axios.get(
url,
{ params: params2 }
)
.then(res => {
// console.log(res);
this.customerList = res.data;
});
},
// 创建
create: function () {
// RESTful API 及参数
let url = '/api/customer';
let payload = {
name: this.name,
principal: this.principal,
area: this.area,
level: this.level
};
// AJAX POST 请求
axios.post(url, payload)
.then(res => {
// console.log(res.data)
this.customerList.push(res.data);
this.name = '',
this.area = '请选择',
this.principal = '请选择',
this.level = '普通客户'
})
.catch(err => {
// console.error(err);
})
},
// 删除
remove: function (id) {
let url = `/api/customer/${id}`;
axios.delete(url)
.then(res => {
console.log(res)
axios.get("/api/customer")
.then(res => {
console.log(res)
this.customerList = res.data;
})
.catch(err => {
console.error(err);
})
})
.catch(err => {
console.error(err);
})
}
},
created() {
// 前端、后端在同一个进程中
let url = '/api/customer';
// 加载
axios.get(url)
.then(res => {
// console.log(res)
this.customerList = res.data;
})
.catch(err => {
// console.error(err);
})
},
});
</script>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
</body>
</html>
效果如图:
基于SpringMVC+MyBatis+Vue实现客户关系管理平台(CRUD)就到这结束啦!有问题的小伙伴可以留言。