【Mock平台】为系列测试开发教程,从0到1编码带你一步步使用Spring Boot 和 Antd React
框架完成搭建一个测试工具平台,希望作为一个实战项目能为你的测试开发学习有帮助。

一、后端SpringBoot

参考之前《Mock平台2-Java Spring Boot框架基础知识》分享来创建后端的服务,实际上QMock服务会涉及到两个服务,一个是供前端页面用的API服务,另一个是mock请求响应服务即可叫其网关,为了统一管理代码又不都耦合到一块,本项目通过IDE先创建一个普通的JAVA项目叫 QMockService,然后再其项目中创建两个**Module Springboot **项目,服务名分别为:

  • qmock-service-api
  • qmock-servcie-gateway

由于第二个代理网关服务暂时用不到,所以你也可以只单独创建一个service-api项目用于实践学习。

API服务架构

通常一个项目都会有约定俗成的模式来规范开发,由于对于JAVA的模式太多,我这里只提供基于MVC模式扩展的我常用结构供参考, 详见qmock-service-api左侧在 main.java包下子目录。

java
|- cn.daqi.mock.api # 代码包
|- commmons # 通用或工具类
|- controller # 接口请求入口
|- entity # 数据表实体类
|- request # 接口请求实体
|- mapper # 数据操作接口类
|- service # 服务接口类
|- impl # 服务接口实现类
resources
|- mapper # Mybatis XML方式数据操作文件
|- application.yml # 项目配置采用yml方式

由于笔者的职业不是后端开发,对于代码架构和模式等,没有过度的实战经验,如果想对各种模式有更多的了解推荐阅读之前转载过美团技术的一篇文章,如果想更深入的了解建议买本架构、代码之道之类的书进行系统学习。

依赖添加

Spring项目之前讲过有很多插件帮助其快速的开发,QMock项目本篇实现还依赖依赖以下几个项目,请在**pom.xml** 进行添加并刷新安装依赖,具体的使用和对比后在后边具体功能实现中逐渐讲解。

<!-- mysql链接驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency> <!-- MyBatis 一款优秀的数据库持久层操作框架 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency> <!-- 帮助简化Bean getter/setter等实现的插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency> <!-- JSON操作类库 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.79</version>
</dependency>

统一返回

Api服务一般都会有公司或项目内部约定好的模版统一返回方便联调开发,QMock项目就直接参考Antd pro一个官方建议来实现,省得做一些额外的自定义配置转换。

所以在commons下创建了统一返回类和一个枚举类,实现上述统一返回。

1.enum RespCode

public enum RespCode {

    /**
* 默认成功和系统状态
* 提示类型: 0 静默silent; 1 警告message.warn; 2 错误message.error; 4 消息notification; 9 跳转page
* */
SUCCESS(true, 2000, "成功", 0),
SYSTEM_ERROR(false, 5000, "系统繁忙,请稍后重试", 2), /* 参数错误 1001~1999 */
PARAMS_WARNING(false, 1001, "参数缺失或为空", 2), /* 用户错误 2001~2999 */
USER_AUTHORITY_FAILURE(false, 2001, "用户名或密码错误", 2); /* 其他错误 3001~3999 */ private Boolean success;
private Integer errorCode;
private String errorMessage;
private Integer showType; RespCode (Boolean success, Integer errorCode, String errorMessage, Integer showType) {
this.success = success;
this.errorCode = errorCode;
this.errorMessage = errorMessage;
this.showType = showType;
} public Boolean success() {
return this.success;
} public Integer errorCode() {
return this.errorCode;
} public String errorMessage() {
return this.errorMessage;
} public Integer showType() {
return this.showType;
}
}

2.class RespResult

