记录: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等样式代码。
其中,
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传递的数据。
{{ this.msg }}
(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
页面:
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日