Spring+Vue(小demo)
1 前端
前端使用 vue + element ui + echarts + axios
1.0 搭建前端环境
1.0.1 NodeJs安装
下载 - 解压 - 配置环境变量 - 验证
C:\Users\MJoe>node -v
v14.17.0
C:\Users\MJoe>npm -v
6.14.13
1.0.2 VueCli安装
npm install -g @vue/cli
// 验证
C:\Users\MJoe>vue --version
@vue/cli 4.5.13
1.1 vue ui 构建vue项目
C:\Users\MJoe> vue ui
安装element ui axios 插件 和 echarts 依赖
1.2 使用idea打开项目
在idea中使用vue.js 首先安装Vue插件
main.js 文件中首先设置 axios baseURL
axios.defaults.baseURL='http://82.156.203.xxx:8181' // 后端ip+port
router/index.js设置路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import Base from "@/views/Base";
import FruitManage from "@/views/FruitManage";
import Index from "@/views/Index";
import FruitAdd from "@/views/FruitAdd";
import FruitBar from "@/views/FruitBar";
import FruitUpdate from "@/views/FruitUpdate";
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: '管理',
component: Base,
redirect: '/index',
children: [
{
path: '/index',
name: '首页',
show: false,
component: Index
},
{
path: '/FruitManage',
name: '查看',
show: true,
component: FruitManage
},
{
path: '/FruitAdd',
name: "新增",
show: true,
component: FruitAdd
},
{
path: '/FruitBar',
name: '柱形图',
show: true,
component: FruitBar
},
{
path: '/FruitUpdate',
name: '更新',
show: false,
component: FruitUpdate
}
]
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
App.vue 设置 前端浏览器的最下面一层的vue
Base.vue 设置总体container
{{submenu.name}}
{{item.name}}
王小虎
FruitManage.vue
编辑
删除
FruitAdd.vue
立即创建
重置
FruitUpdate.vue
更新
重置
FruitBar.vue
前端 <---数据----> 后端
前端使用axios请求后端数据,可以携带数据,格式为JSON
axios.post("/fruit/add",this.ruleForm) // 其中ruleForm为JSON对象传入到后端
后端使用方法参数的方式接收JSON数据后,使用注解@RequestBody转化为一个entity对象
@PostMapping("/add")
public Boolean fruitAdd(@RequestBody Fruit fruit){
int insert = fruitMapper.insert(fruit);
if (insert == 0){
return false;
}else return true;
}
2 后端
springboot + mybatisplus + mysql
2.1 新建springboot项目
添加 mybatis-plus依赖集成到springboot
com.baomidou
mybatis-plus-boot-starter
3.4.3
2.2 新建Fruit数据库
create database fruit;
use fruit;
create table Fruit(
id int not null auto_increment primary key ,
name varchar(10) not null ,
number int not null ,
picture text
)engine = innodb charset =utf8;
2.3 使用mybatisX生成代码插件
生成 mapper service mapper.xml
2.4 application.yml
server:
port: 8181
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://82.156.203.105:3306/fruit?useUnicode=true&characterEncoding=utf-8
username: root
password: ma1234
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
2.5 MybatisplusConfig (mp配置)
package com.mjoe.fruit_backend.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName : MPConfig
* @Description : mybatisplusconfig
* @Author : MJoeBoyae
* @Date: 2021-06-23 16:42
*/
@Configuration
@MapperScan("com.mjoe.fruit_backend.mapper")
public class MPConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
2.6 跨域问题解决
package com.mjoe.fruit_backend.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @ClassName : CorsConfig
* @Description : 跨域问题
* @Author : MJoeBoyae
* @Date: 2021-06-23 17:01
*/
@Configuration
public class CorsConfig{
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowCredentials(false)
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.allowedOriginPatterns("*");
}
};
}
}
2.7 FruitController实现增删改查
package com.mjoe.fruit_backend.controller;
import com.mjoe.fruit_backend.VO.BarView;
import com.mjoe.fruit_backend.entity.Fruit;
import com.mjoe.fruit_backend.mapper.FruitMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName : FruitContrller
* @Description : FruitController
* @Author : MJoeBoyae
* @Date: 2021-06-23 16:43
*/
@Controller
@ResponseBody
@RequestMapping("/fruit")
public class FruitContrller {
@Autowired
FruitMapper fruitMapper;
@GetMapping("/manage")
public List fruitManage(){
List fruits = fruitMapper.selectList(null);
return fruits;
}
@PostMapping("/add")
public Boolean fruitAdd(@RequestBody Fruit fruit){
int insert = fruitMapper.insert(fruit);
if (insert == 0){
return false;
}else return true;
}
@GetMapping("/manageById/{id}")
public Fruit manageById(@PathVariable("id") int id){
Fruit fruit = fruitMapper.selectById(id);
return fruit;
}
@PostMapping("/update")
public boolean fruitUpdate(@RequestBody Fruit fruit){
int i = fruitMapper.updateById(fruit);
if (i == 0){
return false;
}else return true;
}
@DeleteMapping("/deleteById/{id}")
public boolean fruitDelete(@PathVariable("id") int id){
int i = fruitMapper.deleteById(id);
if (i == 0){
return false;
}else return true;
}
@GetMapping("/barView")
public BarView varView(){
List fruits = fruitMapper.selectList(null);
BarView barView = new BarView();
List names = new ArrayList<>();
List numbers = new ArrayList<>();
for (Fruit fruit : fruits) {
names.add(fruit.getName());
numbers.add(fruit.getNumber());
}
barView.setNames(names);
barView.setNumbers(numbers);
return barView;
}
}
2.8 VO封装(view object)
前端使用Echarts.js绘制交互图,根据option选项中标签和数据的的格式,在后台封装成对应的VO对象
前端option选项:
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'bar'
}]
};
从
图像和option
中,可以得到:
- xAxis轴对应的数据是从xAxis中的data拿出来的,格式为List,对应mysql 表中的列:
name
- 数据使从series的data中取出,格式也为List,对应与mysql表中的列:
number
所以封装一个BarView对象,用于取出mysql表中的name和number,类型均为List
package com.mjoe.fruit_backend.VO;
import lombok.Data;
import java.util.List;
/**
* @ClassName : BarView
* @Description : bar对象
* @Author : MJoeBoyae
* @Date: 2021-06-23 18:19
*/
@Data
public class BarView {
private List names;
private List numbers;
}
在controller中定义特定的请求handler
@GetMapping("/barView")
public BarView varView(){
List fruits = fruitMapper.selectList(null);
BarView barView = new BarView();
List names = new ArrayList<>();
List numbers = new ArrayList<>();
for (Fruit fruit : fruits) {
names.add(fruit.getName());
numbers.add(fruit.getNumber());
}
barView.setNames(names);
barView.setNumbers(numbers);
return barView;
}
3 部署前端-后端到docker
3.1 部署后端
首先使用maven打包工具,将后端项目打包成jar包
编写Dockerfile文件用于构建镜像
FROM java:8
MAINTAINER MJoeBoyae
COPY *.jar app.jar
EXPOSE 8181
ENTRYPOINT ["java","-jar","app.jar"]
将Dockerfile文件和jar包上传到服务器(服务器默认已经安装好docker环境,并会使用)
cd到该目录下后,执行docker build命令
docker build -t fruidback:v1 .
使用docker run 运行该镜像,并使用宿主机8181端口映射容器内的8181端口
docker run -d --name fruidbackend -p 8181:8181 fruidback:v1
3.2 部署前端
基于nginx方式,部署vue项目
首先运行npm run build
构建该vue项目,生成dist
文件夹
编写Dockerfile文件,运用构建vue镜像
# 设置基础镜像,这里使用最新的nginx镜像,前面已经拉取过了
FROM nginx
# 定义作者 Edison
MAINTAINER MJoe
EXPOSE 80
# 将dist文件中的内容复制到 /usr/share/nginx/html/ 这个目录下面
COPY dist/ /usr/share/nginx/html/
上传dist文件夹
和Dockerfile
文件到服务端后,cd到该文件夹下,使用docker build
命令构建镜像
docker build -t fruitvue .
使用docker run 运行该镜像,并使用宿主机4030端口映射容器内的80端口(底层使用了Nginx)
docker run -d --name fruidvue -p 4030:80 fruitvue:v1
4 测试
访问:http://82.156.203.105:4030/
tips:由于使用了history模式,所以不能直接在浏览器刷新页面(404)