@Data
public class RespResult implements Serializable { private static final long serialVersionUID = 1L; // 请求是否成功 true / false
private Boolean success; // 实际返回的数据
private Object data; // 错误编码
private Integer errorCode; // 错误信息
private String errorMessage; // 提示类型: 0 silent; 1 message.warn; 2 message.error; 4 notification; 9 page
private Integer showType = 0; // 枚举通用赋值方法
public void setResultCode(RespCode respCode){
this.success = respCode.success();
this.errorCode = respCode.errorCode();
this.errorMessage = respCode.errorMessage();
this.showType = respCode.showType();
} // 默认响应成功
public static RespResult success() {
RespResult respResult = new RespResult();
respResult.setResultCode(RespCode.SUCCESS);
return respResult;
} // 带返回data响应成功
public static RespResult success(Object data) {
RespResult respResult = new RespResult();
respResult.setResultCode(RespCode.SUCCESS);
respResult.setData(data);
return respResult;
} // 根据RespCode枚举失败返回
public static RespResult failure(RespCode respCode){
RespResult respResult = new RespResult();
respResult.setResultCode(respCode);
return respResult;
}
}

这小结最后简单画个流转图了解下后端SpringBoot实现API服务过程,具体例子将在最后登录功能中实践。

二、前端Antd pro

使用 uim 创建 ant-desgin-pro 脚手架,具体的模版已经在《Mock平台3-初识Antd React 开箱即用中台前端框架》讲过不再赘述。

项目创建

这里直接给出我的QMockWeb项目创建过程,其中如果你TypeScript比较熟悉,从体验的各方面还是比较推荐的,由于笔者不熟也为了降低门槛本Mock项目继续采用JavaScript,另外源代码项目已上传到了GitHub上,也可直接Fork使用。

Tips:不要忘记执行命令 npm run start 电脑上运行看下项目是否正常运行。

精简优化

虽然用的是simple模版,但有些内容对于项目可能是用不到的,以及一些基础信息需变更,才能打造一个属于自己的项目,对于Mock平台包含但不限于如下变更。

国际化多语言

