基于springboot vue element-ui axios 前后端分离(体验)

记录:269

场景

(1)浏览器访问前端服务Front,展现A页面。

(2)A页面发送异步请求到后端服务Back,请求返回后携带后台的数据跳转到B页面。

版本:Spring Boot 2.5.13;Vue 2.6.14;Element UI 2.15.8;Axios 0.27.2

备忘录1:一件事情,如果能用文字描述清楚,并写下来,这就是我要的效果。

备忘录2:壁垒。

参考地址:

Spring Boot:https://spring.io/projects/spring-boot

Vue.js:https://cn.vuejs.org/v2/guide/

element-ui:https://element.eleme.cn/

Axios:https://www.npmjs.com/package/axios

一、前端工程

1.创建前端工程

基于图形化界面创建Vue项目,命名:hub-example-autumn-web,参考如下方式。

地址:https://blog.csdn.net/zhangbeizhen18/article/details/123605192

安装完成后,本例在初始化工程上进行添加相应配置。

2.package.json运行依赖

运行依赖在hub-example-autumn-web/package.json中

"dependencies": {
  "axios": "^0.27.2",
  "core-js": "^3.8.3",
  "element-ui": "^2.15.8",
  "vue": "^2.6.14",
  "vue-router": "^3.5.1",
  "vuex": "^3.6.2"
 }

安装组件格式,例如安装axios。

npm install axios  -S

3.vue.config.js跨域代理配置

在/hub-example-autumn-web/vue.config.js配置跨域的代理配置。

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    port: 18080,
    proxy: {
      '/api': {
        target: 'http://localhost:18081',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
})

说明:

port: 18080是前端服务器端口。

/api的作用,前端页面中的/api路径,会被替换为target中的地址(即后端服务器地址)。其中,/api是自定义命名,只要能对应上即可。/api就是前端在调用后端URL地址时,匹配到了/api就把/api替换为http://localhost:18081,这样就组成了一个完整的后端请求地址。

4.工程入口main.js

在hub-example-autumn-web/src/main.js中配置。

(1)main.js是前端程序执行入口和起点。

(2)使用import引入需要使用的核心组件、样式等模块。

(3)使用Vue.prototype把组件挂载到Vue实例,以便全局使用。

(4)使用Vue.use把插件注入Vue实例。

(5)初始化Vue实例。把router、store等传入。把App.vue组件注入,并把App.vue的根节点#app挂载上。注:本例(默认)App.vue是页面起点。

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.config.productionTip = false
Vue.prototype.$axios = axios
Vue.use(ElementUI, { size: 'mini' })
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

5.页面入口App.vue

在hub-example-autumn-web/src/App.vue中是页面入口。

一个标配.vue文件包括

:在这里可以写原生html标签,可以写基于Vue 2.x或者 Vue 3.x的Element UI标签。这些标签作为页面的骨架。

:在这里写Vue代码和JS代码。

:在这里写CSS等样式代码。


其中, 是路由标签,在App.vue的中组装Vue的页面片段。换句话说,路由匹配到的.vue组件,都会通过这个标签,成为App.vue的一部分,然后渲染。

6.路由入口/src/router/index.js

在hub-example-autumn-web/src/router/index.js是路由入口。

(1)导入路由相关模块vue-router。

(2)使用Vue.use注入路由组件。

(3)配置路由规则

其中一个路由配置:

{
  path: '/register',
  name: 'Register',
  component: () => import('../views/Register.vue')
}

使用逻辑:比如请求http://192.168.0.107:18080/register发起后,在前端服务器收到请求后,会去匹配路由中已经定义的规则/register,匹配到后会加载component对应的组件。

(4)初始化路由

/router/index.js如下:

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
  {
    path: '/register',
    name: 'Register',
    component: () => import('../views/Register.vue')
  },
  {
    path: '/index',
    name: 'Index',
    component: () => import('../views/Index')
  }
]
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})
export default router

