Java体系知识之Echarts&跨域访问&Vue脚手架
(1)Echarts图表工具
(2)跨域访问
(3)Vue 脚手架
1 Echarts
1.1 技术简介
(1)Apache ECharts
(2)一个基于 JavaScript 的开源可视化图表库
(3)使用步骤:
A.引入echarts.js文件
B.创建一个指定了宽高的容器
C.根据图表的配置项和数据以图表的形式呈现数据
C1.基于准备好的dom,初始化echarts实例
C2.指定图表的配置项和数据
C3.使用刚指定的配置项和数据显示图表
1.2 案例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.3.3/echarts.js"></script>
</head>
<body>
<div id="main" style="width: 600px;height:400px;"></div>
</body>
<script>
var myChart = echarts.init(document.getElementById('main'));
var option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
}]
};
myChart.setOption(option);
</script>
</html>
2 跨域访问(重点)
2.1 错误信息
Access to XMLHttpRequest at 'http://localhost:8080/area' from origin 'http://127.0.0.1:8848' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
2 area.html:106 o
2.2 跨域访问
(1)Cookie:
A.HTTP协议:无状态协议
B.客户端和服务端,服务端只关心请求
C.如何让服务端知道该客户端已经不是第一次访问它了,可以使用Cookie
D.数据安全考虑:
浏览器基于Cookie同源限制
D1.不涉及到跨域请求时,Cookie会随着请求自动发送到服务器端,用于验证自己身份
D2.涉及到跨域请求时,默认不会在请求中携带Cookie数据
同源:
http:
对于协议|域名|端口,若两个页面有一个值不一样,就认为是不同源
http:
http:
(2)同源政策越来越严格:
浏览器:使用Ajax技术时,只能向自己的服务器发请求
(3)CORS:
Cross-Origin Resource Sharing 跨域资源共享
(4)解决:
在服务器端设置允许哪个客户端来访问它
跨域请求:
resp.setHeader("Access-Control-Allow-Origin","http://127.0.0.1:8848");
resp.setHeader("Access-Control-Allow-Methods","*");
resp.setHeader("Access-Control-Max-Age","3600");
resp.setHeader("Access-Control-Allow-Headers","*");
resp.setHeader("Access-Control-Allow-Credentials","true");
2.3 省市区案例-改造
2.3.1 area.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="root">
<el-select v-model="proCode" placeholder="请选择" @change="getCity()">
<el-option v-for="pro in proList" :key="pro.areaCode" :label="pro.areaName" :value="pro.areaCode">
</el-option>
</el-select>省
<el-select v-model="cityCode" placeholder="请选择" @change="getCoun()">
<el-option v-for="city in cityList" :key="city.areaCode" :label="city.areaName" :value="city.areaCode">
</el-option>
</el-select>市
<el-select v-model="counCode" placeholder="请选择">
<el-option v-for="coun in counList" :key="coun.areaCode" :label="coun.areaName" :value="coun.areaCode">
</el-option>
</el-select>区县
</div>
</body>
<script>
new Vue({
el: "#root",
data: {
proCode: '',
proList: [],
cityCode: '',
cityList: [],
counCode: '',
counList: []
},
methods: {
getCity() {
this.cityCode = "";
this.counCode = "";
this.counList = [];
var provinceCode = this.proCode;
console.log(provinceCode);
axios.get("http://localhost:8080/area?parentCode=" + provinceCode)
.then(resp => {
console.log(resp);
this.cityList = resp.data.returnData;
}).catch(error => {})
},
getCoun() {
this.counCode = "";
var cityCode = this.cityCode;
console.log(cityCode);
axios.get("http://localhost:8080/area?parentCode=" + cityCode)
.then(resp => {
console.log(resp);
this.counList = resp.data.returnData;
}).catch(error => {})
}
},
mounted() {
axios.post("http://localhost:8080/area", "parentCode=0")
.then(resp => {
console.log(resp);
this.proList = resp.data.returnData;
}).catch(error => {
console.log(error);
})
}
})
</script>
</html>
2.3.2 AreaServlet
package com.javasm.servlet;
import com.alibaba.fastjson.JSON;
import com.javasm.entity.Area;
import com.javasm.entity.CodeAndMsg;
import com.javasm.entity.ReturnEntity;
import com.javasm.service.AreaService;
import com.javasm.service.impl.AreaServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
@WebServlet("/area")
public class AreaServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("Access-Control-Allow-Origin","http://127.0.0.1:8848");
resp.setHeader("Access-Control-Allow-Methods","*");
resp.setHeader("Access-Control-Max-Age","3600");
resp.setHeader("Access-Control-Allow-Headers","*");
resp.setHeader("Access-Control-Allow-Credentials","true");
req.setCharacterEncoding("utf-8");
String parentCodeStr = req.getParameter("parentCode");
Integer parentCode = null;
if (parentCodeStr != null && !"".equals(parentCodeStr)) {
parentCode = Integer.valueOf(parentCodeStr);
}
AreaService areaService = new AreaServiceImpl();
List<Area> areaList = areaService.findAreaList(parentCode);
resp.setContentType("application/json;charset=utf-8");
PrintWriter writer = resp.getWriter();
ReturnEntity re = new ReturnEntity();
if (areaList.size() > 0) {
re.setReturnCode(CodeAndMsg.DATA_SUCCESS.getReturnCode());
re.setReturnMsg(CodeAndMsg.DATA_SUCCESS.getReturnMsg());
re.setReturnData(areaList);
} else {
re.setReturnCode(CodeAndMsg.DATA_FAILURE.getReturnCode());
re.setReturnMsg(CodeAndMsg.DATA_FAILURE.getReturnMsg());
}
writer.print(JSON.toJSONString(re));
writer.flush();
writer.close();
}
}
3 Vue 脚手架(重点)
3.1 技术简介
(1)Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统
(2)可以快速搭建完整的前端项目
(3)有自己的服务器,涉及到跨域访问
(4)安装工具:
A.Node.js
npm 是 Node.js 标准的软件包管理器
B.Vue脚手架
CLI 服务是一个开发环境依赖;
它是一个 npm 包,局部安装在每个 @vue/cli 创建的项目中;
(5)了解:
Babel:
Babel 是一个工具链,主要用于在当前和旧的浏览器或环境中;
将 ECMAScript 2015+ 代码转换为 JavaScript 向后兼容版本的代码;
webpack:
是一个现代 JavaScript 应用程序的静态模块打包器->module bundler;
当 webpack 处理应用程序时,它会递归地构建一个依赖关系图;
包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle
(6)单页面应用
(7)修改端口号:
const {
defineConfig
} = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
/* 设置端口号 */
devServer: {
port: 8088, //端口
}
})
3.2 新增功能
(1)创建vue文件
(2)导入组件、配置组件
3.3 案例
3.3.1 Login.vue
<template>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>登录</span>
</div>
<el-form ref="loginForm" :model="loginForm" label-width="80px" :rules="rules" hide-required-asterisk>
<el-form-item label="用户名" prop="userName">
<el-input v-model="loginForm.userName" prefix-icon="el-icon-user"></el-input>
</el-form-item>
<el-form-item label="密码" prop="userPwd">
<el-input v-model="loginForm.userPwd" show-password prefix-icon="el-icon-lock"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('loginForm')">登录</el-button>
<el-button @click="resetForm('loginForm')">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</template>
<script>
export default {
data() {
return {
loginForm: {
userName: '',
userPwd: '',
},
rules: {
userName: [{
required: true,
message: '请输入用户名',
trigger: 'blur'
},
{
min: 4,
max: 8,
message: '长度在 4 到 8 个字符',
trigger: 'blur'
}
],
userPwd: [{
required: true,
message: '请输入密码',
trigger: 'blur'
},
{
min: 4,
max: 8,
message: '长度在 4 到 8 个字符',
trigger: 'blur'
}
],
}
}
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
console.log(valid);
if (valid) {
this.$router.push('/main');
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
},
mounted() {
}
}
</script>
<style>
.text {
font-size: 14px;
}
.item {
margin-bottom: 18px;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both
}
.box-card {
width: 480px;
margin: 179px auto;
}
</style>
3.3.2 Main.vue
<template>
<el-container>
<el-header>
java教育金融系统
</el-header>
<el-container>
<el-aside width="200px">
<el-menu default-active="2" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose">
<el-submenu :index="menu.menuId.toString()" v-for="menu in menuList">
<template slot="title">
<i :class="menu.menuIcon"></i>
<span>{{menu.menuName}}</span>
</template>
<el-menu-item-group>
<el-menu-item :index="sub.menuId.toString()" v-for="sub in menu.subMenu">{{sub.menuName}}
</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-main>Main</el-main>
</el-container>
</el-container>
</template>
<script>
export default {
data() {
return {
activeIndex2: '1',
menuList: [{
"menuId": 1000,
"menuName": "系统模块",
"menuIcon": "el-icon-s-tools",
"subMenu": [{
"menuId": 1001,
"menuName": "用户模块"
}, {
"menuId": 1002,
"menuName": "菜单模块"
}]
}, {
"menuId": 2000,
"menuName": "产品模块",
"menuIcon": "el-icon-s-goods",
"subMenu": [{
"menuId": 2001,
"menuName": "产品系列模块"
}, {
"menuId": 2002,
"menuName": "产品基础模块"
}]
}]
}
},
methods: {
handleSelect(key, keyPath) {
console.log(key, keyPath);
},
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
},
queryMenus() {}
},
mounted() {
this.queryMenus();
}
}
</script>
<style>
.el-header,
.el-footer {
background-color: #B3C0D1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
color: #333;
text-align: center;
line-height: 200px;
}
.el-main {
background-color: #E9EEF3;
color: #333;
text-align: center;
line-height: 160px;
}
body>.el-container {
margin-bottom: 40px;
}
.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
line-height: 260px;
}
.el-container:nth-child(7) .el-aside {
line-height: 320px;
}
html,
body,
#root,
.el-container {
height: 100%;
}
* {
margin: 0;
padding: 0;
}
</style>