默认的脚手架中有八种多语言,Mock项目只需要保留简体中文zh-CN英文en-US作为后续的多语言使用演示使用,多余的去除方法很简单直接删除位于** src/locales/* 下对应的文件夹和js即可。另外一点是可以在config/config.js** 中配置默认语言,如果想删除 pro 自带的全球化,可以通过 npm run i18n-remove 命令彻底移除。

页头尾和加载

项目中还涉及到默认ICON、标题以及一些声明需要改造,这些可以通过 Find in Files 进行关键词进行更改,这里我直接罗列给出,自行按需进行修改。

标题和Logo

在脚手架项目中实际中通过 config\defaultSettings.ts 来控制标题和 Logo,本项暂时没logo所以直接赋值为False不显示。

const Settings = {
...
colorWeak: false,
- // title: 'Ant Design Pro',
+ title: 'QMock',
pwa: false,
// logo: 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
- logo: false,
+ iconfontUrl: '',
};
export default Settings;

加载页

项目中还有一个在 js 还没加载成功,但是 html 已经加载成功的 landing 页面。这个页面的配置存在于 src\pages\document.ejs 文件。其中涉及到的项目图表引用位于**/public/***目录下,其他文案、在线静态资源可根据项目情况配置,QMock修改的效果可通过源码运行查看。

底部声明

页面布局底角会有个声明之类的,项目中也需要改下此文件位于 src/components/Footer/index.jsx 公共组件中,因为上边保留了国际化功能,所以还需要在en-US.jszh-CN.js修改 app.copyright.produced 的值。

登录页和菜单

页面登录窗口也涉及到如手机登录Tab、更多登录、标题、副标题等暂时不需要,这些更改的地方位于src/pages/user/Login/index.jsx 和国际化各语言文件夹下 pages.js ,这部分暂时注释掉为了方便后边实现统一登录的例子时候再用到。

最后精简优化的部分就是菜单了,对应动态菜单需要修改 config/rotues.js 具体配置后边在新增页面的时候再单独讲解,另外还有菜单底部还有内部链接,其实是集成了一个文档工具(https://d.umijs.org/zh-CN),在开发环境下会展示,主要方便使用文档相关的记录,相当于一个内部Wiki,个人觉得还比较有用,QMock后边的一些相关说明信息也打算放在这里。

经过精简优化后看下最终效果

三、登录功能实现

上边说了很多基础配置相关的,接下来个实战打通前后端服务,实现登录功能。

说明:以下实现主要照着做即可,不用勉强看懂每个实现,后续的分享具体应用到会逐一的讲,如果太过在意会打击学习的积极性,当然如果后边没有讲到或者不够清晰也欢迎加互相探讨。

用户表创建

数据库使用的是Mysql5.7+版本,本项目创建名为qmock的数据库,并创建一个users的用户表,同时添加两条数据,SQL语句如下:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; -- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT '',
`password` varchar(50) DEFAULT '',
`access` varchar(20) DEFAULT 'gust',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; -- ----------------------------
-- Records of users
-- ----------------------------
BEGIN;
INSERT INTO `users` VALUES (1, 'admin', 'admin', 'admin');
INSERT INTO `users` VALUES (2, 'user', 'user', 'user');
COMMIT; SET FOREIGN_KEY_CHECKS = 1;

登录接口

还记得一开始我们添加一些依赖吗?如果要实现Mybtis的数据库操作还需要在application.yml 增加一些配置。

server:
port: 8081 # 服务启动端口 # 数据库链接信息
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/qmock
username: mrzcode
password: mrzcode
driver-class-name: com.mysql.jdbc.Driver # Mybatis基本配置
mybatis:
type-aliases-package: cn.daqi.mock.api.entity # 指定实体类所在包
mapper-locations: classpath:mapper/*.xml # 指定mapper xml 所在位置
configuration:
map-underscore-to-camel-case: true # 数据库表字段自动转驼峰命名 如:user_name -> userName

抓取 Antd pro登录时候请求mock接口的路径和参数

curl 'http://localhost:8000/api/login/account' \
--data-raw '{"username":"admin","password":"admin","autoLogin":true,"type":"account"}'

根据此文开头给出的API请求流程图实现每一个对应的类,这里从里层往外层逐步给出代码

(一)根据用户名和密码匹配查询 注解为 @Mapper

package cn.daqi.mock.api.mapper;

import org.apache.ibatis.annotations.*;

@Mapper
public interface LoginMapper { @Select("SELECT count(*) FROM users WHERE name=#{name} and `password`=#{password}")
Integer userLogin(@Param("name") String name, @Param("password") String password);
}

(二)定义请求参数 LoginRequest.java 请求参数类 lombok @Data 注解,其中SQL只判断是否查询到用户,所以暂时用不到 LoginEntity.java 这里便不罗列了。

package cn.daqi.mock.api.entity.requests;

import lombok.Data;

@Data
public class LoginRequest {
private String username;
private String password;
}

(三)登录服务Interface和class实现类

package cn.daqi.mock.api.service;
// ...省略import,自动添加或详细看源代码
public interface LoginService {
RespResult accountLogin(LoginRequest req);
}

注解@Service 放在实现类上

package cn.daqi.mock.api.service.impl;
// ...省略import,自动添加或详细看源代码
@Service
public class LoginImpl implements LoginService { @Autowired
LoginMapper loginMapper; @Override
public RespResult accountLogin(LoginRequest req) {
Integer count= loginMapper.userLogin(req.getUsername(), req.getPassword());
if (count > 0) {
return RespResult.success();
} else {
return RespResult.failure(RespCode.USER_AUTHORITY_FAILURE);
}
}
}

(四)登录API实现类 注解说明

  • @RestController 声明为控制器(= @Controller + @ResponseBody)
  • @RequestMapping 定义跟路径
  • @PostMapping 定义POST请求方法和子路径
package cn.daqi.mock.api.controller;

import cn.daqi.mock.api.commons.RespResult;
import cn.daqi.mock.api.entity.requests.LoginRequest;
import cn.daqi.mock.api.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; /**
* @ Author: Zhang Qi
* @ Copyright: 博客&公众号《大奇测试开发》
* @ Describe: 登录接口API
*/
@RestController
@RequestMapping(value = "/api/login")
public class LoginController { @Autowired
LoginService loginService; /**
* 登录验证接口
* @param req Post请求body参数体
* @return JSON统一格式体
*/
@PostMapping(value = "/account")
public RespResult login(@RequestBody LoginRequest req){
return loginService.accountLogin(req);
}
}

(五)接口测试
运行服务分别用存在和不匹配用户密码进行下接口请求测试

登录页面

