原因解析可参考链接
比对一下两次请求的头信息
前台触发请求的代码如下:
后端处理预检测的代码如下:
源代码如下:
public class TokenInterceptor extends HandlerInterceptorAdapter {
@Autowired
private TokenService tokenService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 获取方法上的注解
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("P3P", "CP=CAO PSA OUR");
if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
response.addHeader("Access-Control-Allow-Methods", "POST,GET,TRACE,OPTIONS");
response.addHeader("Access-Control-Allow-Headers", "Content-Type,Origin,Accept");
response.addHeader("Access-Control-Max-Age", "120");
}
if(!(handler instanceof HandlerMethod)){
System.out.println("预检测");
return false;
}
这样可以回应预检测,可以查看前端请求头的返回信息:
如果在vue中进行如下设置,将不会触发预检测。
调用方法的代码如下,以下为异步请求
import axios from 'axios'
import common from "./getToken";
import javaRsp from "./javaRsp";
import setLocal from "./setLocal";
let api = axios.create({
timeout: 500000,
baseURL:'/file'
})
api.interceptors.response.use(response => {
return response;
}, (error) => {
return error.response;
})
api.doPost = async (url, params) => {
let location = await api.post(url, params, {
headers: {
'Content-Type': 'application/json'
}
});
return location;
}
export default {
async login(params) {
let url = "/token/getTicket";
let str = JSON.stringify(params);
let tokenData;
console.log(str)
let response = await api.doPost(url, str);
console.log(response)
if (response.status == 200 && response.data.code == 200) {
//存储本例localstorage
setLocal.setLocal("ticket",response.data.data);
tokenData = await common.getToken(response.data.data);
}else if(response.status != 200){
tokenData=javaRsp.javaErrorRsp(response.status,"网络异常!");
}else{
tokenData=response.data;
}
return tokenData;
}
}
实际在项目开发中经常会遇见前端多次请求的问题,我也找过前端要他们处理一下,但是都说没办法处理,前端使用的是脚手架,即使前端有做接口防抖处理,但是作为后端还是应当使用一些技术来防治接口幂等的问题,建议在重要的操作做一下验证,比如使用唯一令牌的方式来确保每一次操作只能操作一次。详情见链接。