一文解决前后端分离导致的跨域问题Vue+Springboot

问题:axios访问后端数据导致的跨域以及每次访问session不一样

前端部分

我的vue项目创建命令:

vue init webpack project_name

vue项目创建建议和我的一致,这样才能保证项目目录文件一致。


index.js文件如图:

一文解决前后端分离导致的跨域问题Vue+Springboot_第1张图片

添加如下:

    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      'api': {
        target: 'http://localhost:8088', // 这里是后端的地址
        changeOrigin: true, // 允许跨域
        pathRewrite: {
          '^/api': '' // 后端每次访问添加的前缀,比如你请求/login => /api/login
        }			 // 没有前缀需求删掉api即可
      }
    },

配置好后如图:
一文解决前后端分离导致的跨域问题Vue+Springboot_第2张图片

main.js下添加:

import qs from 'qs'
import store from './store'

axios.defaults.baseURL = 'http://localhost:8088/api' // 注意这里同上面的target
// 使请求带上凭证信息,这里是解决session不一致的问题
axios.defaults.withCredentials = true
Vue.prototype.$axios = axios

至此前端决定了跨域和session不一致的问题。


后端部分

创建一个config包,创建MyConfigMvcConfig.java

添加代码如下:

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 MyWebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //所有请求都允许跨域
        registry.addMapping("/**")
                .allowCredentials(true)
            	/**
            	这里是前端的域名+端口,
            	允许所有访问的话改成*
            	*/
                .allowedOrigins("http://localhost:8080")
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") //允许所有方法
                .allowedHeaders("*")
                .maxAge(3600);
    }
}

至此后端的跨域问题就解决了。

我们都知道有个注解@CrossOrigin注解可以解决跨域的问题,但这个注解目前只在Get方法上起作用,post上就没用了,所以还是用上面的方法解决跨域的问题。

特殊问题

vue常常搭配element-uiaxios使用,axios在请求时默认将数据放入请求体里面,这样后端接受数据时只能通过注解@RequestBody,比较麻烦,不能直接在像在传表单数据那样在方法形参的形式获取,这个问题主要针对的是POST请求。

在main.js添加如下代码解决以上的问题:

import qs from 'qs'

axios.interceptors.request.use((config) => {
  if (config.method === 'post' && !config.url.includes('upload')) {
    config.data = qs.stringify(config.data)
    config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
  }
  return config
}, (error) => {
  return Promise.reject(error)
})

上面的代码的功能axios拦截器修改请求头,代码比较简单,但是可以看到上面同时判断了url是不是包含upload请求,这是因为我用element-ui自带组件upload组件时出现了bug,后端形参反而接受不到数据,所以这里判断了下如果包含upload就使用默认的传参方式。

对应的upload代码如下:

<template>
    <el-upload
    :with-credentials="true"
    :http-request="upload"
    action=""
    multiple
    :limit="1"
    :on-exceed="handleExceed"
    :before-remove="beforeRemove"
    ref="upload"
    :file-list="fileList">
    <el-button type="primary">点击上传el-button>
    el-upload>
template>

<script>
export default {
  props: ['parentId'],
  data () {
    return {
      fileList: []
    }
  },
  methods: {
    handleExceed (files, fileList) {
      this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
    },
    beforeRemove (file, fileList) {
      return this.$confirm(`确定移除 ${file.name}`)
    },
    upload (param) {
      const formData = new FormData()
      formData.append('file', param.file)
      formData.append('id', this.parentId) // 这里可以添加校验数据
      const url = '/admin/upload'
      this.$axios.post(url, formData
      ).then(resp => {
        this.$refs.upload.clearFiles()
        this.$emit('onUpload')
      }).catch(resp => {
        console.log('上传失败')
      })
    }

  }
}
script>

你可能感兴趣的:(vue,springboot)