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

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

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

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.