Vue SpringBoot前后端分离整合

前言

此篇是作者通过一些学习的vue与springboot知识自己尝试并且成功实现vue与springboot交互的例子,大家可以参考一下,其中包含一些新人可能会犯的一些低级错误。配置文件的修改与简单的例子都已经列出,仅供参考!如有更好的方法可以留言。

1、解决Vue跨域问题

使用vue-cli脚手架创建vue项目

打开config/index.js文件

dev: {
    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api': { // 匹配所有以 '/api'开头的请求路径
        target: 'http://localhost:8080', // 代理目标的基础路径
        changeOrigin: true, // 支持跨域
        pathRewrite: {
          //重写路径,当我们在浏览器中看到请求的地址为:http://localhost:8000/api/login 时
          //实际上访问的地址是:http://localhost:8080/login,因为重写了 /api
          '^/api': ''// 重写路径: 去掉路径中开头的'/api'
        }
      }
        //=======如果你想要跨域多个端口的话自己设置
        
    },

        
        
//===========================================以下基本不用怎么修改===========================================
    // Various Dev Server settings
    host: 'localhost', // can be overwritten by process.env.HOST
    port: 8000, // 当前打开项目端口号,可以自行修改端口号
    autoOpenBrowser: false,//项目启动时是否自动打开页面,可以设置为true
    errorOverlay: true,
    notifyOnErrors: true,
    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
    useEslint: true,
    // If true, eslint errors and warnings will also be shown in the error overlay
    // in the browser.
    showEslintErrorsInOverlay: false,

    /**
     * Source Maps
     */

    // https://webpack.js.org/configuration/devtool/#development
    devtool: 'cheap-module-eval-source-map',

    // If you have problems debugging vue-files in devtools,
    // set this to false - it *may* help
    // https://vue-loader.vuejs.org/en/options.html#cachebusting
    cacheBusting: true,

    cssSourceMap: true
  },

将当前配置修改为以上配置。

axios通用模块,直接使用即可

/*
ajax请求函数模块 ajax.js
返回值: promise对象(异步返回的数据是: response.data)
 */
import axios from 'axios'
export default function ajax (url, data={}, type='GET') {

  return new Promise(function (resolve, reject) {
    // 执行异步ajax请求
    let promise
    if (type === 'GET') {
      // 准备url query参数数据
      let dataStr = '' //数据拼接字符串
      Object.keys(data).forEach(key => {
        dataStr += key + '=' + data[key] + '&'
      })
      if (dataStr !== '') {
        dataStr = dataStr.substring(0, dataStr.lastIndexOf('&'))
        url = url + '?' + dataStr
      }
      // 发送get请求
      promise = axios.get(url)
    } else {
      // 发送post请求
      promise = axios.post(url, data)
    }
    promise.then(function (response) {
      // 成功了调用resolve()
      resolve(response.data)
    }).catch(function (error) {
      //失败了调用reject()
      reject(error)
    })
  })
}

接口请求模块

/*
包含n个接口请求函数的模块 api.js
函数的返回值: promise对象
 */
import ajax from './ajax'

const BASE_URL = '/api'
//1.在proxy中设置要访问的地址,并重写/api为空的字符串,因为我们真正请求的地址是没有带/api,这个重写很重要!!!
//2.在创建axios实例的时候将baseURL设置为/api ,这时候我们的跨域就已经完成了。
//3. 假如请求的真正地址为:http://localhost:8080/login_pwd,但我们在浏览器上会看到是这样的 :http://localhost:8000/api/login_pwd ,多了个/api,但并不影响我们请求数据

export const reqPwdLogin = ({username, password}) =>
  ajax(BASE_URL+'/login_pwd', {username, password}, 'POST')

例如:

<template>
    <div>
      <input type="text"  v-model="username">
      <input type="password" v-model="password">
      <button id="submit" @click="login()">登录</button>
    </div>
</template>

<script>
import {reqPwdLogin} from '../api'
export default {
  data(){
    return{
      username:'',
      password:''
    }
  },
  methods: {
    async login(){
      let result
      const {username, password} = this
      if(!this.username) {
        // 用户名必须指定
        this.showAlert('用户名必须指定')
        return
      } else if(!this.password) {
        // 密码必须指定
        this.showAlert('密码必须指定')
        return
      }
      // 发送ajax请求传递username和password参数并且获取后端返回值
      result = await reqPwdLogin({username, password})
      alert(result);
    }
  }
}
</script>

我们通过axios向后端进行请求后,后端会接收到相应的值,但是有一些小坑需要注意!!!

2、解决java后端取值问题

当vue向后台传递的是一个对象时,例如登录时通过post传递一个对象,我们需要使用一个对象进行接收。

例如:传递的对象为data{username,password}时,我们需要创建一个对象用来保存这个对象值。

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class User implements Serializable {
    private String username;
    private String password;
}

后端使用**@RequestBody注解;将要取得的参数列表封装为一个实体类,使用@RequestBody**注解就可以与前端数据进行绑定

@ResponseBody
@RequestMapping("/login_pwd")
public String login(@RequestBody User user, HttpServletResponse response){
    String username = user.getUsername();
    String password = user.getPassword();
    User user = userService.queryUserByUsername(username);
    System.out.println(user);
    String ps;
    if (user.getPassword().equals(password)){
        System.out.println("登录成功");
        ps = JSON.toJSON("登录成功").toString();
        return ps;
    }else {
        System.out.println("登录失败");
        ps= JSON.toJSON("登录失败").toString();

    }
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
    return ps;
}

如果后端是通过get获取的值,我们可以使用**@RequestParam**注解, @RequestParam注解主要是用来绑定一个基本数据类型或 String 数据类型的参数

@ResponseBody
@RequestMapping("/login")
public String login(@RequestParam("username") string username, @RequestParam("password") string password,HttpServletResponse response){
    User user = userService.queryUserByUsername(username);
    System.out.println(user);
    String ps;
    if (user.getPassword().equals(password)){
        System.out.println("登录成功");
        ps = JSON.toJSON("登录成功").toString();
        return ps;
    }else {
        System.out.println("登录失败");
        ps= JSON.toJSON("登录失败").toString();

    }
    
    //"*",表示当前方法所有域都可以使用,用来解决跨域问题
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
    return ps;

}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