SpringBoot + axios + vue + vuex

前言

在Vue中使用axios,需要注意的是:

  • axios相比较vuexvue-router几个功能而言,它不能也不需要使用Vue.use(axios)
  • 请求端口或者域名不同时,需要在后端解决跨域请求的问题

使用

原型链方式

main.js:

import axios from 'axios'

Vue.prototype.$axios = axios

前提是axios已经下载了:npm install axios --save-dev,上面两个代码写好之后,就能通过this.$axios.get(...)在各个组件中使用了。

Vuex方式

vuex/index.js:

import axios from 'axios'

axios.defaults.baseURL = 'http://localhost:8088';

new Vuex.Store({
    //...
    actions: {
        getU ({commit}) {
            // 请求
            axios.get("/getUserName?id=10001")
                .then() // 成功
                .catch() // 失败
        }
    }
});

注意:在baseURL的地址中一定要加http:前缀,一定一定。

如果涉及到跨域的话,就需要在SpringBoot中创建一个过滤类,作用是过滤设置Access-Control-Allow-Origin

package imain.net.filter;

import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by imain on 2018/2/16.
 */
@Configuration
public class CorsFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletResponse response = (HttpServletResponse) res;

        HttpServletRequest reqs = (HttpServletRequest) req;

        // Origin ->> http://localhost:8080,允许此URL进行资源访问
        // https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Access-Control-Allow-Origin?utm_source=mozilla&utm_medium=devtools-netmonitor&utm_campaign=default
        response.setHeader("Access-Control-Allow-Origin",reqs.getHeader("Origin")); // 这是必须的,下面都是可选项
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        // application/x-www-form-urlencoded, multipart/form-data 或 text/plain
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
        chain.doFilter(req, res);
    }
    public void init(FilterConfig filterConfig) {}
    public void destroy() {}
}

配置好这些之后就能够进行前后端交互了,如果需要看完整案例,就继续往下看,否则到此为止即可。(post方式在最底部)

项目案例

前端

// /vuex/index.js
import Vuex from "vuex";
import Vue from "vue";
import axios from 'axios'

Vue.use(Vuex);

axios.defaults.baseURL = 'http://localhost:8088';
axios.defaults.timeout = 5000

export default new Vuex.Store({
  state: {
    username: '未登录'
  },
  mutations: {
    // 接收两个参数,一个是数据中心,一个是修改的值
    updateUserName (state, userParams) {
      console.log('【userParams.name】:', userParams.username)
      console.log('【userParams】:', userParams)
      state.username = userParams.username;
    }
  },
  actions: {
    user ({commit}) {
      // 1.调用API得到用户信息
      console.log('请求开始...')
      axios.get('/getUser?id=1')
      // 成功时,保存用户名字
        .then((response) => {
          console.log('【message】值为:', response.data.name)
          commit('updateUserName', {
            username: response.data.name // 曾小晨
          });
        })
        .catch((error) => console.log('请求错误:', error));
      console.log('请求结束...')
    }
  }
});
<!-- MyVue.vue -->
<template>
  <div>
    <p>您的登录名是:{{username}}</p>
    <button @click="user">获取登录名</button>
  </div>
</template>

<script>

  import { mapState, mapActions } from 'vuex';

  export default {
    methods: {
      ...mapActions(['user'])
    },
    computed: {
      ...mapState(['username']),
    }
  }
</script>

<style>

</style>
<!-- App.vue -->
<template>
  <div id="app">
    <img src="./assets/logo.png">

    <myvuex/>

  </div>
</template>

<script>
  import myvuex from './components/MyVuex.vue';

  export default {
    name: 'App',
    components: {
      myvuex
    },
  }
</script>

<style>
  #app {
    font-family: 'Avenir', Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
    margin-top: 60px;
  }
</style>

后端

// contro
package imain.net.controller;

import imain.net.dao.BootVueDao;
import imain.net.pojo.BootVue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * vue 后端接口
 *
 * Created by Administrator on 2018/2/16.
 */
@RestController
public class BootVueController {

    @Autowired
    private BootVueDao bootVueDao;

    @GetMapping("/")
    public String hi() {
        return "hello boot";
    }

    @GetMapping(name = "/getUser")
    public BootVue get(@RequestParam("id") Integer id) {
        return bootVueDao.findOne(id);
    }

    @GetMapping("/setUser")
    public String set(BootVue bootVue) {
        try {
            bootVueDao.save(bootVue);
        } catch (Exception e) {
            System.out.println("添加失败,请检查");
            e.printStackTrace();
            return "error";
        }
        return "success";
    }
}
// Filter
package imain.net.filter;

import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by Administrator on 2018/2/16.
 */
@Configuration
public class CorsFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        System.out.println("设置跨域请求...");

        HttpServletResponse response = (HttpServletResponse) res;

        HttpServletRequest reqs = (HttpServletRequest) req;

        System.out.println(reqs.getHeader("Origin"));

        // Origin ->> http://localhost:8080,允许此URL进行访问资源
        // https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Access-Control-Allow-Origin?utm_source=mozilla&utm_medium=devtools-netmonitor&utm_campaign=default
        response.setHeader("Access-Control-Allow-Origin",reqs.getHeader("Origin")); // 这是必须的,下面都是可选项
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
//         application/x-www-form-urlencoded, multipart/form-data 或 text/plain
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
        chain.doFilter(req, res);
    }
    public void init(FilterConfig filterConfig) {}
    public void destroy() {}
}

后端只列出了两个关键的类,其他都是一个基本的hello world环境。

axios post

上面用的是get方式,看看post吧,唯一不同的是post需要使用qs模块进行格式化参数,其他是相同的:

import qs from 'qs' // 需要安装qs

axios.post('/getUser', qs.stringify({id: 1}))  // 需要使用qs格式化参数
// 成功时,保存用户名字
  .then((response) => {
    console.log('【message】值为:', response.data)
    commit('updateUserName', {
      username: response.data
    });
  })
  .catch((error) => console.log('请求错误:', error));
  
  
// ↓↓↓↓↓↓ 同样可以写成 ↓↓↓↓↓↓

var params = new URLSearchParams();
params.append('id', 1);

axios.post('/getUser', params)  // 需要使用qs格式化参数
// 成功时,保存用户名字
  .then((response) => {
    console.log('【message】值为:', response.data)
    commit('updateUserName', {
      username: response.data
    });
  })
  .catch((error) => console.log('请求错误:', error));

qs VS JSON:

var a = {name:'hehe',age:10};

qs.stringify(a) ->> name=hehe&age=10

JSON.stringify(a) ->> "{'a': 'hehe', 'age': 10}"

axios默认请求头是application/x-www-form-urlencoded,而这个 application/x-www-form-urlencoded 格式发送数据,数据必须是 URLSearchParams 类型,或者字符串参数 a=1&b=2 格式。详细请点我

end...

如果你也学vue、Java,可以加我QQ一起交流(704729872)

Last modification:May 11th, 2018 at 09:30 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment