Handling CORS in Spring Boot and Vue3: Concepts, Code, and Demo
This article explains the concept of Cross‑Origin Resource Sharing (CORS), demonstrates how to identify cross‑origin requests, and provides a complete Spring Boot backend configuration together with Vue3/Axios frontend code to solve CORS issues in a full‑stack web application.
Cross‑Origin Resource Sharing (CORS) is a browser security mechanism that blocks requests when the protocol, domain, or port differ between the client and server; such requests are considered cross‑origin.
The article first defines CORS, illustrates how to determine whether a URL is cross‑origin with examples, and shows a table summarizing several URLs and the reasons they are or are not cross‑origin.
URL Is Cross‑Origin Reason http://www.mysite.com Yes Domain differs https://www.fullstack.com Yes Protocol differs http://www.fullstack.com:81 Yes Port differs http://www.fullstack.com/index.html No Protocol, domain, and port are the same
Next, the tutorial walks through a three‑part implementation:
1. Frontend setup – Create a Vue3 project, install axios, and add a request utility ( src/utils/request.js) with custom configuration, request/response interceptors, and cookie handling:
import axios from 'axios'
// Create axios instance with custom config
const service = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8081',
timeout: 10000,
withCredentials: true, // send cookies for cross‑origin
headers: { 'Content-Type': 'application/json;charset=UTF-8' }
})
// Request interceptor
service.interceptors.request.use(config => {
// add token or other headers here
return config
}, error => Promise.reject(error))
// Response interceptor
service.interceptors.response.use(response => {
return response.data
}, error => {
console.error('API Error:', error.response?.status, error.message)
return Promise.reject({ status: error.response?.status, message: error.message || '请求失败' })
})
export default service2. Vue components – The root component ( src/App.vue) imports the request utility and a demo component; the demo component ( src/components/ApiDemo.vue) fetches data from /api/data, shows loading, error, and the returned JSON, and includes an automatic retry after 3 seconds.
<script setup>
import { ref, onMounted } from 'vue'
import api from '@/utils/request'
const responseData = ref(null)
const loading = ref(false)
const error = ref(null)
const fetchData = async () => {
loading.value = true
error.value = null
try {
const data = await api.get('/api/data')
responseData.value = data
} catch (err) {
error.value = `错误代码 ${err.status || 500}: ${err.message}`
console.error('API请求失败:', err)
} finally {
loading.value = false
}
}
onMounted(async () => {
await fetchData()
if (error.value) {
setTimeout(fetchData, 3000) // retry after 3 seconds
}
})
</script>
<template>
<div class="demo-container">
<h2>API 数据演示</h2>
<div v-if="loading" class="loading-state">
<div class="spinner"></div> 数据加载中...
</div>
<div v-else-if="error" class="error-state">❌ {{ error }}
<button @click="fetchData" class="retry-btn">重试</button>
</div>
<div v-else class="data-box">
<pre>{{ JSON.stringify(responseData, null, 2) }}</pre>
</div>
</div>
</template>3. Backend configuration – In application.yml set the server port to 8081, then create a Spring Boot controller that returns a simple string, and configure a global CORS filter ( CorsConfig) to allow the Vue dev server ( http://localhost:5173) with all methods, any headers, credentials, and a max age of 3600 seconds:
package com.fullstack.commerce.user.controller;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class DataController {
@GetMapping("/data")
public ResponseEntity<String> getData() {
return ResponseEntity.ok("跨域请求成功!数据来自Spring Boot");
}
}
package com.fullstack.commerce.user.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:5173") // front‑end address
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}After restarting the Spring Boot application and running npm run dev for the Vue project, accessing http://localhost:5173/ initially shows a CORS error; once the backend CORS configuration is applied, the request succeeds and the data is displayed.
The article concludes that CORS is a common interview and development topic, and that Spring Boot together with proper frontend setup provides a straightforward solution, encouraging readers to try the example and reach out for any questions.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
