本例中,后端接口为post请求,请求地址为:http://127.0.0.1:8081/event/findEventList/1/2。
vue使用的是vue3。
跨域(Cross-Origin Resource Sharing,简称CORS)是指浏览器出于安全考虑,限制网页从一个域名(源)向另一个域名的资源发起请求的行为。这是由浏览器的同源策略(Same-Origin Policy)引起的安全机制。
同源策略要求请求的协议(HTTP/HTTPS)、域名(host)、端口(port)三者必须完全相同,否则视为跨域。例如:
http://a.com 请求 https://a.com → 跨域(协议不同)
http://a.com 请求 http://b.com → 跨域(域名不同)
http://a.com:80 请求 http://a.com:8080 → 跨域(端口不同)
引入配置文件:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*") // 允许所有来源(生产环境应指定具体域名)
.allowedMethods("GET", "POST", "PUT", "DELETE");
}
}
在Controller类上放上注解@CrossOrigin
。
利用npm install axios
安装axios,用于发送http请求。
<script>
import axios from 'axios';//引入axios
export default {
data() {//Vue组件的核心选项之一,必须是一个函数,通过返回对象来定义组件的响应式数据,返回对象内都是属性和其对应值,可以利用this被方其他函数调用
return {
data:"",
buttonInfo:"获取数据按钮"
};
},
methods: {//函数集合
fetchData() {//这里是下面html代码中按钮的点击事件触发的函数
axios.post(//这里是post请求
`http://127.0.0.1:8081/event/findEventList/1/2`,
{},
{
headers: {
'Content-Type': 'application/json'
}
}
)
.then(response => {
this.data = response.data;
console.log(this.data);//打印数据到浏览器控制台
})
.catch(error => {
console.error('请求失败:', error);
});
}
}
}
</script>
<template>
<button v-on:click = "fetchData" v-text="buttonInfo"></button>
</template>
这里可以在main.js上做通用处理,
main.js 初始:
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App);
app.mount('#app');
main.js 处理后:
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios';//这里做了通用导入axios
const app = createApp(App);
app.config.globalProperties.$http1 = axios;//这里对app这个vue对象的配置中的全局属性中,我随意定义的http1属性设置为axios
app.mount('#app');
然后vue中如下:
<script>
// import axios from 'axios';//引入axios,但这里被通用导入替代,已经不需要了
export default {
data() {
return {
data:"",
buttonInfo:"获取数据按钮"
};
},
methods: {
fetchData() {
this.$http1.post(//这里是post请求,这里利用在main.js设置的全局属性http1
`http://127.0.0.1:8081/event/findEventList/1/2`,
{},
{
headers: {
'Content-Type': 'application/json'
}
}
)
.then(response => {
this.data = response.data;
console.log(this.data);
})
.catch(error => {
console.error('请求失败:', error);
});
}
}
}
</script>
<template>
<button v-on:click = "fetchData" v-text="buttonInfo"></button>
</template>
main.js还可以更进一步,如下:
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios';
axios.defaults.baseURL = 'http://127.0.0.1:8081';//设置通用的头部url,可以拼接到每一个组件vue的axios发送的请求的头部
const app = createApp(App);
app.config.globalProperties.$http1 = axios;
app.mount('#app');
vue中如下:
<script>
export default {
data() {
return {
data:"",
buttonInfo:"获取数据按钮"
};
},
methods: {
fetchData() {
this.$http1.post(
`/event/findEventList/1/2`,//这里省略了头部
{},
{
headers: {
'Content-Type': 'application/json'
}
}
)
.then(response => {
this.data = response.data;
console.log(this.data);
})
.catch(error => {
console.error('请求失败:', error);
});
}
}
}
</script>
<template>
<button v-on:click = "fetchData" v-text="buttonInfo"></button>
</template>
无需操作。
vite.config.js:
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
server: {//Vite开发服务器的顶层配置项,用于定义开发环境下的服务器行为
proxy: {//代理配置,定义请求代理规则的入口
'/api': {//代理路径匹配规则:匹配所有以/api开头的请求路径,这里的“api”可以随便设置,但是要与下面的api,以及vue文件中请求地址头部哪个api字段要保持一致
target: 'http://127.0.0.1:8081/',//目标服务器地址,请求会被转发到该地址
changeOrigin: true,//开启跨域请求
rewrite: path => path.replace(/^\/api/, '')//路径重写函数,使用正则移除请求路径中的/api前缀,也就是这个服务器配置,会匹配/api开头的请求路径,转发到target上,然后再把/api这一部分删除掉
}
}
}
})
vue文件中:
<script>
import axios from 'axios';//引入axios
export default {
data() {
return {
data:"",
buttonInfo:"获取数据按钮"
};
},
methods: {
fetchData() {
axios.post(
`/api/event/findEventList/1/2`,//这里省略了头部,然后在原有“/event/findEventList/1/2”基础上加上“/api”,这样会被vite.config.js的跨域配置匹配上,然后添加指向target:http://127.0.0.1:8081/,最后删除掉/api,形成正确的访问链接
{},
{
headers: {
'Content-Type': 'application/json'
}
}
)
.then(response => {
this.data = response.data;
console.log(this.data);
})
.catch(error => {
console.error('请求失败:', error);
});
}
}
}
</script>
<template>
<button v-on:click = "fetchData" v-text="buttonInfo"></button>
</template>
同样的,main.js上可以做通用处理:
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios';//这里做了通用导入axios
const app = createApp(App);
app.config.globalProperties.$http2 = axios;//这里对app这个vue对象的配置中的全局属性中,我随意定义的http2属性设置为axios
app.mount('#app');
vue文件中:
<script>
// import axios from 'axios';//引入axios,但这里被通用导入替代,已经不需要了
export default {
data() {
return {
data:"",
buttonInfo:"获取数据按钮"
};
},
methods: {
fetchData() {
this.$http2.post(//这里是post请求,这里利用在main.js设置的全局属性http2
`/api/event/findEventList/1/2`,
{},
{
headers: {
'Content-Type': 'application/json'
}
}
)
.then(response => {
this.data = response.data;
console.log(this.data);
})
.catch(error => {
console.error('请求失败:', error);
});
}
}
}
</script>
<template>
<button v-on:click = "fetchData" v-text="buttonInfo"></button>
</template>
注意,这里不能如上面版本3一样,做进一步处理,设置axios.defaults.baseURL,这会导致vite.config.js的跨域处理被绕开从而失效。