测试开发【Mock平台】04实战:前后端项目初始化与登录鉴权实现
【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 / falseprivate Boolean success;// 實際返回的數據private Object data;// 錯誤編碼private Integer errorCode;// 錯誤信息private String errorMessage;// 提示類型: 0 silent; 1 message.warn; 2 message.error; 4 notification; 9 pageprivate 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.js和zh-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 {@AutowiredLoginMapper loginMapper;@Overridepublic 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請求方法和子路徑
(五)接口測試
運行服務分別用存在和不匹配用戶密碼進行下接口請求測試
登錄頁面
完成了后端的用戶鑒權接口,現在來改造下前端的登錄,使其此接口從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 的功能可能需要這個,比如 cookiechangeOrigin: 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实战:前后端项目初始化与登录鉴权实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我的世界粘土服务器怎么注册a,我的世界粘
- 下一篇: linux mediainfo java