【QA能力建設(shè)】Java Spring Boot項(xiàng)目-代碼走讀

以下內(nèi)容為個人理解,有不足之處還望指正......

背景:我們多數(shù)時候,測試都是基于表層現(xiàn)象看問題,部分缺陷很容易發(fā)現(xiàn)(開發(fā)代碼寫錯),但因?yàn)闇y試場景的遺漏,導(dǎo)致上線出問題。所以我們需要對開發(fā)的代碼有整體了解。

目的:1.加強(qiáng)對需求實(shí)現(xiàn)的了解;2.對項(xiàng)目整體可以做到心中有數(shù),以確定測試邊界(有疑問或不理解的地方,可以和開發(fā)進(jìn)行思維碰撞;了解越多,測試設(shè)計可以更加充分);3.識別一些低級別缺陷。


以下一、二、三大點(diǎn)是走讀代碼的前置條件

一.了解Java項(xiàng)目關(guān)鍵字 (部分參考網(wǎng)上)

在一般工程中,基本上都會出現(xiàn)controller、service、impl、Dao等關(guān)鍵字,來說下這些關(guān)鍵字之間的聯(lián)系

Controller:負(fù)責(zé)具體的業(yè)務(wù)模塊流程控制,在此層里面要調(diào)用Serice層的接口來控制業(yè)務(wù)流程,控制的配置是在Spring的配置文件里面進(jìn)行,針對具體的業(yè)務(wù)流程,會有不同的控制器。

Service:Service層主要負(fù)責(zé)業(yè)務(wù)模塊的邏輯應(yīng)用設(shè)計。同樣是首先設(shè)計接口,再設(shè)計其實(shí)現(xiàn)的類(impl),接著再Spring的配置文件中配置其實(shí)現(xiàn)的關(guān)聯(lián)。Service層的業(yè)務(wù)實(shí)現(xiàn),具體要調(diào)用到已定義的Dao層的接口。

Dao:Dao層主要是做數(shù)據(jù)持久層的工作,負(fù)責(zé)與數(shù)據(jù)庫進(jìn)行聯(lián)絡(luò)的一些任務(wù)都封裝在此,Dao層的設(shè)計首先是設(shè)計Dao的接口,然后在Spring的配置文件中定義此接口的實(shí)現(xiàn)類,然后就可在模塊中調(diào)用此接口來進(jìn)行數(shù)據(jù)業(yè)務(wù)的處理,而不用關(guān)心此接口的具體實(shí)現(xiàn)類是哪個類,顯得結(jié)構(gòu)非常清晰,Dao層的數(shù)據(jù)源配置,以及有關(guān)數(shù)據(jù)庫連接的參數(shù)都在Spring的配置文件中進(jìn)行配置。

二.了解maven

1.簡介參考maven(一) maven到底是個啥玩意~。

2.安裝maven查看

3.公司私庫配置。

配置完成后,在IDEA>Terminal中跑sh package.sh ,出現(xiàn)如下所示 就代表成功導(dǎo)入 公司私庫內(nèi)的jar包。

image.jpeg

4.做以上操作的目的?

為了能在Java項(xiàng)目 代碼走讀時看到Dao內(nèi)方法的具體實(shí)現(xiàn)(對數(shù)據(jù)庫的增刪改查)。

三.了解pom.xml文件

pom是項(xiàng)目對象模型(Project Object Model)的簡稱,它是Maven項(xiàng)目中的文件,使用XML表示,名稱叫做pom.xml。作用類似ant的build.xml文件,功能更強(qiáng)大。該文件用于管理:源代碼、配置文件、開發(fā)者的信息和角色、問題追蹤系統(tǒng)、組織信息、項(xiàng)目授權(quán)、項(xiàng)目的url、項(xiàng)目的依賴關(guān)系等等。詳細(xì)可查看

四.小白實(shí)操 代碼走讀

示例 project:dada-api-learning branch:feature/LEAR-1781

image.jpeg

?前戲?

1.到公司gitlab獲取工程,克隆倉庫到本地。

git clone git@xxxxxxxxxxxxxx/dada-api-learning.git;然后 git checkout feature/LEAR-1781 ----git命令不熟的自己去補(bǔ)

2.打開IntelliJ IDEA讀取工程。

?開始?

思考下,整個工程那么多代碼,我們應(yīng)重點(diǎn)關(guān)注什么???

我的理解:后端代碼主要實(shí)現(xiàn)業(yè)務(wù)數(shù)據(jù)的增刪改查,將數(shù)據(jù)返回客戶端。

故而,我們關(guān)注的重點(diǎn)就是由客戶端發(fā)送HTTP請求--->后端接收請求--->進(jìn)行邏輯處理,提取數(shù)據(jù)--->將數(shù)據(jù)返回客戶端。這整個過程。

那么,咱們詳細(xì)解讀下整個過程 (示例API:/v2/learning/yearendreport/getReport)


*首先,客戶端發(fā)來的HTTP請求是由Controller接收的

那么我們要找到Controller目錄(在src/main/java/com.dadaabc.api.learning/controller),然后再找對應(yīng)業(yè)務(wù)命名的Controller文件進(jìn)入 || 若不知文件名,可以復(fù)制對應(yīng)API 包含的方法名,在IDEA中雙擊shift打開搜索框搜索進(jìn)入
image.jpeg

下圖為Controller層代碼
image.jpeg

Controller層詳解:

1.@RestController關(guān)鍵字會接收客戶端發(fā)來的HTTP請求,然后用@RequestMapping關(guān)鍵字去匹配對應(yīng)路徑的請求(關(guān)鍵字后跟的("/v2/learning/yearendreport")就是對應(yīng)接口的前置路徑)

