在学习uniapp的过程中,发现uniapp
框架默认集成request
请求框架存在问题,发送请求时在header中塞入token值,而后台接收不到,也就是说uniapp默认的request请求框架,不支持在请求头中放入token的做法。
基于以上原因,笔者确定放弃默认的请求框架,引入第三方axios
请求框架。
那么该怎么说呢?默认三步骤:一引入,二配置,三测试
这里笔者使用的npm
工具安装axios组件,同时指定版本,如果不指定版本默认会安装最新版本,最新版本的axios组件在真机测试阶段会出现请求不适配的问题,这里先按下不谈,后续文章会说明情况。
npm i axios@0.27.2
注意:一定要配置axios.defaults.adapter
来适配uniapp框架。
同时在请求和响应拦截中,对token进行设置和获取操作,在前后端分离的项目中以token
作为用户请求后台的唯一合法依据。
import Vue from 'vue'
import axios from 'axios'
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';
const service = axios.create({
baseURL: "http://127.0.0.1:7777/",
timeout: 6000,
})
// 请求拦截
service.interceptors.request.use(config => {
// 非登录接口添加token
if (config["url"].indexOf("login") < 0) {
config.headers['token'] = uni.getStorageSync('token');
}
return config;
},
error => {
return Promise.reject(error);
});
// 响应拦截
service.interceptors.response.use(res => {
if (res.status == 200) {
// 请求成功后设置token
if (res.data.code == 100) {
uni.setStorageSync('token', res.header["token"]);
}
return res.data;
} else {
return Promise.reject(res.data.msg);
}
});
// 自定义适配器 , 适配uniapp语法
axios.defaults.adapter = function(config) {
return new Promise((resolve, reject) => {
let settle = require('axios/lib/core/settle');
let buildURL = require('axios/lib/helpers/buildURL');
let buildFullPath = require('axios/lib/core/buildFullPath');
let fullurl = buildFullPath(config.baseURL, config.url);
uni.request({
method: config.method.toUpperCase(),
url: buildURL(fullurl, config.params, config.paramsSerializer),
header: config.headers,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
dataType: config.dataType,
responseType: config.responseType,
sslVerify: config.sslVerify,
complete: function complete(response) {
response = {
data: response.data,
status: response.statusCode,
errMsg: response.errMsg,
header: response.header,
config: config
};
settle(resolve, reject, response);
},
});
})
}
export default service
同时别忘了将配置的axios.js
文件引入到main.js
中
配置main.js
。由于笔者在uniapp中使用的Vue2.x版本,所以以下main.js内写法与Vue3.x的写法不同,请读者注意粘贴。
import Vue from 'vue'
import App from './App'
import uView from "uview-ui";
import axios from './common/axios/axios.js'
Vue.config.productionTip = false
Vue.use(uView);
Vue.prototype.$api = axios
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
完成以上工作,uniapp引入axios组件的工作就完成了,那么下面就开始测试,是否可以正常访问了。
1、由于由于跨域问题,于是笔者在后台的接口类上配置跨域注解。
CrossOrigin
: 该注解用于标注该接口可被跨域访问。可能读者会想为什么不在前端配置代理来实现跨域呢?当前为了测试组件是否引入成功,所以一切从简,以测试结果为主。前端配置代理实现跨域请继续阅读下文。
@CrossOrigin
@RestController
public class MembersController {
@Resource
private MembersService membersService;
/**
* 登录账号
* @param param 账号和密码
* @return 返回 Ret
*/
@PostMapping("/login")
public Ret login(@RequestBody LoginBo param){
return membersService.login(param);
}
}
逻辑处理中心:
@Service
public class MembersService extends ServiceImpl<MembersMapper, Members> implements IService<Members> {
@Resource
private MembersMapper membersMapper;
/**
* 登录账号
* @param param 账号和密码
* @return 返回 Ret
*/
public Ret login(LoginBo param) {
// 1、验参
String account = param.getAccount();
// 2、查询结果并判断
QueryWrapper<Members> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("account", account);
Members members = membersMapper.selectOne(queryWrapper);
if ( members == null ) {
return Ret.builder().code(300).msg("登录失败!").build();
} else if ( !Objects.equals(param.getPassword(), members.getPassword()) ) {
return Ret.builder().code(300).msg("密码填写错误!").build();
}
// 3、封装返回登录成功日志信息
LoginVo loginVo = LoginVo.builder()
.account(account)
.avatar(members.getAvatar())
.token(account)
.nickName(members.getNickName())
.build();
return Ret.builder().code(100).data(loginVo).build();
}
}
uniapp中的login.vue
页面
这个$api 是否眼熟,是的就是在main.js中配置的全局别名。
methods: {
login() {
let data = {
...this.form
}
this.$api({
method: 'post',
url: '/login',
data: data
}).then(res => {
if (res.code == 100) {
// 存入本次缓存中
uni.setStorageSync('userInfo', res.data);
this.$u.toast('登录成功');
uni.navigateBack();
} else {
this.$u.toast(res.msg);
}
}).catch(err => {
console.log(err)
});
},
},
测试结果如下:
输入错误的账号和密码,请求状态 200
,表示请求成功的意思,也就是表示axios组件引入成功了。
这里需要用到manifest.json
文件,点击该文件并选择源码视图
并在其中配置以下信息
"h5": {
"devServer": {
"hot": true,
"port": 8080,
"disableHostCheck": true,
"proxy": {
"/api": {
"target": "http://127.0.0.1:7777/",
"changeOrigin": true,
"secure": false,
"pathRewrite": {
"^/api": ""
}
}
}
}
}
同时修改axios.js文件
const service = axios.create({
baseURL: "/api",
timeout: 6000
})
这时就可以删除后台接口上的 @CrossOrigin
注解了。
下面测试结果如下:
测试成功,这样就实现了通过前端配置代理来解决跨域问题,同时这样服务器会更安全一些,避免被其他的前台所访问。以上是笔者在学习uniapp整合axios过程中的一些总结,希望可以对各位读者有所帮助。