無(wú)錫科技職業(yè)學(xué)院 崔凱洋
互聯(lián)網(wǎng)求職已經(jīng)不再新鮮,市面上的招聘平臺(tái)廣泛卻不精準(zhǔn),如何為校園學(xué)生精準(zhǔn)對(duì)接優(yōu)質(zhì)的企業(yè)資源、為提升學(xué)生的就業(yè)優(yōu)勢(shì)已成為師生間討論的焦點(diǎn)話題。應(yīng)屆畢業(yè)生的實(shí)習(xí)問(wèn)題涉及到學(xué)校、企業(yè),在求職和招聘問(wèn)題上,如何讓學(xué)校、企業(yè)和學(xué)生都滿意是我們項(xiàng)目的初衷。頂崗實(shí)習(xí)校企生三方管理平臺(tái)是面向校園、權(quán)威領(lǐng)先的校園招聘平臺(tái)。為學(xué)生提供求職、實(shí)訓(xùn)和準(zhǔn)確的企業(yè)招聘信息,為企業(yè)提供學(xué)校官方認(rèn)可的人才招聘渠道,可提前發(fā)布校招信息,搶得獲取優(yōu)秀人才的先機(jī),學(xué)??梢詣?dòng)態(tài)的查看學(xué)生求職的意向,為其提供更加優(yōu)質(zhì)的就業(yè)計(jì)劃。同時(shí),學(xué)校也可以審核企業(yè)信息,保證招聘企業(yè)、信息的安全可靠及時(shí)與企業(yè)協(xié)商人才輸送方案等??偠灾?,頂崗實(shí)習(xí)校企生三方管理平臺(tái)可為學(xué)校、企業(yè)、學(xué)生提供全方位的人力資源服務(wù)。
頂崗實(shí)習(xí)三方管理平臺(tái)后端采用SpringBoot、Mybatis、EasyPoi、Maven、MySQL、Java8、Git等主流技術(shù)棧;前端采用漸進(jìn)式JavaScript框架Vue和UI設(shè)計(jì)語(yǔ)言AntDesign。頂崗實(shí)習(xí)平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn)的過(guò)程中主要完成了以下八個(gè)業(yè)務(wù)的設(shè)計(jì):針對(duì)學(xué)生、教師、企業(yè)、學(xué)校用戶(hù)的管理、權(quán)限管理、角色管理、職位管理、投遞管理,資質(zhì)管理、招聘企業(yè)管理、展臺(tái)管理。平臺(tái)上線后,能夠進(jìn)一步幫助學(xué)生提高社會(huì)實(shí)踐能力。
頂崗實(shí)習(xí)在很多院校都是一門(mén)必修課。無(wú)錫科技職業(yè)學(xué)院以頂崗實(shí)習(xí)作為一門(mén)課程并注重學(xué)生實(shí)踐能力的培養(yǎng),建校以來(lái)與眾多優(yōu)秀的企業(yè)合作,為新吳區(qū)企業(yè)提供專(zhuān)業(yè)人才輸送。時(shí)至今日,越來(lái)越多的學(xué)生選擇無(wú)錫科技職業(yè)學(xué)院,每個(gè)班的班主任通過(guò)Excel表格匯總各班的就業(yè)情況并將其匯總至每個(gè)系,再由每個(gè)系匯集到每個(gè)學(xué)院中,最終將所有學(xué)院的就業(yè)信息匯集起來(lái),才能統(tǒng)一的分析這一年的學(xué)生的就業(yè)率、就業(yè)偏好,然后再制定下一年的招生計(jì)劃,整個(gè)過(guò)程需要眾多人員的參與。有教師反映Excel表格的信息填寫(xiě)十分耗時(shí),不但加重了班主任、年級(jí)主任和院長(zhǎng)的工作量,而且使得教師本應(yīng)該專(zhuān)注在教學(xué)任務(wù)上的時(shí)間、精力減少。學(xué)校與學(xué)生就業(yè)的矛盾日漸突出,為此,校領(lǐng)導(dǎo)集中開(kāi)會(huì)研討,本項(xiàng)目的雛形應(yīng)運(yùn)而生。
在現(xiàn)有的市場(chǎng)中,不乏優(yōu)秀的招聘就業(yè)平臺(tái),并且已經(jīng)取得了卓越的市場(chǎng)表現(xiàn)。這些招聘就業(yè)平臺(tái)大多數(shù)都是面向全國(guó),招聘領(lǐng)域也是五花八門(mén),有的甚至功能臃腫,廣告也隨處可見(jiàn),最讓人觸目驚心的是一些虛假招聘信息充斥在互聯(lián)網(wǎng)上,讓人難辨真假。在公民信息納入法制正規(guī)的今天,依然能夠看到有些企業(yè)不顧人民利益,賺取不義之財(cái)。2021年央視《3·15晚會(huì)》上,招聘平臺(tái)泄露求職者簡(jiǎn)歷的現(xiàn)象,已經(jīng)形成了“黑色產(chǎn)業(yè)鏈”。我們團(tuán)隊(duì)為無(wú)錫科技職業(yè)學(xué)院設(shè)計(jì)一款能夠在線上運(yùn)營(yíng)的頂崗實(shí)習(xí)平臺(tái),在精準(zhǔn)的面向本校應(yīng)屆畢業(yè)生和有效的保護(hù)本校學(xué)生的信息安全、保障企業(yè)信息的真實(shí)性上做到了兼顧。校園市場(chǎng)上也迫切的需要一個(gè)學(xué)校、企業(yè)、學(xué)生三方互惠互利的頂崗實(shí)習(xí)平臺(tái)。
后端技術(shù)發(fā)展到今天已經(jīng)非常成熟,Java更是擅長(zhǎng)平臺(tái)軟件的開(kāi)發(fā)。頂崗實(shí)習(xí)平臺(tái)以Java為主要的開(kāi)發(fā)語(yǔ)言。
SpringBoot為Java開(kāi)發(fā)人員提供了一個(gè)很好的平臺(tái)來(lái)開(kāi)發(fā)一個(gè)可以獨(dú)立運(yùn)行和生產(chǎn)級(jí)別的B/S應(yīng)用程序[1]。
另外,得益于JVM的幫助,以Java作為主要的開(kāi)發(fā)語(yǔ)言會(huì)大大降低平臺(tái)適配性的難度,這也為我們后期考慮上線移動(dòng)端提供了可能。
頂崗實(shí)習(xí)平臺(tái)數(shù)據(jù)庫(kù)使用的是開(kāi)源的MySQL,我們團(tuán)隊(duì)成員都是在校學(xué)生,充分利用JetBrains公司的教育優(yōu)惠政策下載并使用教育版的集成開(kāi)發(fā)環(huán)境IntelliJ IDEA,免費(fèi)空間的遠(yuǎn)程代碼倉(cāng)庫(kù)Gitee,一臺(tái)8GB教師優(yōu)惠云服務(wù)器。盡量用最低的經(jīng)濟(jì)成本開(kāi)發(fā)一個(gè)高效的能實(shí)際上線的項(xiàng)目。
在頂崗實(shí)習(xí)項(xiàng)目剛剛啟動(dòng)不久后,我們就著重制定了合理的項(xiàng)目實(shí)施進(jìn)度計(jì)劃表,以及團(tuán)隊(duì)成員的分工與合作。由于本項(xiàng)目是在疫情防控期間制作完成的,我們團(tuán)隊(duì)成員很少能夠聚集在一起討論技術(shù)難題,非常感謝騰訊會(huì)議能夠提供一個(gè)使我們團(tuán)隊(duì)成員互相交流的機(jī)會(huì)。
我們團(tuán)隊(duì)盡量避免由于經(jīng)驗(yàn)不足過(guò)度使用某項(xiàng)新技術(shù),以確保項(xiàng)目在出現(xiàn)問(wèn)題后能夠及時(shí)的查找出錯(cuò)原因,嚴(yán)格按照三層架構(gòu)編程,通過(guò)軟件測(cè)試來(lái)保障頂崗實(shí)習(xí)平臺(tái)的正確性和健壯性。
如圖1所示,不同權(quán)限的用戶(hù)通過(guò)域名訪問(wèn)登錄界面,用戶(hù)輸入賬號(hào)密碼后會(huì)發(fā)送一個(gè)請(qǐng)求,該請(qǐng)求經(jīng)過(guò)Nginx反向代理到存放Java應(yīng)用程序的Tomcat容器中,接著會(huì)訪問(wèn)服務(wù)器內(nèi)部的地址:http://localhost:8090,該請(qǐng)求在Tomcat容器的Java程序中拿到賬號(hào)、密碼還有一些必要信息返回給前端瀏覽器并與用戶(hù)輸入的賬號(hào)密碼進(jìn)行比對(duì)。如果賬號(hào)密碼與Java程序查到的賬號(hào)密碼一致,則登錄成功;不一致則返回錯(cuò)誤信息。用戶(hù)登錄后任何的請(qǐng)求都會(huì)經(jīng)過(guò)應(yīng)用服務(wù),比如用戶(hù)通過(guò)搜索框搜索職位信息是通過(guò)原生SQL完成的,學(xué)生上傳簡(jiǎn)歷存儲(chǔ)在服務(wù)器中的簡(jiǎn)歷文件夾。瀏覽器中大部分都是動(dòng)態(tài)的數(shù)據(jù)存放在MySQL數(shù)據(jù)庫(kù)中,用戶(hù)的操作被有序的記錄下來(lái),存放在日志文件中。前后端分離后,需要由前后端工程師共同定義接口,使用Swagger在線生成接口文檔之后,大家都根據(jù)這個(gè)接口文檔進(jìn)行開(kāi)發(fā)。由于是團(tuán)隊(duì)項(xiàng)目,我們使用云托管平臺(tái)碼云,并在阿里云部署上線。
圖1 頂崗實(shí)習(xí)平臺(tái)架構(gòu)圖Fig.1 Structure diagram of post practice platform
角色是一種特殊的權(quán)限。企業(yè)通過(guò)審核后操作權(quán)限將得到提升,在實(shí)際的使用中,給賬號(hào)賦予某項(xiàng)操作的權(quán)限,有可能因?yàn)榭紤]不周到,賦予了該用戶(hù)不該有的權(quán)限或者少賦予了某個(gè)權(quán)限。這就要求我們?yōu)槎鄠€(gè)權(quán)限設(shè)置一種角色,通過(guò)某個(gè)角色來(lái)管理某些權(quán)限,這將優(yōu)化繁瑣的賦權(quán)過(guò)程。
企業(yè)用戶(hù)通過(guò)發(fā)布招聘信息,發(fā)布在學(xué)生、企業(yè)和學(xué)校的首頁(yè)上,學(xué)生看到心儀的崗位可以投遞簡(jiǎn)歷。學(xué)生投遞后企業(yè)可以閱讀簡(jiǎn)歷,如果企業(yè)認(rèn)為該簡(jiǎn)歷不符合企業(yè)的招聘需求,企業(yè)可以直接拒絕該簡(jiǎn)歷,此時(shí)學(xué)生將會(huì)收到簡(jiǎn)歷被某某公司拒絕的消息提示;如果企業(yè)認(rèn)為該學(xué)生的簡(jiǎn)歷符合企業(yè)的招聘需求,則可直接通過(guò)簡(jiǎn)歷中的聯(lián)系方式聯(lián)系學(xué)生,可以電話視頻面試、也可以線下面試,面試后再由企業(yè)決定該學(xué)生的去與留。
學(xué)生的每一次投遞都會(huì)被記錄,學(xué)校管理員、教師都可以查看每個(gè)班級(jí)的投遞統(tǒng)計(jì)、錄取統(tǒng)計(jì)、簡(jiǎn)歷被拒絕的統(tǒng)計(jì)等。
頂崗實(shí)習(xí)平臺(tái)使用的數(shù)據(jù)庫(kù)是MySQL 8.0,設(shè)計(jì)數(shù)據(jù)首先就要考慮到字MySQL字段約束,所有的數(shù)據(jù)表中使用主鍵約束。在頂崗實(shí)習(xí)平臺(tái)項(xiàng)目中,外鍵約束、聯(lián)合主鍵是禁止被使用的,當(dāng)然也是禁止外鍵的聯(lián)級(jí)操作。如果設(shè)置外鍵約束,每次進(jìn)行插入、刪除和更新操作的時(shí)候,都必須考慮外鍵約束,我們應(yīng)該盡可能的用Java邏輯代碼判斷,這樣可以避免一些不必要的查詢(xún)某條數(shù)據(jù)是否存在。在設(shè)計(jì)數(shù)據(jù)庫(kù)的時(shí)候要充分考慮一對(duì)一關(guān)聯(lián)、一對(duì)多關(guān)聯(lián)、多對(duì)一關(guān)聯(lián)和多對(duì)多關(guān)聯(lián)用于維護(hù)數(shù)據(jù)與數(shù)據(jù)之間的關(guān)系。在整個(gè)數(shù)據(jù)庫(kù)的查詢(xún)中,只使用主鍵與主鍵相關(guān)聯(lián)。如果兩個(gè)表有關(guān)系表的時(shí)候,盡量添加拓展字段組成新的數(shù)據(jù)表。設(shè)計(jì)User、Role、Permision表以及他們的關(guān)系表,在如圖2所示頂崗實(shí)習(xí)頂崗數(shù)據(jù)表逆向圖中可以清晰的看到學(xué)校信息表、班級(jí)表、學(xué)院表、學(xué)校表、企業(yè)資質(zhì)表等。頂崗實(shí)習(xí)平臺(tái)數(shù)據(jù)表的設(shè)計(jì)整體原則是可以對(duì)數(shù)據(jù)表字段增加,但是絕對(duì)不允許修改,不要使用MySQL 8.0的關(guān)鍵字,這就要求在設(shè)計(jì)數(shù)據(jù)表字段時(shí)要充分考慮字段的合法性。
圖2 頂崗實(shí)習(xí)平臺(tái)數(shù)據(jù)庫(kù)逆向圖Fig.2 Reverse diagram of post practice platform database
為了方便敘述,這里采用在線方式創(chuàng)建SpringBoot項(xiàng)目的腳手架,在如圖3所示中右側(cè)可以先添加必要的依賴(lài),在啟動(dòng)IDEA后,可以在pom.xml添加項(xiàng)目完整的Maven依賴(lài)。
圖3 頂崗實(shí)習(xí)平臺(tái)在線環(huán)境搭建Fig.3 Construction of on-the-job practice platform and online environment
在頂崗實(shí)習(xí)平臺(tái)并不需要單獨(dú)地對(duì)照數(shù)據(jù)表寫(xiě)實(shí)體類(lèi),可以借助MybatisX 插件生成實(shí)體類(lèi)。
在頂崗實(shí)習(xí)平臺(tái)統(tǒng)一使用POJO包存放實(shí)體類(lèi)。定義出接收前端傳來(lái)的VO類(lèi)和返回結(jié)構(gòu)的DTO類(lèi),這個(gè)類(lèi)相當(dāng)于是實(shí)體類(lèi)的拓展,為了統(tǒng)一風(fēng)格,所有的接收參數(shù)與返回結(jié)構(gòu)都需要單獨(dú)編寫(xiě)。
3.3.1 異常處理與跨域處理
值得注意的是項(xiàng)目當(dāng)中有一些異常,編寫(xiě)統(tǒng)一同異常處理類(lèi)可以使我們的代碼更加簡(jiǎn)潔可讀性高,不需要再每個(gè)方法后面拋出異常,這時(shí)我們需要統(tǒng)一的處理[2]。例如,在進(jìn)行邏輯刪除的時(shí)候先檢查數(shù)據(jù)庫(kù)中是否存在這條數(shù)據(jù),如果存在,則進(jìn)行邏輯刪除。一般項(xiàng)目數(shù)據(jù)庫(kù)和Java程序并不是在一臺(tái)服務(wù)器上,此時(shí)還有可能因?yàn)榉?wù)器宕機(jī)、停電導(dǎo)致數(shù)據(jù)庫(kù)停止運(yùn)行,這時(shí)需要檢測(cè)在數(shù)據(jù)刪除的過(guò)程中有沒(méi)有異常的出現(xiàn),這都是我們應(yīng)該考慮到的。
跨域問(wèn)題是前后端開(kāi)發(fā)人員必須經(jīng)歷的過(guò)程,可以完全由前端處理,也可以由后端完全處理,也可以采用前后端混合處理,頂崗實(shí)習(xí)項(xiàng)目中采用的方式是完全由后端人員處理。
3.3.2 攔截器、Token如圖4所示,一個(gè)請(qǐng)求在攔截器中經(jīng)過(guò)Filter到Controller層,再由Controller拋出響應(yīng),因此所有的請(qǐng)求最先進(jìn)入Filter,最后離開(kāi)Filter。
圖4 攔截器原理圖Fig.4 Schematic diagram of interceptor
Token是沒(méi)有狀態(tài)的,用戶(hù)的每一次請(qǐng)求都要求攜帶Token。在傳統(tǒng)的方式中,我們使用Session存儲(chǔ)用戶(hù)的登錄狀態(tài),一旦用戶(hù)在同一時(shí)間大量訪問(wèn),存儲(chǔ)這些用戶(hù)Session信息的服務(wù)器將會(huì)面臨巨大的帶寬壓力,甚至?xí)斐删W(wǎng)絡(luò)堵塞,影響用戶(hù)體驗(yàn)。Token的無(wú)狀態(tài)可以完美解決此問(wèn)題。此外Token還可以防止跨站請(qǐng)求偽造攻擊,頂崗實(shí)習(xí)平臺(tái)在一周后Token自動(dòng)過(guò)期,每次重新登錄后也會(huì)更新Token,極大的提高了用戶(hù)信息的安全。
在核心代碼實(shí)現(xiàn)章節(jié)中,控制層要充分考慮每一個(gè)接口是否要使用Token。除登錄不需要用戶(hù)攜帶Token外,其他的任何操作都需要Token的支持。
3.3.3 業(yè)務(wù)處理
作為后端程序的開(kāi)發(fā)人員,我們應(yīng)更加注重,具體的業(yè)務(wù)的實(shí)現(xiàn)過(guò)程,具體的業(yè)務(wù)實(shí)現(xiàn)過(guò)程依賴(lài)于持久層(Mapper)、業(yè)務(wù)層(Service)、控制層(Controller)。
(1)Mapper層即數(shù)據(jù)持久層,也被稱(chēng)為DAO層,Mapper層作用為訪問(wèn)數(shù)據(jù)庫(kù),向數(shù)據(jù)庫(kù)發(fā)送SQL語(yǔ)句,完成數(shù)據(jù)的增刪改查任務(wù)。(2)Service層即業(yè)務(wù)邏輯層,作用是完成功能設(shè)計(jì),Service層調(diào)用Mapper層接口,接收Mapper層返回的數(shù)據(jù),完成項(xiàng)目的基本功能設(shè)計(jì)。(3)Controller層即控制層,功能為請(qǐng)求和響應(yīng)控制。Controller層負(fù)責(zé)前后端交互,接受前端請(qǐng)求,調(diào)用Service層,接收Service層返回的數(shù)據(jù),最后返回具體的頁(yè)面和數(shù)據(jù)到客戶(hù)端。
第一步就是規(guī)劃我們的SQL語(yǔ)句,這一步非常重要,一個(gè)具體的業(yè)務(wù)最終都是落實(shí)在SQL語(yǔ)句上;第二步是設(shè)計(jì)接口和抽象方法,選擇合適的返回值類(lèi)型與接口名;第三步編寫(xiě)Mapper映射文件。如圖5所示可以看到本次查詢(xún)職位信息的持久層部分代碼。
圖5 持久層代碼片段Fig.5 Persistence layer code snippet
一般,一個(gè)接口會(huì)調(diào)用業(yè)務(wù)邏輯層的一個(gè)方法,來(lái)實(shí)現(xiàn)該接口的具體業(yè)務(wù)邏輯和功能。如圖6所示,業(yè)務(wù)邏輯層通常需要3個(gè)步驟完成:(1)對(duì)異常機(jī)制的利用;(2)設(shè)計(jì)接口和抽象接口實(shí)現(xiàn)類(lèi);(3)對(duì)編寫(xiě)業(yè)務(wù)層單元測(cè)試。
圖6 業(yè)務(wù)層代碼片段Fig.6 Business layer code snippet
完成了對(duì)持久層和業(yè)務(wù)層的開(kāi)發(fā)后,可以著手編寫(xiě)控制層。在這一層中通過(guò)DTO返回結(jié)構(gòu),可以給用戶(hù)具體的接口與返回報(bào)文了??刂茖悠a片段如圖7所示,同樣需要三個(gè)步驟。
圖7 控制層代碼片段Fig.7 Control layer code snippet
第一步是創(chuàng)建響應(yīng),將狀態(tài)碼、狀態(tài)描述信息、返回?cái)?shù)據(jù)。除異常信息需要我們返回自定義的狀態(tài)碼,狀態(tài)碼為200統(tǒng)一使用默認(rèn)HTTP CODE碼返回給瀏覽器;第二步是依據(jù)當(dāng)前業(yè)務(wù)功能模塊設(shè)計(jì)請(qǐng)求,請(qǐng)求一般包括請(qǐng)求路徑、參數(shù)類(lèi)型和響應(yīng)結(jié)果;第三步是處理請(qǐng)求,在業(yè)務(wù)層中我們處理了來(lái)自持久層的異常,在控制層中我們也應(yīng)當(dāng)處理異常,并且這個(gè)異常時(shí)來(lái)自業(yè)務(wù)層的。控制層會(huì)有非常多的接口返回,這時(shí)候我們也應(yīng)當(dāng)抽離一個(gè)BaseController父類(lèi),在這個(gè)父類(lèi)中統(tǒng)一的處理異常。
至此,我們已經(jīng)完成了一個(gè)功能的設(shè)計(jì),持久層、業(yè)務(wù)層、控制層三者相輔相成。
一個(gè)好的習(xí)慣就是在編寫(xiě)完核心業(yè)務(wù)代碼的時(shí)候每一層都要做單元測(cè)試,借助Junit依賴(lài)完成單元測(cè)試。在Test目錄下編寫(xiě)一個(gè)無(wú)返回值類(lèi)型的方法并使用@Test注解,盡量可以使用斷言用于覆蓋所有的測(cè)試路徑,使每一個(gè)分支都能執(zhí)行。例如,持久層程序?qū)憜卧獪y(cè)試以確保我們的操作已經(jīng)與MySQL數(shù)據(jù)庫(kù)進(jìn)行了交互;業(yè)務(wù)層編寫(xiě)單元測(cè)試為了確保從持久層拿到的數(shù)據(jù)經(jīng)業(yè)務(wù)層處理可以做增刪改查的處理;控制層的單元測(cè)試可以確保返回的結(jié)構(gòu)是符合預(yù)期的。
接口的檢驗(yàn)是尤為重要的,在控制層添加合理的、易于理解的注解,可以減少前后端人員的溝通成本。在pom.xml中引入Swagger依賴(lài),如圖8所示,可以通過(guò)瀏覽器訪問(wèn)自動(dòng)生成的接口文檔,接口規(guī)范盡量使用Restful風(fēng)格,用于減少前后端開(kāi)發(fā)人員的溝通成本。
圖8 Swagger接口文檔Fig.8 Swagger interface documentation
程序設(shè)計(jì)應(yīng)該遵循逐步求精、自頂向下和模塊化的原則??紤]到項(xiàng)目周期比較短,我們團(tuán)隊(duì)在設(shè)計(jì)需求的時(shí)候,并沒(méi)有過(guò)度的設(shè)計(jì),過(guò)度設(shè)計(jì)反而會(huì)使我們?cè)诰幊痰倪^(guò)程中考慮不足。JDK8的新特性通過(guò)函數(shù)式編程創(chuàng)建一個(gè)Stream流,然后使用Filter對(duì)流中元素進(jìn)行過(guò)濾,通過(guò)Map得到需要的元素,使用Collect(Collectors.toList())轉(zhuǎn)化為L(zhǎng)ist集合,最后還是要通過(guò)遞歸找到子菜單[3]。最大的體會(huì)是函數(shù)式編程會(huì)使我們團(tuán)隊(duì)更加專(zhuān)注于業(yè)務(wù)邏輯上的處理,也解決了代碼繁瑣的問(wèn)題和業(yè)務(wù)邏輯間的耦合。整個(gè)項(xiàng)目從0到1的過(guò)程已經(jīng)實(shí)現(xiàn)了,頂崗實(shí)習(xí)平臺(tái)還需在線上運(yùn)營(yíng)一段時(shí)間,我們可以分析大量的日志不斷地修復(fù)Bug、迭代版本才可以實(shí)現(xiàn)從1到n。
引用
[1] [美]克雷格·沃斯.Spring Boot實(shí)戰(zhàn)[M].北京:人民郵電出版社, 2016:3-6.
[2] 王松.Spring Boot+Vue全棧開(kāi)發(fā)實(shí)戰(zhàn)[M].北京:清華大學(xué)出版社, 2018:46-47.
[3] [美]凱S.霍斯特曼.Java核心技術(shù)卷Ⅰ:基礎(chǔ)知識(shí)(原書(shū)第11版)[M]. 北京:機(jī)械工業(yè)出版社,2019:372-373.
數(shù)字技術(shù)與應(yīng)用2022年9期