Backend Development 9 min read

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.

Full-Stack Internet Architecture
Full-Stack Internet Architecture
Full-Stack Internet Architecture
Handling CORS in Spring Boot and Vue3: Concepts, Code, and Demo

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 service

2. 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
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.

Spring BootAxiosWeb DevelopmentCORSCross-OriginVue3
Full-Stack Internet Architecture
Written by

Full-Stack Internet Architecture

Introducing full-stack Internet architecture technologies centered on Java

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.