完成了后端的用户鉴权接口,现在来改造下前端的登录,使其此接口从mock请求切换到真正的后端请求,涉及以下几个处。

(一) 代理转发 同上个vue系列一样,前后端的分离项目为了解决跨域的问题都需要配置下proxy,项目使其转发指向本地的qmock-service-api后端服务,修改的文件为 config/proxy.js

dev: {
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
'/api/': {
// 要代理的地址
+ target: 'http://localhost:8081',
- // target: 'https://preview.pro.ant.design',
// 配置了这个可以从 http 代理到 https
// 依赖 origin 的功能可能需要这个,比如 cookie
changeOrigin: true,
},
},

(二)去掉前端Mock登录配置 位于mock/user.js 注释或者删除掉整块mock接口定义

'POST /api/login/account': async (req, res) => {
// ...省略内部代码
}

由于我们只是替换了一个登录接口,其他如用户信息等没有实现,依然走的是mock,所以antd这里会坑需要同步注意修改!

GET /api/currentUser 这个Mock方法需要注释或删除掉 if (!getAccess()) { ...省略... }
部分代码,否则会验证鉴权失败,大家可以打开debug对比试试。

(三)修改/account 请求 默认登录接口和后端的统一接口格式不一样,这里需要稍微修改前端对其接口的逻辑判断,登录页面文件位于 src/pages/user/Login/index.jsx

const handleSubmit = async (values) => {
try {
// 登录
const msg = await login({ ...values, type }); + if (msg.success) {
- // if (msg.stutus) {
const defaultLoginSuccessMessage = intl.formatMessage({
id: 'pages.login.success',
defaultMessage: '登录成功!',
});
message.success(defaultLoginSuccessMessage);
await fetchUserInfo();
/** 此方法会跳转到 redirect 参数所在的位置 */ if (!history) return;
const { query } = history.location;
const { redirect } = query;
history.push(redirect || '/');
return;
} console.log(msg); // 如果失败去设置用户错误信息 + setUserLoginState({ status: 'error', type:'account' });
- // setUserLoginState(msg)
} catch (error) {
const defaultLoginFailureMessage = intl.formatMessage({
id: 'pages.login.failure',
defaultMessage: '登录失败,请重试!',
});
message.error(defaultLoginFailureMessage);
}
};

以上如果全部顺利弄完,重新启动前后端服务来联调看下效果吧,如图登录的接口正确请求了真实的接口。

本次分享内容稍微有点多,时间也拖的有点久,主要是一些内容笔者在给大家实战中也有学习成本和各种问题,好在功夫不负有心人,希望通过的我的前期天坑能让大家在学习少一些弯路。

最后笔者在学习Antd中有一点体会是,React确实比Vue入门使用要复杂些,但花了两天时间看了下官方文档后更加觉得React和Antdpro在支持平台全栈开发更能有好多表现。后边也打算随着我自己掌握技能的深入,然后出一个从测试开发角度理解的React基础教程,这样对于用好Antd更事半功倍。

本次代码已同步更新到GitHub上,有需要关注并回复 “mock平台”获取,同时本次内容作为一个模版单独打了temple分支,方便大家参考或直接使用,但后续的功能实现都会正常以master分支提交。