7.Vuex入口/src/store/index.js

本例使用初始化配置。

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
  state: {
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

8.封装axios

根据个人习惯对axios进行管理。

(1)创建axios实例、设置请求拦截器、设置应答拦截器

在/hub-example-autumn-web/src/api/axios-request.js中

import axios from 'axios'
const baseURL = '/api'
export function request (config) {
  // 创建axios的实例对象AxiosInstance
  const instance = axios.create({
    baseURL,
    timeout: 3600,
    withCredentials: true,
    headers: {
      'Content-Type': 'application/json; charset=utf-8'
    }
  })
  // 设置axios请求拦截器
  instance.interceptors.request.use(config => {
    return config
  }, err => {
    console.log(err)
  })
  // 设置axios应答拦截器
  instance.interceptors.response.use(res => {
    if (res.status === 200) {
      return res
    } else {
      console.log('axios的response的200还没返回.' + res)
    }
  }, error => {
    console.log(error)
    return Promise.reject(error)
  })
  return instance(config)
}

其中,const baseURL = '/api'和vue.config.js中的/api是对应上的。

withCredentials: true,表示跨域请求是否提供凭据信息。在前端设置后,后端也要设置。

withCredentials是XMLHttpRequest的一个属性,axios封装了XMLHttpRequest。

(2)封装API

把所有调用http的API统一集中写在约定文件中,并以方法的方式暴露。

在/hub-example-autumn-web/src/api/comom-api.js

import { request } from '@/api/axios-request'
const baseApi = '/autumn'
export function register (inputPara) {
  return request({
    url: `${baseApi}/autu/register`,
    method: 'post',
    data: inputPara,
    headers: {
      'Content-Type': 'application/json; charset=utf-8'
    }
  })
}

register函数调用的后端发布的供客户端调用的http方法:

完整URL:http://127.0.0.1:18081/autumn/autu/register

方法:POST

(3)封装API注意

针对get请求和post请求,AxiosRequestConfig内部接收参数不一样。

封装post请求: {method: 'post',data: inputPara}。

封装get请求: {method: get,params: inputPara}。

9.页面

开发页面时,使用基于 Vue 2.x 的Element UI,需要哪种组件,从Element UI官网找到相应组件,把相应的代码拷贝到.vue文件中,再根据实际需求进行改造。

(1)Register.vue

在hub-example-autumn-web/src/views/Register.vue

本例就是从官网找到等需要的标签进行改造。



(2)Index.vue

在hub-example-autumn-web/src/views/Index.vue展示一条从Register.vue传递的数据。



(3)使用this.$router.push传递数据

在Register.vue中发送

this.$router.push({
  name: 'Index',
  params: { dataInfo: res.data.data }
})

(4)使用this.$route接收数据

在Index.vue中接收

const temp = this.$route.params.dataInfo

注意:发送使用this.$router.push,接收使用this.$route.params。

二、后端工程

1. 创建后端工程

使用IntelliJ IDEA 2021.2.3创建基于Maven工程。

2. pom.xml依赖包

本例使用核心依赖。


    8
    8
    1.8
    2.5.13 
    2.5.13 
  
  
    
      org.springframework.boot
      spring-boot
      ${spring.boot.version}
    
    
      org.springframework.boot
      spring-boot-starter-web
      ${spring.boot.version}
    
    
      org.projectlombok
      lombok
      true
      1.18.22
    
    
      cn.hutool
      hutool-all
      5.7.22
    
    
      org.apache.commons
      commons-lang3
      3.12.0
    

3. application.yml

本例使用核心依赖

server:
  port: 18081
  servlet:
    context-path: /autumn

4. 服务入口类

入口类

@SpringBootApplication
public class AutumnApplication {
    public static void main(String[] args) {
        SpringApplication.run(AutumnApplication.class);
    }
}

5.Controller入口

入口类

@Slf4j
@RestController
@RequestMapping("/autu")
public class AutumnController {
  @PostMapping("/register")
  @ResponseBody
  public ResultObj register(@RequestBody RegisterVO registerVO) {
  log.info("AutumnController->register接收参数,registerVO = " + registerVO);
   if (registerVO == null) {
      ResultObj.fail("系统异常.");
   }
   String info = "您好," + registerVO.getUserName() + ",欢迎来到前后端分离技术世界.";
   Map map = new HashMap<>();
   map.put("welcome", info);
   map.put("uuid", IdUtil.simpleUUID());
   log.info("AutumnController->register返回值,ResultObj = " 
     + ResultObj.success(200, "成功", map));
   return ResultObj.success(200, "成功", map);
  }
}

6.跨域配置入口

跨域配置入口

@Configuration
public class CorsConfig implements WebMvcConfigurer {
  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
     .allowedOriginPatterns("*")
     .allowCredentials(true)
     .allowedMethods("GET", "POST", "DELETE", "PUT")
     .maxAge(3600);
  }
}

