目录
1.搭建数据库
create schema apple;
use apple;
CREATE TABLE `fruit` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(11) DEFAULT NULL,
`sale` int DEFAULT NULL,
`icon` varchar(300) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
INSERT INTO `fruit` VALUES (1,'苹果',333,'https://i02piccdn.sogoucdn.com/7a0b5e51b03f3245'),(2,'香蕉',133,'https://i03piccdn.sogoucdn.com/3506f1c96181e955'),(3,'橘子',299,'https://i03piccdn.sogoucdn.com/6c8d3681470e2f24'),(6,'火龙果',133,'https://i02piccdn.sogoucdn.com/49fb5d2c90f97382'),(15,'芒果',222,'https://i02piccdn.sogoucdn.com/283567c3cb9018ab');
2.搭建Vue项目
cdm : vue ui
2.1 创建普通项目
2.2 安装插件
2.3 router.index.js
2.4 Bar.vue
<template>
<div id="myChart" :style="{width: '800px', height: '600px'}"></div>
</template>
<script>
export default {
name: 'Echarts',
mounted(){
// 基于准备好的dom,初始化echarts实例
let myChart = this.$echarts.init(document.getElementById('myChart'))
// 绘制图表
myChart.setOption({
title: {
text: '水果销量统计',
left: 'center',
top: 20,
textStyle: {
color: '#555555'
}
},
tooltip: {},
xAxis: {
data: [
"苹果",
"香蕉",
"橘子",
"火龙果",
"葡萄",
"西瓜"
]
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [
{
value: 333,
itemStyle: {
color: "#3fb1e3"
}
},
{
value: 133,
itemStyle: {
color: "yellow"
}
},
{
value: 99,
itemStyle: {
color: "bisque"
}
},
{
value: 222,
itemStyle: {
color: "red"
}
},
{
value: 399,
itemStyle: {
color: "blue"
}
},
{
value: 123,
itemStyle: {
color: "forestgreen"
}
}
]
}]
});
}
}
</script>
2.5 Pie.vue
<template>
<div id="myChart" :style="{width: '800px', height: '600px'}"></div>
</template>
<script>
export default {
name: 'Echarts',
mounted(){
// 基于准备好的dom,初始化echarts实例
let myChart = this.$echarts.init(document.getElementById('myChart'))
// 绘制图表
myChart.setOption({
title: {
text: '水果销量统计',
subtext: '数据统计',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left',
},
series: [
{
name: '访问来源',
type: 'pie',
radius: '50%',
data: [
{value: 333, name: '苹果',itemStyle:{color: "#3fb1e3"}},
{value: 133, name: '香蕉',itemStyle:{color: "yellow"}},
{value: 99, name: '橘子',itemStyle:{color: "bisque"}},
{value: 222, name: '火龙果',itemStyle:{color: "red"}},
{value: 399, name: '葡萄',itemStyle:{color: "blue"}},
{value: 123, name: '西瓜',itemStyle:{color: "forestgreen"}}
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
});
}
}
</script>
2.6 Table
<template>
<div >
<el-table
:data="tableData"
border
style="width: 50%">
<el-table-column
fixed
prop="id"
label="编号"
width="150">
</el-table-column>
<el-table-column
prop="name"
label="水果名"
width="120">
</el-table-column>
<el-table-column
prop="sale"
label="销售量"
width="120">
</el-table-column>
<el-table-column
prop="icon"
label="图片"
width="220">
<!--slot-scope:绑定icon这条数据-->
<template slot-scope="scope">
<img :src="scope.row.icon" style="height: 70px"/>
</template>
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="100">
<template slot-scope="scope">
<el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
<el-button type="text" size="small">编辑</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
methods: {
handleClick(row) {
console.log(row);
}
},
data() {
return {
tableData: null
}
}
}
</script>
2.7 App.vue
<div id="app">
<div id="nav">
<router-link to="/add">添加数据</router-link> |
<router-link to="/table">数据管理</router-link> |
<router-link to="/pie">饼图</router-link> |
<router-link to="/bar">柱状图</router-link>
</div>
<div style="border:0px solid red;width: 800px;height: 600px;margin-left: 366px;">
<router-view/>
</div>
</div>
3.搭建SpringBoot
3.1 创建普通项目
导入Mybatis Plus
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<!--代码生成器-->
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<!--代码生成器需要一个模板导入-->
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
3.2 连接数据库
3.2 GenerateTest(代码自动生成)
package com.node.demo;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
public class GenerateTest {
public static void main(String[] args) {
//创建generator对象
AutoGenerator autoGenerator = new AutoGenerator();
//数据源
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setDbType(DbType.MYSQL);
dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
dataSourceConfig.setUsername("root");
dataSourceConfig.setPassword("123456");
dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/apple");
autoGenerator.setDataSource(dataSourceConfig);
//全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java");
globalConfig.setAuthor("admin");
globalConfig.setOpen(false);
globalConfig.setServiceName("%sService");
autoGenerator.setGlobalConfig(globalConfig);
//包信息
PackageConfig packageConfig = new PackageConfig();
packageConfig.setParent("com.node.demo");
packageConfig.setEntity("entity");
packageConfig.setMapper("mapper");
packageConfig.setService("service");
packageConfig.setServiceImpl("service.impl");
packageConfig.setController("controller");
autoGenerator.setPackageInfo(packageConfig);
//策略配置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setInclude("fruit");
strategyConfig.setNaming(NamingStrategy.underline_to_camel);
strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
strategyConfig.setEntityLombokModel(true);
autoGenerator.setStrategy(strategyConfig);
//运行
autoGenerator.execute();
}
}
3.3 application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/apple
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
configuration:
mapper-locations: classpath:com/node/demo/mapper/xml/*.xml
server:
port: 8081
3.4 Controller
package com.node.demo.controller;
import com.node.demo.entity.Fruit;
import com.node.demo.service.FruitService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* <p>
* 前端控制器
* </p>
*
* @author admin
* @since 2021-05-22
*/
@RestController
@RequestMapping("//fruit")
public class FruitController {
@Autowired
private FruitService fruitService;
@GetMapping("/list")
public List<Fruit> list(){
return fruitService.list();
}
}
3.5 DemoApplication.java
3.6 测试
4.整合Spring+Vue
4.1 java解决端口跨域问题
package com.node.demo.configuration;
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 CrosConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}
4.2Table.vue
<template slot-scope="scope">
<img :src="scope.row.icon" style="height: 70px"/>
</template>
created() {
let _this=this //this:是回调函数function (response)的this,而_this是全局的this
axios.get('http://localhost:8081/fruit/list').then(function (response) {
console.log(response)
_this.tableData =response.data
})
}
4.3 CURD
4.3.1 删除
4.3.1.1 FruitController
@DeleteMapping("/delete/{id}")
public boolean delete(@PathVariable("id") Integer id){
return fruitService.removeById(id);
}
4.3.1.2 Table.vue
<template slot-scope="scope">
<el-button @click="Del(scope.row)" type="text" size="small">删除</el-button>
<el-button type="text" @click="modify(scope.row)" size="small">修改</el-button>
</template>
Del(row) {
let _this=this
this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
axios.delete('http://localhost:8081/fruit/delete/'+row.id).then(function (response) {
//因为后端返回的是一个Boolean类型,所有判断一下是否为true
if(response.data){
/*_this.$message({
type: 'success',
message: '删除成功!'
})
location.reload()*/
_this.$alert(row.name+'删除成功','删除数据',{
confirmButtonText:'确定',
callback:action => {
location.reload()
}
})
}
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
}
4.3.2 修改
4.3.2.1 FruitController
@GetMapping("/find/{id}")
public Fruit find(@PathVariable("id") Integer id){
return fruitService.getById(id);
}
@PutMapping("/update")
public boolean update(@RequestBody Fruit fruit){ //获取前端传递的Fruit数据
return fruitService.updateById(fruit);
}
4.3.2.2 Table.vue
modify(row){
this.$router.push({
path:'/Modify',
query:{
id:row.id
}
})
}
}
4.3.3 添加
4.3.3.1 FruitController
@PostMapping("/add")
public boolean add(@RequestBody Fruit fruit){
return this.fruitService.save(fruit);
}
4.3.3.2 Add.vue
<template>
<el-form ref="fruitRules" :model="fruit" :rules="rules" label-width="80px" class="demo-ruleForm" style="width: 600px">
<el-form-item label="名称" prop="name">
<el-input v-model="fruit.name"></el-input>
</el-form-item>
<el-form-item label="销量" prop="sale">
<el-input v-model.number="fruit.sale"></el-input>
</el-form-item>
<el-form-item label="图片" prop="icon">
<el-input v-model="fruit.icon"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit('fruitRules')">立即创建</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</template>
<script>
export default {
name: "Add",
data() {
return {
fruit: {
name: '',
sale: '',
icon: ''
},
rules:{
name:[
{ required: true, message: '请输入水果名称', trigger: 'blur' }
],
sale:[
{ required: true, message: '请输入销量', trigger: 'blur' },
{ type: 'number', message: '销量必须为数字值'}
],
icon:[
{ required: true, message: '请输入图片链接', trigger: 'blur' }
]
}
}
},
methods: {
onSubmit(formName){
this.$refs[formName].validate((valid) => {
if (valid) {
let _this = this
axios.post('http://localhost:8081/fruit/add',this.fruit).then(function (response) {
if(response.data){
_this.$alert(_this.fruit.name+'添加成功!', '添加数据', {
confirmButtonText: '确定',
callback: action => {
//跳转到/table
_this.$router.push('/table')
}
});
}
})
}
});
}
}
}
</script>
<style scoped>
</style>
4.4柱状图数据显示
4.4.1 观察
4.4.2 BarVo.java
package com.node.demo.vo;
/*
* 由于前端的图标要获取后端的数据,是以一个集合对象的形式出来。而是分开x轴和y轴两种数据,所以需要重新写一个类*/
import lombok.Data;
import java.util.List;
/*
* 对应前端的Bar*/
@Data
public class BarVo {
private List<String> names; //对应前端bar的x轴数据
private List<DataVo> values; 对应前端bar的y轴数据
}
4.4.3 PieVo.java
package com.node.demo.vo;
import lombok.Data;
import java.util.Map;
/*
* 这里对应的是Bar中y轴的data数据
* */
@Data
public class DataVo {
private Integer value;
private Map<String,String> itemStyle; //前端itemStyle的是键:值属性
}
4.4.4 FruitService.java
package com.node.demo.service;
import com.node.demo.entity.Fruit;
import com.baomidou.mybatisplus.extension.service.IService;
import com.node.demo.vo.BarVo;
import com.node.demo.vo.PieVo;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author admin
* @since 2021-05-22
*/
public interface FruitService extends IService<Fruit> {
public BarVo barVoList(); //前端返回的是一个对象集合
}
4.4.5 FruitServiceImpl.java
package com.node.demo.service.impl;
import com.node.demo.entity.Fruit;
import com.node.demo.mapper.FruitMapper;
import com.node.demo.service.FruitService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.node.demo.util.DataUtil;
import com.node.demo.vo.BarVo;
import com.node.demo.vo.DataVo;
import com.node.demo.vo.PieVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* 服务实现类
* </p>
*
* @author admin
* @since 2021-05-22
*/
@Service
public class FruitServiceImpl extends ServiceImpl<FruitMapper, Fruit> implements FruitService {
@Autowired
private FruitMapper fruitMapper;
public BarVo barVoList() {
/*先查出数据再转换Vo*/
BarVo barVo = new BarVo(); //BarVo里面有Names和Values(DataVo)两个数据:相当于包了DataVo
List<String> names = new ArrayList<>();
List<DataVo> values = new ArrayList<>();
//先查出数据
List<Fruit> fruits = this.fruitMapper.selectList(null);
for (Fruit fruit : fruits) {
names.add(fruit.getName());
DataVo dataVo = new DataVo();//DataVo里面有Value(Sale)和ItemStyle(颜色)两个数据
dataVo.setValue(fruit.getSale());//dataVo.setValue就是数据库水果的sale数据
dataVo.setItemStyle(DataUtil.createItemStyle(fruit.getSale()));
values.add(dataVo);
}
barVo.setNames(names);
barVo.setValues(values);
//转换Vo
return barVo;
}
4.4.6 DataUtil
package com.node.demo.util;
import java.util.HashMap;
import java.util.Map;
public class DataUtil {
public static Map<String,String> createItemStyle(Integer sale){
String color = "";
if(sale<60){
color = "#96dee8";
}
if(sale>60 && sale<160){
color = "#c4ebad";
}
if(sale>160 && sale<300){
color = "#6be6c1";
}
if(sale>300 && sale<500){
color = "#3fb1e3";
}
if(sale>500){
color = "#a0a7e6";
}
Map<String,String> map = new HashMap<>();
map.put("color", color);
return map;
}
}
4.4.7 FruitController.java
@GetMapping("/barVo")
public BarVo barVo(){
return this.fruitService.barVoList();
}
4.4.8 Bar.Vue
<template>
<div id="myChart" :style="{width: '800px', height: '600px'}"></div>
</template>
<script>
export default {
name: 'Echarts',
mounted(){
let _this = this
axios.get('http://localhost:8081/fruit/barVo').then(function (response) {
// 基于准备好的dom,初始化echarts实例
let myChart = _this.$echarts.init(document.getElementById('myChart'))
// 绘制图表
myChart.setOption({
title: {
text: '水果销量统计',
left: 'center',
top: 20,
textStyle: {
color: '#555555'
}
},
tooltip: {},
xAxis: {
data: response.data.names
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: response.data.values
}]
});
})
}
}
</script>
4.5 饼状图数据显示
4.4.1 观察
4.4.2 PieVo.java
package com.node.demo.vo;
import lombok.Data;
import java.util.Map;
@Data
public class PieVo {
private Integer value;
private Map<String,String> itemStyle;
private String name;
}
4.4.3 FruitService.java
public List<PieVo> pieVoList(); 前端返回的是一个集合对象
4.4.4 FruitServiceImpl.java
public List<PieVo> pieVoList() {
List<PieVo> pieVoList = new ArrayList<>();
List<Fruit> fruits = this.fruitMapper.selectList(null);
for (Fruit fruit : fruits) {
PieVo pieVo = new PieVo();
pieVo.setValue(fruit.getSale());
pieVo.setName(fruit.getName());
pieVo.setItemStyle(DataUtil.createItemStyle(fruit.getSale()));
pieVoList.add(pieVo);
}
return pieVoList;
}
4.4.5 FruitController.java
@GetMapping("/pieVo")
public List<PieVo> pieVo(){
return this.fruitService.pieVoList();
}
4.4.6 Pie.Vue