【Vue2+SpringBoot在线商城】01-Axios与后端Result
本项目是使用Vue2+SpringBoot+Mysql制作的在线商城项目。
一. Result后端实现
1.1 定义请求返回结果类型
定义一个公共的枚举类ResultType,定义相关的枚举常量,返回的状态码和状态的描述信息对应起来。
package com.xmut.backend.utils;
/**
* 请求返回结果类型
*/
public enum ResultType {
SUCCESS("200", "操作成功"),
FAIL("400", "操作失败"),
UNAUTHORIZED("401", "权限不足"),
NOT_FOUND("404", "接口不存在"),
INTERNAL_SERVER_ERROR("500", "服务器内部错误"),
AGAIN_LOGIN("600", "请重新登录");
private String code;
private String name;
ResultType(String code, String name) {
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
}
然后实现了枚举的构造方法ResultType(String code, String name),以及枚举的Getter方法,用于获取状态码和获取状态码对应的提示信息。
1.2 Result
1.2.1 定义泛型类
定义泛型类,T是返回的数据类型。然后实现序列化接口,用于网络传输和持久化。
public class Result<T> implements Serializable{
}
1.2.2 定义变量
定义三个变量,一个是statusCode状态码(默认成功),一个是message提示信息(默认也是成功的消息),还有一个data用于存放实际的返回结果。
private String statusCode = ResultType.SUCCESS.getCode();
private String message = ResultType.SUCCESS.getName();
private T data = null;
1.2.3 定义Getter和Setter方法
然后定义Getter和Setter方法,分别用于获取和设置状态码、获取和设置提示信息、获取和设置返回结果。
/**
* 获取状态编码
*/
public String getStatusCode() {
return statusCode;
}
/**
* 设置状态编码
*/
public void setStatusCode(String statusCode) {
this.statusCode = statusCode;
}
/**
* 获取提示信息
*/
public String getMessage() {
return message;
}
/**
* 设置提示信息
*/
public void setMessage(String message) {
this.message = message;
}
/**
* 获取返回结果
*/
public T getData() {
return data;
}
/**
* 设置返回结果
*/
public void setData(T data) {
this.data = data;
}
1.2.4 定义服务器错误方法
public void addError() {
this.addError(""); // 调用重载方法,使用空消息
}
public void addError(String message) {
this.message = message; // 设置自定义消息
this.statusCode = ResultType.INTERNAL_SERVER_ERROR.getCode(); // 设置500错误码
// 如果消息为空,使用INTERNAL_SERVER_ERROR(500)错误消息
if (this.message == null || "".equals(this.message)) {
this.message = ResultType.INTERNAL_SERVER_ERROR.getName();
}
}
1.2.5 定义成功方法
public void success() {
this.success(""); // 调用重载方法
}
public void success(String message) {
this.message = message; // 设置成功消息
this.statusCode = ResultType.SUCCESS.getCode(); // 设置成功状态码
// 如果消息为空,使用默认成功消息
if (this.message == null || "".equals(this.message)) {
this.message = ResultType.SUCCESS.getName();
}
}
1.2.6 定义业务失败方法
结构同上
public void fail() {
this.fail(""); // 调用重载方法
}
public void fail(String message) {
this.message = message;
this.statusCode = ResultType.FAIL.getCode(); // 设置业务失败状态码
if (this.message == null || "".equals(this.message)) {
this.message = ResultType.FAIL.getName(); // 使用默认失败消息
}
}
1.2.7 定义未授权的方法
public void unauthorized() {
this.unauthorized(""); // 调用重载方法
}
public void unauthorized(String message) {
this.message = message;
this.statusCode = ResultType.UNAUTHORIZED.getCode(); // 设置401未授权状态码
if (this.message == null || "".equals(this.message)) {
this.message = ResultType.UNAUTHORIZED.getName(); // 使用默认消息
}
}
1.2.8 定义notfound方法
public void notFound() {
this.notFound(""); // 调用重载方法
}
public void notFound(String message) {
this.message = message;
this.statusCode = ResultType.NOT_FOUND.getCode(); // 设置404状态码
if (this.message == null || "".equals(this.message)) {
this.message = ResultType.NOT_FOUND.getName(); // 使用默认消息
}
}
1.2.9 定义重新登录方法
public void againLogin() {
this.againLogin(""); // 调用重载方法
}
public void againLogin(String message) {
this.message = message;
this.statusCode = ResultType.AGAIN_LOGIN.getCode(); // 设置重新登录状态码
if (this.message == null || "".equals(this.message)) {
this.message = ResultType.AGAIN_LOGIN.getName(); // 使用默认消息
}
}
1.2.10 Result.java完整代码
import java.io.Serializable;
/**
* 请求返回结果对象
*/
public class Result<T> implements Serializable {
private String statusCode = ResultType.SUCCESS.getCode();
private String message = ResultType.SUCCESS.getName();
private T data = null;
/**
* 获取状态编码
*/
public String getStatusCode() {
return statusCode;
}
/**
* 设置状态编码
*/
public void setStatusCode(String statusCode) {
this.statusCode = statusCode;
}
/**
* 获取提示信息
*/
public String getMessage() {
return message;
}
/**
* 设置提示信息
*/
public void setMessage(String message) {
this.message = message;
}
/**
* 获取返回结果
*/
public T getData() {
return data;
}
/**
* 设置返回结果
*/
public void setData(T data) {
this.data = data;
}
public void addError() {
this.addError("");
}
public void addError(String message) {
this.message = message;
this.statusCode = ResultType.INTERNAL_SERVER_ERROR.getCode();
if (this.message == null || "".equals(this.message)) {
this.message = ResultType.INTERNAL_SERVER_ERROR.getName();
}
}
public void success() {
this.success("");
}
public void success(String message) {
this.message = message;
this.statusCode = ResultType.SUCCESS.getCode();
if (this.message == null || "".equals(this.message)) {
this.message = ResultType.SUCCESS.getName();
}
}
public void fail() {
this.fail("");
}
public void fail(String message) {
this.message = message;
this.statusCode = ResultType.FAIL.getCode();
if (this.message == null || "".equals(this.message)) {
this.message = ResultType.FAIL.getName();
}
}
public void unauthorized() {
this.unauthorized("");
}
public void unauthorized(String message) {
this.message = message;
this.statusCode = ResultType.UNAUTHORIZED.getCode();
if (this.message == null || "".equals(this.message)) {
this.message = ResultType.UNAUTHORIZED.getName();
}
}
public void notFound() {
this.notFound("");
}
public void notFound(String message) {
this.message = message;
this.statusCode = ResultType.NOT_FOUND.getCode();
if (this.message == null || "".equals(this.message)) {
this.message = ResultType.NOT_FOUND.getName();
}
}
public void againLogin() {
this.againLogin("");
}
public void againLogin(String message) {
this.message = message;
this.statusCode = ResultType.AGAIN_LOGIN.getCode();
if (this.message == null || "".equals(this.message)) {
this.message = ResultType.AGAIN_LOGIN.getName();
}
}
}
1.3 定义一个测试用的User实体
由于这边只是为了进行前后端的测试,所以只是简单定义了一个User实体,只有name,后续根据业务需要再进行修改、扩充。
package com.xmut.backend.entity;
/**
* User实体
*/
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
1.4 后端定义一个测试控制类HelloController
package com.xmut.backend.controller;
import com.xmut.backend.entity.User;
import com.xmut.backend.utils.Result;
// 导入Spring Web的注解,用于定义RESTful接口
import org.springframework.web.bind.annotation.*;
/**
* axios 联调测试接口
*/
@RestController // 声明这是一个RESTful控制器,会自动将返回对象转换为JSON
@RequestMapping("/kmall/hello") // 定义控制器的基础路径,所有接口都在/kmall/hello下
public class HelloController {
// GET请求接口,路径为:/kmall/hello/get
@GetMapping("/get")
public Result get(@RequestParam(required = false) String type) { // 方法参数:可选的查询参数type(required=false表示参数非必需)
Result result = new Result(); // 创建Result对象
// 先返回 401,用来测试前端 statusCode 分支
result.unauthorized("unauthorized");
// 也可以切换成 success:
// result.setData(type);
// result.success("success");
return result; // 返回Result对象,Spring会将其自动转为JSON
}
@PostMapping("/postTest")
public Result postTest(@RequestParam String id) {
Result result = new Result();
result.setData(id);
result.success();
return result;
}
@PostMapping("/postJson")
public Result postJson(@RequestBody User user) {
Result result = new Result();
result.setData(user == null ? null : user.getName());
result.success();
return result;
}
}
二、前端测试
2.1 axios的module层helloApi.js
import { get, post, postJson } from './index'
// get -> 查询参数
// post -> x-www-form-urlencoded
// postJson -> application/json
export function myGet(params) {
return get('/kmall/hello/get', params)
}
export function myPost(params) {
return post('/kmall/hello/postTest', params)
}
export function myPostJson(params) {
return postJson('/kmall/hello/postJson', params)
}
2.2 /api/index.js
2.2.1 导入库
qs:一个查询字符串解析和序列化库,用于将对象转换为 URL 查询字符串格式
import axios from 'axios'
import qs from 'qs'
2.2.2 全局配置
所有请求都会在前面加上/api前缀
axios.defaults.baseURL = '/api'
2.2.3 拦截器
结构:
axios.interceptors.response.use(
function (res) {
// 成功响应处理
},
function (err) {
// 错误响应处理
}
)
完整代码:
axios.interceptors.response.use(
function (res) { // res: 完整的HTTP响应对象
var data = res.data // data: 从响应中提取的data字段
var code = data && data.statusCode // code: 从data中提取statusCode字段(状态码)
// 如果状态码为200,表示业务成功
if (code === 200 || code === '200') {
return Promise.resolve(data) // 创建一个已解析的Promise,将data传递给下一个.then()处理
} else if (code === 600 || code === '600') { // 如果业务状态码为600,表示需要登录
return Promise.reject('直接跳转到登陆页面') // 创建一个被拒绝的Promise,传递错误信息
} else { // 其他业务状态码,表示业务错误
return Promise.reject((data && data.message) || 'error')
}
},
function (err) { // 处理HTTP层面的错误(如网络错误等)
return Promise.reject(err)
}
)
2.2.4 get方法
export function get(url, params) {
return axios({
method: 'get',
url: '' + url, // 确保url是字符串
params: params
})
}
2.2.5 post方法(表单格式)
transformRequest: 在发送前转换请求数据
allowDots: true: 允许使用点号表示嵌套对象(如 user.name=John),例如:{ user: { name: 'John' } } → user.name=John
export function post(url, params) {
return axios({
method: 'post',
url: '' + url,
data: params,
transformRequest: [
function (data) {
return qs.stringify(data, { allowDots: true }) // 将JavaScript对象转换为application/x-www-form-urlencoded格式
}
],
headers: {
'Content-Type': 'application/x-www-form-urlencoded' // 表单
}
})
}
2.2.6 postJson
不进行qs.stringify转换,直接发送js对象
Spring Boot 后端使用 @RequestBody 注解接收
举例:{ "user": { "name": "John" } } 直接作为 JSON 发送
export function postJson(url, params) {
return axios({
method: 'post',
url: '' + url,
data: params,
headers: {
'Content-Type': 'application/json'
}
})
}
2.3 在页面中添加相应的测试按钮,定义好测试数据
<div class="api-test">
<div class="api-row">
<el-button size="mini" @click="testGetRequest">get-request</el-button>
<el-button size="mini" @click="testPostRequest">post-request</el-button>
<el-button size="mini" @click="testPostJsonRequest">postJson-request</el-button>
<el-input v-model.trim="testId" size="mini" class="api-input" placeholder="id(给post用)" />
<el-input v-model.trim="testName" size="mini" class="api-input" placeholder="name(给postJson用)" />
</div>
<div v-if="lastResultText" class="api-result">
<pre>{{ lastResultText }}</pre>
</div>
</div>
testId: '123',
testName: 'abc',
lastResultText: ''
在vue中,写以下几个方法,用于处理API相应请求。
testGetRequest: function () {
var self = this // 保存当前Vue实例的引用,避免在回调中this指向改变
myGet({ type: 'ttyy' }) // 调用封装好的GET请求函数,传递参数type为'ttyy'
.then(function (result) { // 请求成功时的回调
self.handleApiResult(result) // 调用结果处理方法
})
.catch(function (error) { // 请求失败时的回调
self.lastResultText = 'error: ' + error // 在页面上显示错误信息
console.log('error:' + error) // 控制台打印错误
})
},
testPostRequest: function () {
var self = this
var id = (self.testId || '').trim() || '123'
// 获取页面输入框的testId值,如果不存在或为空,则使用默认值'123'
myPost({ id: id })
.then(function (result) {
self.handleApiResult(result)
})
.catch(function (error) {
self.lastResultText = 'error: ' + error
console.log('error:' + error)
})
},
testPostJsonRequest: function () {
var self = this
var name = (self.testName || '').trim() || 'abc'
myPostJson({ name: name })
.then(function (result) {
self.handleApiResult(result)
})
.catch(function (error) {
self.lastResultText = 'error: ' + error
console.log('error:' + error)
})
},
handleApiResult: function (result) {
// 将结果格式化成JSON字符串显示在页面上
try {
this.lastResultText = JSON.stringify(result, null, 2)
// 参数说明:JSON.stringify(value, replacer, space)
// null: 不转换任何属性
// 2: 缩进2个空格,美化输出
} catch (e) {
this.lastResultText = String(result) // 如果转换失败,直接转为字符串
}
// 2) 根据statusCode进行不同的业务处理
var code = result && result.statusCode
switch (code) {
case '200': {
this.$message.success('操作成功')
console.log(result)
break
}
case '400': {
this.$message.error('操作失败')
console.log('操作失败')
break
}
case '401': {
this.$message.warning('权限不足/未登录')
console.log('权限不足')
break
}
case '404': {
this.$message.error('接口不存在')
console.log('接口不存在')
break
}
default: {
this.$message.info('default')
console.log('default')
console.log(result)
break
}
}
2.4 测试结果
2.4.1 Get

2.4.2 Post

2.4.3 PostJson

测试成功,接下来就可以进一步地开始实现了。
更多推荐



所有评论(0)