7.实体类

(1).RegisterVO接收前端传过来的参数对象

@Data
public class RegisterVO {
  private String userName;
  private String password;
  private String city;
}

(2).ResultObj返回给前端的数据对象

@Data
public class ResultObj implements Serializable {
 private static final long serialVersionUID = -820698071194414678L;
 private int code;
 private String msg;
 private Object data;
 public static ResultObj success(int code, String msg, Object data) {
   ResultObj obj = new ResultObj();
   obj.setCode(code);
   obj.setMsg(msg);
   obj.setData(data);
   return obj;
 }
 public static ResultObj fail(String msg) {
   ResultObj obj = new ResultObj();
   obj.setCode(300);
   obj.setMsg(msg);
   obj.setData("");
   return obj;
 }
}

三、前端和后端联调

1.启动前端服务

前端服务: http://localhost:18080/

2.启动后端服务

后端服务: http://localhost:18081/

3.前端发起请求

请求:http://localhost:18080/register

页面:

基于springboot vue element-ui axios 前后端分离(体验)_第1张图片

4.页面使用axios异步请求到后端服务地址

后端地址:http://localhost:18081/autumn/autu/register

点击注册Button将注册信息提交到后端的/autumn/autu/register,并获取返回值。

5.后端接收请求并返回数据

后端接收请求并返回数据

日志截图:

 6.跳转到Index.vue

前端地址:http://localhost:18080/index

页面:

 四、前端和后端报错解决

1.跨域报错解决

报错信息:

Access to XMLHttpRequest at 'http://localhost:18081/autumn/autu/register' from origin 
'http://192.168.0.107:18080' has been blocked by CORS policy: Response to preflight request 
doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present 
on the requested resource.

解决:

(1)在前端vue.config.js跨域代理配置。本例在(一、前端工程的第3节)

(2)在后端实现 WebMvcConfigurer配置跨域。本例在(二、后端工程的第6节)

2.页面之间数据传递报错

发送页面:

this.$router.push({
   name: 'Index',
   params: { dataInfo: res.data.data }
})

接收页面:

this.$route.params.dataInfo

注意:发送使用this.$router,接收使用this.$route。

五、交互逻辑

1.在浏览器输入地址http://localhost:18080/register,

2.前端服务器接收到请求后,获取到路径/register,就拿着这个路径到定义好的路由规则中匹配,匹配到如下规则,然后就加载出对应组件的页面。

{
  path: '/register',
  name: 'Register',
  component: () => import('../views/Register.vue')
}

3.在页面上操作注册Button,会使用axios异步提交表单数据到后端服务器。

地址:http://localhost:18081/autumn/autu/register

4.后台服务器接收到请求后执行处理逻辑并把数据返回给前端。

5.前端的axios接收到请求返回数据后,携带数据,使用this.$router.push跳转到index.vue

6.在浏览器展现页面和数据。

以上,感谢。

2022年5月14日

你可能感兴趣的:(L02-前端,vue.js,spring,boot,ui)