本项目是使用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

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

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