2.如果匹配成功,然后就執(zhí)行下面的YearEndReportController類

1)private static final Logger logger = LoggerFactory.getLogger(YearEndReportController.class); 意思是使用指定YearEndReportController類初始化日志對象,方便在日志輸出的時候,打印日志信息。

2)自動裝配了這個接口的業(yè)務(wù)實(shí)現(xiàn)邏輯(service),具體為什么會在這個地方引入,咱們先不深究。

@Autowired

private YearEndReportService yearEndReportService;

@Autowired

private YearEndReportInitService initService;

@Autowired

private AsyncService asyncService;

3.@RequestMapping(value = "/getReport", method = RequestMethod.POST) 這塊就是真正匹配接口了,意思是以/v2/learning/yearendreport/getReport結(jié)尾的post請求會匹配執(zhí)行g(shù)etReport()方法

1) @RequestBody JSONObject jsonObject 意思是接收的參數(shù)來自于requestBody中(即請求體),且傳參為json格式。

2)Integer studentId = jsonObject.getInteger("studentId");表示去取前端傳遞的參數(shù)(參數(shù)為整型)

4.以下代碼表示先校驗(yàn)學(xué)生id,若id不存在就直接返回錯誤code碼和message 至客戶端。

if (studentId == null) {

logger.info("getReport studentId is null");

return ErrorCode.BAD_PARAMETER;

}

5.以下代碼中的yearEndReportService就是具體業(yè)務(wù)邏輯實(shí)現(xiàn)的類(service層),getReportByStudentId就是業(yè)務(wù)實(shí)現(xiàn)的具體方法;可以按住Ctrl,點(diǎn)擊getReportByStudentId跳轉(zhuǎn)查看具體實(shí)現(xiàn)。(這一步就跳轉(zhuǎn)到了業(yè)務(wù)具體實(shí)現(xiàn)的service層)

ResponseData responseData = yearEndReportService.getReportByStudentId(studentId);

下圖為Service層代碼(這塊是設(shè)計接口,具體實(shí)現(xiàn)邏輯在ResponseData getReportByStudentId(int studentId);)
image.jpeg

點(diǎn)左側(cè) 箭頭指向處 可跳轉(zhuǎn)查看具體實(shí)現(xiàn)的類(impl)

下圖為Service具體實(shí)現(xiàn)的類(impl)方法,這塊也就是 核心業(yè)務(wù)邏輯

image.jpeg

Service層詳解:

1.YearEndReport report = yearEndReportDao.findByStudentId(studentId); 這塊意思是在yearEndReportDao下的findByStudentId方法里去查學(xué)生的信息,需傳入studentId,將查出的結(jié)果賦值給report變量。 ---Dao層在最后提及

2.以下代碼的意思是,如果查表得出的學(xué)生信息不存在,就去調(diào)createNewUserReport方法實(shí)時創(chuàng)建用戶的報告(需傳入學(xué)生id);若實(shí)時創(chuàng)建時也找不到學(xué)生信息,那么就打印日志說“這個學(xué)生依舊沒有報告”,并且return出去(將code碼和"null"返回客戶端);若創(chuàng)建報告成功,那么就將報告數(shù)據(jù)插入到y(tǒng)earEndReport表中

if (report == null) {

report = createNewUserReport(studentId);

if (report == null) {

    logger.info("getReportByStudentId this student still dont have studentId:{}", studentId);

return new ResponseData(ResponseData.CODE_SUCCESS, report);

}

logger.info("getReportByStudentId this student is new,studentId:{},newReport:{}", studentId, report);

yearEndReportDao.insertReport(report);

}

3.JSONObject jsonReport = JSONObject.parseObject(reportInfo); 意思是將報告內(nèi)容轉(zhuǎn)換成json格式

4.以下代碼的意思是,更新 studentName/studentAvatar/likeReport/avatarInfo這4項(xiàng)信息到報告內(nèi)容中去,最后將所有信息返回客戶端(包括code_success狀態(tài)碼和json格式的報告內(nèi)容)

JSONObject jsonReport = JSONObject.parseObject(reportInfo);

jsonReport.put("studentName", report.getStudentName());

jsonReport.put("studentAvatar", report.getStudentAvatar());

jsonReport.put("likeReport", report.getLikeReport());

String avatarInfo = jsonReport.getString("avatarInfo");

jsonReport.put("avatarInfo", JSONObject.parseObject(avatarInfo));

return new ResponseData(ResponseData.CODE_SUCCESS, jsonReport);

下圖為Dao層代碼:

Dao入口:(點(diǎn)擊截圖箭頭指向區(qū)域跳轉(zhuǎn)查看)
image.jpeg

下圖是實(shí)現(xiàn)Dao的接口,具體邏輯都在YearEndReport findByStudentId(int studentId);內(nèi),點(diǎn)擊圖中箭頭指向處,跳轉(zhuǎn)查看SQL語句

image.jpeg

Dao層詳解:

下圖就是上面跳轉(zhuǎn)過來的具體的實(shí)現(xiàn)(SQL查詢),其中#{studentId} 讀取的是跳轉(zhuǎn)前傳過來的參數(shù)

SQL : SELECT id,student_id,student_name, student_avatar,like_report, report_info FROM year_end_report WHERE student_id = #{studentId} order by id desc limit 1;
image.jpeg

讀到這里,后端接收HTTP請求—>處理數(shù)據(jù)—>將數(shù)據(jù)返回客戶端,這整個流程的代碼算是走讀完畢。

通過以上步驟,你應(yīng)該知道這個接口到底查了什么東西,與你的預(yù)期結(jié)果是否一致。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容