目录
qs.stringify() 和JSON.stringify()
1、Content-Type: application/json
2、Content-Type: multipart/form-data
3、Content-Type: application/x-www-form-urlencoded
方式一:Content-Type: application/json
5.3.1 在Nodejs项目中express框架下开启支持跨域
5.3.2 在Java项目中springboot框架下开启支持跨域
1. Ajax请求
1.1 原生ajax
//创建异步对象
var xhr = new XMLHttpRequest();
//设置请求基本信息,并加上请求头
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.open('post', 'test.php' );
//发送请求
xhr.send('name=Lan&age=18');
xhr.onreadystatechange = function () {
// 这步为判断服务器是否正确响应
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
};
1.2 jqueryAjax
var loginBtn = document.getElementsByTagName("button")[0];
loginBtn.onclick = function(){
ajax({
type:"post",
url:"test.php",
data:"name=lan&pwd=123456",
success:function(data){
console.log(data);
}
});
}
1.3 fetch
fetch('http://www.mozotech.cn/bangbang/index/user/login', {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams([
["username", "Lan"],["password", "123456"]
]).toString()
})
.then(res => {
console.log(res);
return res.text();
})
.then(data => {
console.log(data);
})
1.4 axios
axios({
method: 'post',
url: '/abc/login',
data: {
userName: 'Lan',
password: '123'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
1.5 几种ajax库的对比
ajax:
【优点:局部更新;原生支持】
【缺点:可能破坏浏览器后退功能;嵌套回调】
jqueryAjax:
【在原生的ajax的基础上进行了封装;支持jsonp】
fetch:
【优点:解决回调地狱】
【缺点:API 偏底层,需要封装;默认不带Cookie,需要手动添加; 浏览器支持情况不是很友好,需要第三方的ployfill】
axios:
【几乎完美】
axios的特点
- 支持浏览器和node.js
- 支持promise
- 能拦截请求和响应
- 能转换请求和响应数据
- 能取消请求
- 自动转换JSON数据
- 浏览器端支持防止CSRF(跨站请求伪造)
2 调用Restfull接口
2.1 restfull接口规范
URI
URI 表示资源,资源一般对应服务器端领域模型中的实体类。
URI规范:
- 不用大写;
- 用中杠-不用下杠_;
- 参数列表要encode;
- URI中的名词表示资源集合,使用复数形式。
服务器端的组合实体必须在uri中通过父实体的id导航访问:
组合实体不是first-class的实体,它的生命周期完全依赖父实体,无法独立存在,在实现上通常是对数据库表中某些列的抽象,不直接对应表,也无id。一个常见的例子是 User — Address,Address是对User表中zipCode/country/city三个字段的简单抽象,无法独立于User存在。必须通过User索引到Address:GET /user/1/addresses
HTT请求方法
通过标准HTTP方法对资源CRUD:
GET:查询
GET /zoos
GET /zoos/1
GET /zoos/1/employees
POST:创建单个资源。POST一般向“资源集合”型uri发起
POST /animals //新增动物
POST /zoos/1/employees //为id为1的动物园雇佣员工
PUT:更新单个资源(全量),客户端提供完整的更新后的资源。与之对应的是 PATCH,PATCH 负责部分更新,客户端提供要更新的那些字段。PUT/PATCH一般向“单个资源”型uri发起
PUT /animals/1
PUT /zoos/1
DELETE:删除
DELETE /zoos/1/employees/2
DELETE /zoos/1/employees/2;4;5
DELETE /zoos/1/animals //删除id为1的动物园内的所有动物
安全性和幂等性
- 安全性:不会改变资源状态,可以理解为只读的;
- 幂等性:执行1次和执行N次,对资源状态改变的效果是等价的
安全性和幂等性均不保证反复请求能拿到相同的response。以 DELETE 为例,第一次DELETE返回200表示删除成功,第二次返回404提示资源不存在,这是允许的。
复杂查询
查询可以捎带以下参数
1. 为了演示提供好以下接口:
2. 在页面导入以下js库
<script src="./node_modules/axios/dist/axios.js"></script>
<script src="./node_modules/qs/dist/qs.js"></script>
2.2 qs.js库
qs.stringify() 和JSON.stringify()
let a = {name:'hehe',age:10};
qs.stringify序列化结果如下:
name=hehe&age=10
而JSON.stringify序列化结果如下:
"{"a":"hehe","age":10}"
qs.parse()和JSON.parse()
qs.parse()将URL解析成对象的形式
let url = 'method=query_sql_dataset_data&projectId=85&appToken=7d22e38e-5717-11e7-907b-a6006ad3dba0';
qs.parse(url);
解析后的结果如下:
{method: "query_sql_dataset_data", projectId: "85", appToken: "7d22e38e-5717-11e7-907b-a6006ad3dba0"}
JSON.parse()用于从一个字符串中解析出json 对象
let str = '[{"field":"thedate","v1":"20170102"},{"field":"rev_type","v1":"大数据收入"}]'
JSON.parse(str)
解析后的结果如下:
[
{field: "thedate", v1: "20170102"},
{field: "rev_type", v1: "大数据收入"}
]
2.3 发送Get请求
<head>
<script src="./node_modules/vue/dist/vue.js"></script>
<script src="./node_modules/axios/dist/axios.js"></script>
<script src="./node_modules/qs/dist/qs.js"></script>
</head>
<body>
<div id="app">
<p>
<button @click="addUser">添加</button>
<button @click="updateUser">修改</button>
<button @click="deleteUser">删除</button>
</p>
<table border="1" cellspacing="0">
<tr>
<th>姓名</th><th>生日</th><th>年龄</th><th>邮箱</th>
</tr>
<tr v-for="(user, index) in userList">
<td>{{user.username}}</td><td>{{user.birthday}}</td><td>{{user.age}}</td><td>{{user.email}}</td>
</tr>
</table>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
userList:[]
},
methods: {
},
created() {
// 发送get请求
const _this = this
axios.get('http://127.0.0.1:8080/user/1')
.then(function(resp){
_this.userList.push(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
},
})
</script>
传递GET请求参数:
• 直接在 URL 中附加参数
getUser(){
// 发送get请求
const _this = this
axios.get('http://127.0.0.1:8080/user?name=admin' )
.then(function(resp){
_this.userList.push(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
}
• 使用 parmas 属性添加GET参数
getUser(){
// 发送get请求
const _this = this
axios.get('http://127.0.0.1:8080/user', {
params: {name: 'admin'}
} )
.then(function(resp){
_this.userList.push(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
}
2.4 发送post请求
axios POST提交数据的三种请求方式写法
1、Content-Type: application/json
addUser(){
var userData = {
id: 1,
username: 'tom',
birthday: '2020-08-08T13:13:25.262+0000',
age: 18,
email: 'tom@sohu.com'
}
// 发送post请求
axios.post('http://127.0.0.1:8080/user', userData)
.then(function(resp){
console.log(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
},
2、Content-Type: multipart/form-data
FormData
FormData 接口提供了一种表示表单数据的键值对的构造方式,经过它的数据可以使用 XMLHttpRequest.send() 方法送出,本接口和此方法都相当简单直接。如果送出时的编码类型被设为 "multipart/form-data",它会使用和表单一样的格式。
实现了 FormData 接口的对象可以直接在for...of结构中使用
addUser(){
let userFormData = new FormData()
userFormData.append('id', '1')
userFormData.append('username', 'tom')
userFormData.append('birthday', '2020-08-08T13:13:25.262+0000')
userFormData.append('age', '18')
userFormData.append('email', 'tom@sohu.com')
// 发送post请求
axios.post('http://127.0.0.1:8080/user', userFormData)
.then(function(resp){
console.log(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
},
3、Content-Type: application/x-www-form-urlencoded
URLSearchParams
如果你想构建一个简单的GET请求,并且通过<form>的形式带有查询参数,可以将它直接传递给URLSearchParams。URLSearchParams 接口定义了一些实用的方法来处理 URL 的查询字符串。一个实现了 URLSearchParams 的对象可以直接用在 for...of 结构中
addUser(){
let userParams = new URLSearchParams()
userParams.append('id', '1')
userParams.append('username', 'tom')
userParams.append('birthday', '2020-08-08T13:13:25.262+0000')
userParams.append('age', '18')
userParams.append('email', 'tom@sohu.com')
// 发送post请求
axios.post('http://127.0.0.1:8080/user', userParams)
.then(function(resp){
console.log(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
},
或
addUser(){
var userData = {
id: 1,
username: 'tom',
birthday: '2020-08-08T13:13:25.262+0000',
age: 18,
email: 'tom@sohu.com'
}
// 发送post请求
axios.post('http://127.0.0.1:8080/user', Qs.stringify(userData))
.then(function(resp){
console.log(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
},
2.5 发送put请求
updateUser(){
var userData = {
id: 1,
username: 'tom',
birthday: '2020-08-08T13:13:25.262+0000',
age: 18,
email: 'tom@sohu.com'
}
// 发送put请求
axios.put('http://localhost:8080/user/1', userData)
.then(function(resp){
console.log(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
},
2.6 发送delete请求
方式一:Content-Type: application/json
deleteUser(){
// 发送delete请求:以json对象的形式带参
axios.delete('http://localhost:8080/user', {
data: {age: 20}
})
.then(function(resp){
console.log(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
},
方式二:使用 parmas 属性
deleteUser(){
// 发送delete请求:以json对象的形式带参
axios.delete('http://localhost:8080/user', {
params: {age: 20}
})
.then(function(resp){
console.log(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
},
2.7 执行多个并发请求
getUser1(){
const _this = this
axios.get('http://127.0.0.1:8080/user/1')
},
getUser2(){
const _this = this
axios.get('http://127.0.0.1:8080/user/2')
},
getMultiUser(){
axios.all([this.getUser1(), this.getUser2()])
.then(axios.spread(function (acct, perms) {
// 两个请求现在都执行完成
}));
}
3 配置axois
3.1 自定义配置
使用自定义配置新建一个 axios 实例
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
3.2 配置拦截器
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
config.auth = { //设置的自定义 `Authorization`头
username: 'janedoe',
password: 's00pers3cret'
}
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
console.log('响应状态码' + response.status)
console.log('响应数据:' + JSON.stringify(response.data))
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
4 vue中使用axios
1. 使用vue-cli创建vue项目
vue create crm
2. 使用vue命令安装axios
cd crm
vue add axios
这时自动已在vue应用程序中配置好axios,后续直接使用即可
3. 使用axios发送ajax请求
created(){
// 发送get请求
const _this = this
axios.get('http://127.0.0.1:8080/user/1')
.then(function(resp){
_this.userList.push(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
}
4. 启动服务
cd crm
$ npm run serve
报错原因: 该项目安装了eslint规范,ESLint 是在 ECMAScript/JavaScript 代码中识别和报告模式匹配的工具,它的目标是保证代码的一致性和避免错误。在许多方面,它和 JSLint、JSHint 相似。
解决方法1:
在package.json文件内加入如下代码:
"rules": {
"generator-star-spacing": "off",
"no-tabs":"off",
"no-unused-vars":"off",
"no-console":"off",
"no-irregular-whitespace":"off",
"no-debugger": "off"
},
如图所示:
解决方法2:
在安装项目的时候不安装ESLint:
Use ESLint to lint your code? NO
5 axios跨域
5.1 什么时跨域问题
axios跨域问题:Ajax加载其 它服务器的API数据,可能会 遇到跨域的问题
➢跨域,是指在当前域下,要访问 其它域中的资源
5.2 Vue 开发环境中配置代理
在vue.config.js配置文件中,配置代理服务器
✓访问 当前指定地址时,会把请求交给代理服务器发送,避开跨域问题
✓ Vue中使用时,直接给出不含服务器域名的url即可
1. 创建vue.config.js
// vue配置项
module.exports = {
devServer: {
// 遇到未知请求,将会交给代理服务器处理
proxy: 'http://127.0.0.1:8888'
}
}
2. 发送ajax请求时写相对路径
methods: {
addUser(){
var userData = {
id: 1,
username: 'tom',
birthday: '2020-08-08T13:13:25.262+0000',
age: 18,
email: 'tom@sohu.com'
}
// 发送post请求
this.axios.post('/user', userData)
.then(function(resp){
console.log(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
},
},
created(){
// 发送get请求
const _this = this
this.axios.get('/user/1')
.then(function(resp){
_this.userList.push(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
}
}
➢可以同时设置多个跨域请求的代理
✓发送axios请求时,请求URL要使用 指定的代理前缀
✓只对开发服务器有效,生产环境中仍存在跨域问题
在vue.config.js进行配置
// vue配置项
module.exports = {
devServer: {
// 遇到未知请求,将会交给代理服务器处理
//proxy: 'http://127.0.0.1:8888'
proxy: {
'/api': {
target: 'http://127.0.0.1:8888',
pathRewrite: {
'^api/': '/' // 不是'^/api': '/'
}
}
}
}
}
在页面发送ajax请求
methods: {
addUser(){
var userData = {
id: 1,
username: 'tom',
birthday: '2020-08-08T13:13:25.262+0000',
age: 18,
email: 'tom@sohu.com'
}
// 发送post请求
this.axios.post('/api/user', userData)
.then(function(resp){
console.log(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
},
},
created(){
// 发送get请求
const _this = this
this.axios.get('/api/user/1')
.then(function(resp){
_this.userList.push(resp.data)
})
.catch(function(e){
console.error('请求失败:',e)
})
}
5.3 服务器端支持跨域
5.3.1 在Nodejs项目中express框架下开启支持跨域
1. 安装 cors 跨域支持模块 yarn add cors
yarn add cors
或
npm install -S cors
2. 启用 cors 中间件
5.3.2 在Java项目中springboot框架下开启支持跨域
在配置WebMvc相关配置类中添加如下代码:
@Configuration
public class AdminWebMvcConfing implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.allowedHeaders("*")
.maxAge(3600)
.allowCredentials(true);
}
}