测试开发【Mock平台】04实战:前后端项目初始化与登录鉴权实现的更多相关文章

  1. NodeJS平台下的前后端文件共享

    一.前后端文件共享的需要背景——为什么需要共享? 项目基本JS/NodeJS全端开发,有部分代码前后端都需要用得到 有一些配置是在前后端都需要用得到的 区别其他开发平台,NodeJS平台下的前后端文件 ...

  2. 基于NodeJS的全栈式开发(基于NodeJS的前后端分离)

    也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离) 前言 为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异.痛定思痛,今天我们 ...

  3. 项目平台统一(前后端IDE、代码风格)

    项目平台统一(前后端IDE.代码风格) 记录人:娄雨禛 前端:Webstorm(HTML+CSS+JavaScript) 后端:IntelliJ IDEA(Java) 代码风格:Java风格代码 代码 ...

  4. Docker 部署前后端项目

    Docker 部署前后端项目 平生不会相思,才会相思,便害相思. 简介:都是被逼的,从零开始一个Docker 部署九个微服务和三个前端项目.其中,这些服务需要用到Nacos.MySQL.Nginx.E ...

  5. vue+springboot前后端分离实现单点登录跨域问题处理

    最近在做一个后台管理系统,前端是用时下火热的vue.js,后台是基于springboot的.因为后台系统没有登录功能,但是公司要求统一登录,登录认证统一使用.net项目组的认证系统.那就意味着做单点登 ...

  6. Spring Security OAuth2.0认证授权六:前后端分离下的登录授权

    历史文章 Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授权二:搭建资源服务 Spring Security OA ...

  7. 前后端分离使用 Token 登录解决方案

    前后端分离使用 Token 登录解决方案:https://juejin.im/post/5b7ea1366fb9a01a0b319612

  8. 在IDEA中使用Maven将SpringBoot项目打成jar包、同时运行打成的jar包(前后端项目分离)

    1.maven教程官网 https://m.runoob.com/maven/ 2.理解Maven的构建生命周期(clean.Package) 3.在项目中使用maven进行打包 4.运行打包好的ja ...

  9. Go+gRPC-Gateway(V2) 微服务实战,小程序登录鉴权服务(五):鉴权 gRPC-Interceptor 拦截器实战

    拦截器(gRPC-Interceptor)类似于 Gin 中间件(Middleware),让你在真正调用 RPC 服务前,进行身份认证.参数校验.限流等通用操作. 系列 云原生 API 网关,gRPC ...

随机推荐

  1. LGP4287题解

    小清新 manacher 题.题意清楚. 首先看到回文,自然而然地就去想 manacher 了.先想想,manacher 到底在干嘛? manacher 做的其实是一个暴力,枚举每一个位置最远能够伸到 ...

  2. LGP2726题解

    当初 mark 这道题还是因为看到是黑,感觉比较水,然后它现在掉紫了. 不过这题题解居然满了,写一篇给自己看吧. 首先我们有一个思路,就是割掉一条边,然后分别求两颗树的重心. 等等,这好像是CSP原题 ...

  3. BBS项目分布搭建四(点赞点踩及评论功能准备)

    BBS项目分布搭建四(点赞点踩及评论功能) 1. 点赞点踩样式准备 # 在base.html文件中 head标签内 添加css模块: {% block css %} {% endblock %} # ...

  4. 终结初学者对ElasticSearch、Kibana、Logstash安装的种种困难

    项目中准备使用ElasticSearch,之前只是对ElasticSearch有过简单的了解没有系统的学习,本系列文章将从基础的学习再到深入的使用. 咔咔之前写了一份死磕MySQL文章,如今再入一个系 ...

  5. 关于二维DP————站上巨人的肩膀

    意匠惨淡经营中ing, 语不惊人死不休........ 前几天学了DP,做了个简单的整理,记录了关于DP的一些概念之类的,今天记录一下刚学的一个类型 ----关于二维DP 那建立二维数组主要是干嘛用的 ...

  6. python psutila模块(示例)

    # qianxiao996精心制作 #博客地址:https://blog.csdn.net/qq_36374896 import psutil import time import datetime ...

  7. 什么?Android上面跑Linux?

    前言 众所周知,现在程序员因为工作.个人兴趣等对各种系统的需求越来越大,部分人电脑做的还是双系统.其中,比较常见的有各种模拟器.虚拟机在windows上面跑Android.Linux,大家估计都习以为 ...

  8. VS Code通过code runner插件编译运行多个cpp文件 | 链接编译.h文件

    1.多个cpp文件在同一级目录 参考:https://jingyan.baidu.com/article/2f9b480d7ceb3d01ca6cc224.html 此时可通过修改Code Runne ...

  9. java代码常用知识点

    1.Assert java断言assert是jdk1.4引入的.assert这个关键字我们称之为"断言".当这个关键字后边的条件为假的时候,程序自动崩溃并抛出AssertionEr ...

  10. SpringDataJpa备忘录

    单向多对一关系 //产品类型 一的一方 @Entity public class ProductDir { @Id @GeneratedValue private Long id; private S ...