【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. javascript、css3曲线运动示例记录

    想做一个加入购物车的曲线动效,网上找到两个demo,分别是js和css3实现的. js:https://www.cnblogs.com/wangmeijian/p/5824176.html jquer ...

  2. 『现学现忘』Docker基础 — 26、Docker镜像分层的理解

    目录 1.分层的镜像 2.加深理解 3.特别说明 1.分层的镜像 我们可以去下载一个镜像,注意观察下载的日志输出,可以看到Docker的镜像是一层一层的在下载. 思考:为什么Docker镜像要采用这种 ...

  3. CPU是海王?聊聊 主/子线程 和 同/异步 的关系

    最近表弟一直在找实习,经常会问我一些问题,有些问题在没有经历过真实工作时是真的不好理解的,所以我开了这个[表弟专栏],专门为找工作的表弟解决一些疑惑. 这篇文章从计算机发展的角度出发,描述为什么计算机 ...

  4. pyhon反射

    一:反射 1.python面向对象中的反射: 通过字符串的形式操作对象相关的属性.python中的一切事物都是对象(都可以使用反射) 2.四个内置方法 hasattr 检测是否含有某属性 getatt ...

  5. CVE-2017-8759 微软word漏洞复现以及利用

    CVE-2017-8759 微软word漏洞复现以及利用 0x00 漏洞描述 近日,360集团核心安全事业部分析团队发现一个新型的Office文档高级威胁攻击,攻击使用了9月12日补丁刚修复的.NET ...

  6. unittest 测试用例实现

    unittest框架结构 test_case: 测试套件,每一个.py文件代表一个测试用例,测试用例以test开头,否则框架读取不到测试用例 __init__.py是做什么的? 要弄明白这个问题,首先 ...

  7. Linux源码安装RabbitMQ高可用集群

    1.环境说明 linux版本:CentOS Linux release 7.9.2009 erlang版本:erlang-24.0 rabbitmq版本:rabbitmq_server-3.9.13 ...

  8. BGP的四类属性详解

    BGP的四类属性 公认必遵(Well-known mandatory) 要求所有运行BGP协议的设备都必须能识别,且在更新消息中必须包含. Origin(起源) 属性 用来标识路由信息的来源. 如果路 ...

  9. newFixedThreadPool的默认值

    可以点进去,每个的默认值都是不同的

  10. 什么是 Spring Batch?

    Spring Boot Batch 提供可重用的函数,这些函数在处理大量记录时非常重要,包括日志/跟踪,事务管理,作业处理统计信息,作业重新启动,跳过和资源管理.它还提供了更先进的技术服务和功能,通过 ...