項(xiàng)目架構(gòu)
項(xiàng)目介紹
教育后臺(tái)管理系統(tǒng)是提供給相關(guān)業(yè)務(wù)人員使用的一個(gè)后臺(tái)管理系統(tǒng),業(yè)務(wù)人員可以在這個(gè)后臺(tái)管理系統(tǒng)中,對(duì)課程信息、講師信息、 學(xué)員信息等數(shù)據(jù)進(jìn)行維護(hù)。
課程管理模塊
課程管理
- 新建課程
- 條件查詢(xún):課程名稱(chēng),狀態(tài)
- 課程信息列表展示:ID,課程名稱(chēng),價(jià)格,排序,狀態(tài)
- 課程狀態(tài)的切換:上架,下架
營(yíng)銷(xiāo)信息 (營(yíng)銷(xiāo)信息其實(shí)就是課程的具體信息)
- 回顯對(duì)應(yīng)課程的詳細(xì)信息
- 修改課程信息,包含了圖片上傳
配置課時(shí)(配置課時(shí)指的就是對(duì)課程內(nèi)容的配置,課程內(nèi)容就包括了章節(jié)信息和課時(shí)信息)
- 添加章節(jié)
- 以樹(shù)形結(jié)構(gòu)的下拉列表方式 展示課程對(duì)應(yīng)的章節(jié)與課時(shí)信息
- 修改章節(jié)
- 章節(jié)章節(jié)狀態(tài)的設(shè)置
前后端分離開(kāi)發(fā)
前后端分離已成為互聯(lián)網(wǎng)項(xiàng)目開(kāi)發(fā)的業(yè)界標(biāo)準(zhǔn)使用方式,將前端和后端的開(kāi)發(fā)進(jìn)行解耦。并且前后端分離會(huì)為以后的大型分布式架構(gòu)、微服務(wù)架構(gòu)、多端化服務(wù)(各種客戶(hù)端,比如瀏覽器、車(chē)載終端、安卓、IOS 等)打下堅(jiān)實(shí)的基礎(chǔ)。
前后端分離的核心思想就是前端HTML頁(yè)面通過(guò)AJAX調(diào)用后端的API接口,并通過(guò)JSON數(shù)據(jù)進(jìn)行交互。
接口文檔
前后端分離開(kāi)發(fā)方式需要由前后端工程師共同定義接口;編寫(xiě)接口文檔之后都根據(jù)這個(gè)接口文檔進(jìn)行開(kāi)發(fā),到項(xiàng)目結(jié)束前都要一直進(jìn)行接口文檔的維護(hù)。
一個(gè)接口的描述至少包括下面幾項(xiàng):
- 名稱(chēng): findCourseList
- 描述: 根據(jù)條件查詢(xún)課程信息
- URL: http://localhost:8080/edu_home/course/
- 請(qǐng)求方式: GET
- 請(qǐng)求參數(shù) methodName:"findCourseList";
- 響應(yīng)結(jié)果
{ "status": "0", "msg": "success"}
前后端耦合的缺陷 (以 JSP 為例)
- UI 出好設(shè)計(jì)圖之后,前端開(kāi)發(fā)工程師只負(fù)責(zé)將設(shè)計(jì)圖切成 HTML,需要由 Java 開(kāi)發(fā)工程師來(lái)將 HTML 套成 JSP 頁(yè)面,修改問(wèn)題的時(shí)候需要雙方協(xié)同開(kāi)發(fā),效率低下。
- JSP 頁(yè)面必須要在支持 Java 的 WEB 服務(wù)器上運(yùn)行(如 Tomcat、Jetty 等),無(wú)法使用 Nginx 等(官方宣稱(chēng)單實(shí)例 HTTP 并發(fā)高達(dá) 5 W),性能提升不上來(lái)。
- 第一次請(qǐng)求 JSP,必須要在 WEB 服務(wù)器中編譯成 Servlet,第一次運(yùn)行會(huì)較慢。 之后的每次請(qǐng)求 JSP 都是訪問(wèn) Servlet 再用輸出流輸出的 HTML 頁(yè)面,效率沒(méi)有直接使用 HTML 高。
前后端分離的優(yōu)勢(shì)
- 前后端分離的模式下,如果發(fā)現(xiàn) Bug,可以快速定位是誰(shuí)的問(wèn)題,不會(huì)出現(xiàn)互相踢皮球的現(xiàn)象
- 前后端分離可以減少后端服務(wù)器的并發(fā)/負(fù)載壓力。除了接口以外的其他所有HTTP請(qǐng)求全部轉(zhuǎn)移到前端 Nginx 上,接口的請(qǐng)求則轉(zhuǎn)發(fā)調(diào)用 Tomcat.
- 前后端分離的模式下,即使后端服務(wù)器暫時(shí)超時(shí)或宕機(jī)了,前端頁(yè)面也會(huì)正常訪問(wèn),只不過(guò)數(shù)據(jù)刷不出來(lái)而已。
- 前后端分離會(huì)更加合理的分配團(tuán)隊(duì)的工作量,減輕后端團(tuán)隊(duì)的工作量,提高了性能和可擴(kuò)展性。
技術(shù)選型
前端技術(shù)選型
Vue.js – 是一套用于構(gòu)建用戶(hù)界面的漸進(jìn)式 JavaScript 框架
Element UI 庫(kù) – 是餓了么前端出品的基于 Vue.js 的后臺(tái)組件庫(kù),方便程序員進(jìn)行頁(yè)面快速布局和構(gòu)建
node.js – 運(yùn)行在服務(wù)端的 JavaScript 運(yùn)行環(huán)境
axios – 對(duì) ajax 的封裝, 簡(jiǎn)單來(lái)說(shuō)就是 ajax 技術(shù)實(shí)現(xiàn)了局部數(shù)據(jù)的刷新,axios 實(shí)現(xiàn)了對(duì) ajax 的封裝
后端技術(shù)選型
Web 層:Servlet 前端控制器,F(xiàn)ilter 過(guò)濾器,BeanUtils 數(shù)據(jù)封裝
Service 層:業(yè)務(wù)邏輯處理
Dao 層:MySQL 數(shù)據(jù)庫(kù),Druid 數(shù)據(jù)庫(kù)連接池,DBUtils 操作數(shù)據(jù)庫(kù)
項(xiàng)目開(kāi)發(fā)環(huán)境
開(kāi)發(fā)工具:后端 IntelliJ IDEA,前端 VS code,數(shù)據(jù)庫(kù) SQLYog
開(kāi)發(fā)環(huán)境:JDK 11,Maven 3.6.3,MySQL 5.7
Maven 項(xiàng)目管理工具
Maven 介紹
Maven 是一個(gè)跨平臺(tái)的項(xiàng)目管理工具。作為 Apache 組織的一個(gè)頗為成功的開(kāi)源項(xiàng)目,其主要服務(wù)于基于 Java 平臺(tái)的項(xiàng)目創(chuàng)建,依賴(lài)管理和項(xiàng)目信息管理。Maven 是 Apache 的頂級(jí)項(xiàng)目,意為“專(zhuān)家,內(nèi)行”,它是一個(gè)項(xiàng)目管理的工具,Maven 自身是純 java 開(kāi)發(fā)的,可以使用 Maven 對(duì) java 項(xiàng)目進(jìn)行構(gòu)建、依賴(lài)管理。
依賴(lài)管理:依賴(lài)指的就是項(xiàng)目中需要使用的第三方 Jar 包, 一個(gè)大一點(diǎn)的工程往往需要幾十上百個(gè) Jar 包,按照之前的方式,每使用一種 Jar 就需要導(dǎo)入到工程中,還要解決各種 Jar 沖突的問(wèn)題;而 Maven 可以對(duì) Jar 包進(jìn)行統(tǒng)一的管理,包括快速引入 Jar 包,以及對(duì)使用的 Jar 包進(jìn)行統(tǒng)一的版本控制。
一鍵構(gòu)建項(xiàng)目:之前創(chuàng)建項(xiàng)目需要確定項(xiàng)目的目錄結(jié)構(gòu),比如 src 存放 Java 源碼,resources 存放配置文件,還要配置環(huán)境比如 JDK 的版本等等,如果有多個(gè)項(xiàng)目就需要每次搞一套配置,十分麻煩;而 Maven 提供了一個(gè)標(biāo)準(zhǔn)化的 Java 項(xiàng)目結(jié)構(gòu),可以通過(guò) Maven 快速創(chuàng)建一個(gè)標(biāo)準(zhǔn)的 Java 項(xiàng)目。
Maven 的使用
下載地址:http://maven.apache.org/download.cgi
Maven 下載后,將 Maven 解壓到一個(gè)沒(méi)有中文沒(méi)有空格的路徑下,解壓后目錄結(jié)構(gòu)如下:
- bin:存放了 maven 的命令
- boot:存放了一些 maven 本身的引導(dǎo)程序,如類(lèi)加載器等
- conf:存放了 maven 的一些配置文件,如 setting.xml 文件
- lib:存放了 maven 本身運(yùn)行所需的一些 jar 包
配置 Maven 環(huán)境變量:配置 MAVEN_HOME ,變量值是 maven 安裝的路徑;將 MAVEN_HOME 添加到 Path 系統(tǒng)變量。
最后通過(guò)命令行運(yùn)行 mvn -v 命令檢查 maven 是否安裝成功。
Maven 倉(cāng)庫(kù)
Maven 中的倉(cāng)庫(kù)是用來(lái)存放 maven 構(gòu)建的項(xiàng)目和各種依賴(lài)的(Jar包)。
倉(cāng)庫(kù)分類(lèi)
- 本地倉(cāng)庫(kù):位于自己計(jì)算機(jī)中的倉(cāng)庫(kù),用來(lái)存儲(chǔ)從遠(yuǎn)程倉(cāng)庫(kù)或中央倉(cāng)庫(kù)下載的插件和 jar 包。
- 遠(yuǎn)程倉(cāng)庫(kù):需要聯(lián)網(wǎng)才可以使用的倉(cāng)庫(kù),阿里提供了一個(gè)免費(fèi)的 maven 遠(yuǎn)程倉(cāng)庫(kù)。
- 中央倉(cāng)庫(kù):在 maven 軟件中內(nèi)置一個(gè)遠(yuǎn)程倉(cāng)庫(kù)地址 http://repo1.maven.org/maven2,它是中央倉(cāng)庫(kù),服務(wù)于整個(gè)互聯(lián)網(wǎng),它是由 Maven 團(tuán)隊(duì)自己維護(hù),里面存儲(chǔ)了非常全的 jar 包,它包含了世界上大部分流行的開(kāi)源項(xiàng)目構(gòu)件。
本地倉(cāng)庫(kù)的配置
Maven 倉(cāng)庫(kù)默認(rèn)是在 C 盤(pán)的 .m2 目錄下,所以這里要重新配置到別的盤(pán)符中。
在 Maven 安裝目錄中,進(jìn)入 conf 文件夾, 可以看到一個(gè) settings.xml 文件;打開(kāi) settings.xml 文件,在 localRepository 標(biāo)簽下配置倉(cāng)庫(kù)目錄。
阿里云遠(yuǎn)程倉(cāng)庫(kù)配置
打開(kāi) settings.xml,找到 <mirrors> 標(biāo)簽,將如下內(nèi)容復(fù)制到 <mirrors> 中即可:
<mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror>
創(chuàng)建 Maven 項(xiàng)目
IDEA 中配置 Maven
打開(kāi) IDEA 創(chuàng)建一個(gè)新的 project,然后選擇 File –> Settings –> 搜素 maven,修改默認(rèn)配置配置。
創(chuàng)建 Maven 工程
在 IDEA 中配置好 maven 后使用 maven 快速的去構(gòu)建一個(gè) Java Web 項(xiàng)目,不選擇 archetype。
Maven目錄說(shuō)明:
src/main/java —— 存放項(xiàng)目的 .java 文件 src/main/resources —— 存放項(xiàng)目資源文件,如數(shù)據(jù)庫(kù)的配置文件 src/test/java —— 存放所有單元測(cè)試 .java 文件,如 JUnit 測(cè)試類(lèi) target —— 項(xiàng)目輸出位置,編譯后的 class 文件會(huì)輸出到此目錄 pom.xml —— maven 項(xiàng)目核心配置文件
Maven 工程改造
當(dāng)前創(chuàng)建的 maven 項(xiàng)目是一個(gè) 普通的 Java 項(xiàng)目,不是 web 項(xiàng)目,所以需要改造。
- 在 main 目錄下創(chuàng)建一個(gè) webapp 文件夾
- 選擇 project Structure —> facets—> 點(diǎn)擊 號(hào)添加 web —> 選擇當(dāng)前工程 hello_maven
- 根據(jù)新建的 webapp 目錄,來(lái)修改 Deployment 和 Resources 的路徑信息
pom.xml 核心配置文件
一個(gè) maven 工程都有一個(gè) pom.xml 文件,通過(guò) pom.xml 文件定義項(xiàng)目的信息、項(xiàng)目依賴(lài)、引入插件等等。
- 此時(shí),在項(xiàng)目中直接創(chuàng)建一個(gè) Servlet,會(huì)出現(xiàn)缺少 jar 包報(bào)錯(cuò);要解決問(wèn)題,就要將 servlet-api-xxx.jar 包放進(jìn)來(lái);而作為 maven 工程應(yīng)當(dāng)添加 servlet 的坐標(biāo),從而導(dǎo)入它的 jar。
- 在 pom.xml 文件中可以引入依賴(lài)包的坐標(biāo)
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>? <groupId>com.renda</groupId> <artifactId>hello_maven</artifactId> <version>1.0-SNAPSHOT</version>? <!-- import package coordinates --> <dependencies> <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> </dependencies></project>
一個(gè) Maven 工程就是由 groupId,artifactId 和 version 作為唯一標(biāo)識(shí);所以在引用其他第三方庫(kù)的時(shí)候,也是通過(guò)這三個(gè)變量確定。
坐標(biāo)的概念:在 maven 中坐標(biāo)就是為了定位一個(gè)唯一確定的 jar 包;maven 擁有大量的構(gòu)建,需要一個(gè)統(tǒng)一規(guī)范來(lái)唯一標(biāo)識(shí)一個(gè)構(gòu)建。
Maven 坐標(biāo)主要組成 – 確定一個(gè) jar 在互聯(lián)網(wǎng)位置:
groupId - 定義當(dāng)前 Maven 組織名稱(chēng),通常是公司名artifactId - 定義實(shí)際項(xiàng)目名稱(chēng)version - 定義當(dāng)前項(xiàng)目的當(dāng)前版本packaging - 打包類(lèi)型:打成 jar 包或者打成 war 包
maven 的依賴(lài)管理,是對(duì)項(xiàng)目所依賴(lài)的 jar 包進(jìn)行統(tǒng)一管理:
dependencies表示依賴(lài)關(guān)系使用 <dependency> 聲明一個(gè)依賴(lài)后,Maven 就會(huì)自動(dòng)下載這個(gè)依賴(lài)包
坐標(biāo)的來(lái)源方式:
- 輸入網(wǎng)址,進(jìn)行查詢(xún):https://mvnrepository.com/
- 使用 IDEA 在 pom.xml 文件中右鍵選擇 Generate –> Dependency –> 搜索輸入名稱(chēng)
添加插件
在 pom.xml 中加入如下配置:
<project ...> ...? <!-- properties 是全局設(shè)置,可以設(shè)置整個(gè) maven 項(xiàng)目的編譯器 JDK 版本 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- 重點(diǎn) --> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties>? <!-- 在 build 中需要指定一下項(xiàng)目的 JDK 編譯版本,maven 默認(rèn)使用 1.5 版本進(jìn)行編譯 --> <!-- 注意 build 與 dependencies 是平級(jí)關(guān)系,標(biāo)簽不要寫(xiě)錯(cuò)位置 --> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <release>11</release> </configuration> </plugin> </plugins> </build></project>
運(yùn)行 Maven 項(xiàng)目
- ServletDemo01
@WebServlet("/demo01")public class ServletDemo01 extends HttpServlet {? @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); }? @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("Hello Maven!"); }}
- index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html> <head> <title>Title</title> </head> <body> <p>This is My First Maven Project</p> </body></html>
- 配置 Tomcat,部署項(xiàng)目。
- 運(yùn)行項(xiàng)目, 默認(rèn)訪問(wèn) index.jsp。
- 訪問(wèn) Servlet:http://localhost:8080/hello_maven/demo01。
Maven 的常用命令
生命周期:使用 maven 完成項(xiàng)目的構(gòu)建,項(xiàng)目構(gòu)建包括:清理、編譯、測(cè)試、部署等過(guò)程。
Maven 通過(guò)執(zhí)行一些簡(jiǎn)單命令即可實(shí)現(xiàn)生命周期的各個(gè)過(guò)程:
- mvn compile – 完成編譯操作 , 執(zhí)行完畢后,會(huì)生成 target 目錄,該目錄中存放了編譯后的字節(jié)碼文件。
- mvn clean – 執(zhí)行完畢后,會(huì)將 target 目錄刪除。
- mvn test – 執(zhí)行完畢后,會(huì)在target目錄中生成三個(gè)文件夾:surefire、surefire-reports(測(cè)試報(bào)告)、test-classes(測(cè)試的字節(jié)碼文件)
- mvn package – 完成打包操作;執(zhí)行完畢后,會(huì)在 target 目錄中生成一個(gè)文件,該文件可能是 jar 或 war。
- mvn install – 將打好的 jar 包安裝到本地倉(cāng)庫(kù)的操作,執(zhí)行完畢后,會(huì)在本地倉(cāng)庫(kù)中出現(xiàn)安裝后的 jar 包,方便其他工程引用。
IDEA 界面左側(cè)有一個(gè) maven 視圖,里面有對(duì)應(yīng)的命令插件,可以執(zhí)行上面表格中的命令。
依賴(lài)范圍介紹
A 依賴(lài) B,需要在 A 的 pom.xml 文件中添加 B 的坐標(biāo),添加坐標(biāo)時(shí)需要指定依賴(lài)范圍:
- compile – 編譯范圍,指 A 在編譯時(shí)依賴(lài) B,此范圍為默認(rèn)依賴(lài)范圍。編譯范圍的依賴(lài)會(huì)用在編譯、測(cè)試、運(yùn)行,由于運(yùn)行時(shí)需要所以編譯范圍的依賴(lài)會(huì)被打包。
- provided – 只有在當(dāng) JDK 或者一個(gè)容器已提供該依賴(lài)之后才使用, provided 依賴(lài)在編譯和測(cè)試時(shí)需要,在運(yùn)行時(shí)不需要,比如:servlet API 被 Tomcat 容器提供。
- runtime – 在運(yùn)行和測(cè)試系統(tǒng)的時(shí)候需要,但在編譯的時(shí)候不需要。比如:JDBC 的驅(qū)動(dòng)包。由于運(yùn)行時(shí)需要所以 runtime 范圍的依賴(lài)會(huì)被打包。
- test – 在編譯和運(yùn)行時(shí)都不需要,它們只有在測(cè)試編譯和測(cè)試運(yùn)行階段可用, 比如:Junit。由于運(yùn)行時(shí)不需要所以 test 范圍依賴(lài)不會(huì)被打包。
- system – 與 provided 類(lèi)似,但是必須顯式的提供一個(gè)對(duì)于本地系統(tǒng)中 JAR 文件的路徑,需要指定 system Path 磁盤(pán)路徑,system 依賴(lài)不推薦使用。
后臺(tái)系統(tǒng)搭建
課程管理模塊功能分析
課程管理:展示課程列表、根據(jù)課程名和狀態(tài)進(jìn)行查詢(xún)、新建課程、課程上架與下架。
營(yíng)銷(xiāo)信息:回顯課程信息、修改課程信息(包含了圖片上傳)。
配置課時(shí)(一個(gè)課程對(duì)應(yīng)多個(gè)章節(jié),一個(gè)章節(jié)有多個(gè)課時(shí)):以樹(shù)形結(jié)構(gòu)的下拉框形式展示課程對(duì)應(yīng)的章節(jié)與課時(shí)信息、添加章節(jié)功能、修改章節(jié)功能、修改章節(jié)狀態(tài)功能。
課程管理模塊表設(shè)計(jì)
一個(gè)課程信息表對(duì)多個(gè)課程章節(jié)表
一個(gè)課程章節(jié)表對(duì)多個(gè)課時(shí)信息表
一個(gè)課時(shí)信息表對(duì)一個(gè)課程媒體表
環(huán)境搭建
使用 Maven 快速構(gòu)建工程。
導(dǎo)入 pom.xml。
導(dǎo)入工具類(lèi)及配置文件。
導(dǎo)入實(shí)體類(lèi)。
在項(xiàng)目中添加 Lombok 依賴(lài) jar,Lombok 常用注解:
- @Getter/@Setter: 作用類(lèi)上,生成所有成員變量的 getter / setter 方法
- @ToString : 作用于類(lèi),覆蓋默認(rèn)的 toString() 方法,可以通過(guò) of 屬性限定顯示某些字段,通過(guò) exclude 屬性排除某些字段
- @AllArgsConstructor:生成全參構(gòu)造器
- @NoArgsConstructor:生成無(wú)參構(gòu)造器
- @Data: 該注解使用在類(lèi)上,該注解會(huì)提供 getter、setter、equals、hashCode、toString 方法。
導(dǎo)入表對(duì)應(yīng)的實(shí)體類(lèi)。
通用 Servlet
每個(gè)模塊下都有很多的功能,比如課程模塊的新建課程,上架課程,下架課程,根據(jù)課程名查詢(xún)等等功能 ,每一個(gè)功能都是一個(gè) Servlet。但是 Servlet 太多了不好管理,而且 Servlet 越多服務(wù)器運(yùn)行就越慢,資源消耗就越多。
Servlet 對(duì)應(yīng)模塊
使用一個(gè) Servlet 對(duì)應(yīng)一個(gè)模塊的方式進(jìn)行開(kāi)發(fā)
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>Title</title></head><body> <a href="${pageContext.request.contextPath}/test?methodName=addCourse">新建課程</a> <a href="${pageContext.request.contextPath}/test?methodName=findByName">根據(jù)課程名查詢(xún)</a> <a href="${pageContext.request.contextPath}/test?methodName=findByStatus">根據(jù)課程狀態(tài)查詢(xún)</a></body></html>
TestServlet
/** * 模擬課程模塊,模塊中有很多功能 * */@WebServlet("/test")public class TestServlet extends HttpServlet { /** * doGet() 方法作為調(diào)度器 控制器,根據(jù)請(qǐng)求的功能不同,調(diào)用對(duì)應(yīng)的方法 * * */ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 獲取要調(diào)用的方法名 String methodName = req.getParameter("methodName"); // 判斷執(zhí)行對(duì)應(yīng)的方法 if("addCourse".equals(methodName)){ addCourse(req,resp); }else if("findByStatus".equals(methodName)){ findByName(req,resp); }else if("findByStatus".equals(methodName)){ findByStatus(req,resp); }else{ System.out.println("訪問(wèn)的功能不存在!"); } }? @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); }?? /** * 模塊對(duì)應(yīng)的功能部分 * */ public void addCourse(HttpServletRequest req, HttpServletResponse resp){ System.out.println("新建課程"); }? public void findByStatus(HttpServletRequest req, HttpServletResponse resp){ System.out.println("根據(jù)狀態(tài)查詢(xún)"); }? public void findByName(HttpServletRequest req, HttpServletResponse resp){ System.out.println("根據(jù)課程名稱(chēng)查詢(xún)"); }}
提高代碼的可維護(hù)行
可以使用反射去對(duì)代碼進(jìn)行優(yōu)化,提升代碼的可維護(hù)性/可擴(kuò)展性
/** * 對(duì)應(yīng)的是課程管理模塊 */@WebServlet("/test")public class TestServlet extends BaseServlet {? /** * 根據(jù)請(qǐng)求功能不同,調(diào)用不同的方法,起到調(diào)度器的作用。 */ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 獲取參數(shù):要訪問(wèn)的方法名 String methodName = req.getParameter("methodName"); if (methodName != null) { // 使用反射方式提升代碼的可維護(hù)性 try { // 獲取字節(jié)碼對(duì)象 Class aClass = this.getClass(); // 根據(jù)傳入的方法名獲取對(duì)應(yīng)的方法對(duì)象 Method method = aClass.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); method.invoke(this, req, resp); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); System.out.println("請(qǐng)求的功能不存在"); } } }?? @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); }? /** * 添加課程 */ public void addCourse(HttpServletRequest req, HttpServletResponse resp) { System.out.println("新建課程"); }? /** * 根據(jù)課程名查詢(xún) */ public void findByName(HttpServletRequest req, HttpServletResponse resp) { System.out.println("根據(jù)課程名查詢(xún)"); }? /** * 根據(jù)課程狀態(tài)查詢(xún) */ public void findByStatus(HttpServletRequest req, HttpServletResponse resp) { System.out.println("根據(jù)課程狀態(tài)查詢(xún)"); }}
抽取通用的 BaseServlet
將反射相關(guān)的代碼抽取到一個(gè)類(lèi)中 BaseServlet,讓 BaseServlet 去繼承 HTTPServlet
BaseServlet
public class BaseServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 獲取參數(shù):要訪問(wèn)的方法名 String methodName = req.getParameter("methodName"); if (methodName != null) { // 使用反射方式提升代碼的可維護(hù)性 try { // 獲取字節(jié)碼對(duì)象 Class aClass = this.getClass(); // 根據(jù)傳入的方法名獲取對(duì)應(yīng)的方法對(duì)象 Method method = aClass.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class); method.invoke(this, req, resp); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); System.out.println("請(qǐng)求的功能不存在"); } } }?? @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); }}
TestServlet 繼承 BaseServlet
@WebServlet("/test")public class TestServlet extends BaseServlet {? /** * 添加課程 */ public void addCourse(HttpServletRequest req, HttpServletResponse resp) { System.out.println("新建課程"); }? /** * 根據(jù)課程名查詢(xún) */ public void findByName(HttpServletRequest req, HttpServletResponse resp) { System.out.println("根據(jù)課程名查詢(xún)"); }? /** * 根據(jù)課程狀態(tài)查詢(xún) */ public void findByStatus(HttpServletRequest req, HttpServletResponse resp) { System.out.println("根據(jù)課程狀態(tài)查詢(xún)"); }?}
JSON
JSON 簡(jiǎn)述
JSON (JavaScript Object Notation) – JavaScript 對(duì)象表示法(JSON 源于 JS)。
- JSON 是一種輕量級(jí)的數(shù)據(jù)交換格式
- JSON 采用完全獨(dú)立于語(yǔ)言的文本格式,不同的編程語(yǔ)言 JSON 數(shù)據(jù)是一致的
- JSON 易于人閱讀和編寫(xiě),也易于機(jī)器解析和生成(一般用于提升網(wǎng)絡(luò)傳輸速率)
對(duì)比 XML 與 JSON
XML – 可擴(kuò)展標(biāo)記語(yǔ)言,是一種用于標(biāo)記電子文件使其具有結(jié)構(gòu)性的標(biāo)記語(yǔ)言。
JSON – 是一種輕量級(jí)的數(shù)據(jù)交換格式。
相同點(diǎn): 它們都可以作為一種數(shù)據(jù)交換格式。
區(qū)別:
- XML 是重量級(jí)的,JSON 是輕量級(jí)的,XML 在傳輸過(guò)程中比較占帶寬,JSON 占帶寬少,易于壓縮。
- XML 和 JSON 都用在項(xiàng)目交互下,XML 多用于做配置文件,JSON 用于數(shù)據(jù)交互
- JSON 獨(dú)立于編程語(yǔ)言存在,任何編程語(yǔ)言都可以去解析 JSON
JSON 語(yǔ)法格式
{ "id" : 1, "name" : "張小明", "age" : 25}
- 由 {} 括起來(lái)
- 數(shù)據(jù)以"鍵 : 值"對(duì)的形式出現(xiàn)(鍵多以字符串形式出現(xiàn);值可取字符串,數(shù)值,或者其他 JSON 對(duì)象)
- 每?jī)蓚€(gè)"鍵 : 值"對(duì)以逗號(hào)分隔(最后一個(gè)"鍵 : 值"對(duì)省略逗號(hào))
- 參數(shù)值如果是 String 類(lèi)型,就必須加引號(hào);如果是數(shù)字類(lèi)型,引號(hào)可加可不加
// 自定義 JSON 數(shù)據(jù)格式var person = {"name":"Mary", "sex":"女", "age":19};console.log(person);?// 數(shù)組格式var persons = {"person" : [{"name":"Mary", "sex":"女", "age":19}, {"name":"jack", "sex":"男", "age":20}]};console.log(persons)?// 集合格式var personList = [{"name":"小紅", "sex":"女", "age":19}, {"name":"小明", "sex":"男", "age":20}];console.log(personList)
JSON 數(shù)據(jù)的轉(zhuǎn)換
前后端的 AJAX 通訊用的都是 JSON 格式,所以在開(kāi)發(fā)的過(guò)程中經(jīng)常會(huì)涉及到 JSON 數(shù)據(jù)的轉(zhuǎn)換
FastJson 介紹
Fastjson 是一個(gè) Java 庫(kù),可以將 Java 對(duì)象轉(zhuǎn)換為 JSON 格式,當(dāng)然它也可以將 JSON 字符串轉(zhuǎn)換為 Java 對(duì)象。
FastJson 特點(diǎn)如下:
- 能夠支持將 java bean 序列化成 JSON 字符串,也能夠?qū)?JSON 字符串反序列化成 Java bean
- 速度快
- 無(wú)其他包的依賴(lài),使用比較方便
FastJson 的使用
在 Maven 項(xiàng)目中使用 FastJson 庫(kù),需要提前在 Maven 的配置文件中添加此 FastJson 包的依賴(lài)
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.3</version></dependency>?<dependency> <groupId>com.colobu</groupId> <artifactId>fastjson-jaxrs-json-provider</artifactId> <version>0.3.1</version></dependency>
將 Java 對(duì)象轉(zhuǎn)換為 JSON 格式
定義一個(gè)名為 Person 的 JavaBean 類(lèi)
public class Person { private String username;? private int age;? private String birthday;? // getter and setter ...}
可以使用 JSON.toJSONString() 將 Java 對(duì)象轉(zhuǎn)換換為 JSON 對(duì)象
public class TestFastJson {? /** * Java 對(duì)象轉(zhuǎn)換為 Json */ @Test public void javaBeanToJSON() { // 創(chuàng)建 Person 對(duì)象 Person person = new Person("小明", 23, DateUtils.getDateFormat());? // 轉(zhuǎn)換為 JSON 數(shù)據(jù) String jsonString = JSON.toJSONString(person); System.out.println(jsonString); }? /** * Java 中的集合轉(zhuǎn)換為 JSON */ @Test public void listToJSON() { // 創(chuàng)建 Person 對(duì)象集 Person person1 = new Person("小明", 21, DateUtils.getDateFormat()); Person person2 = new Person("小紅", 22, DateUtils.getDateFormat()); Person person3 = new Person("小張", 23, DateUtils.getDateFormat()); List<Person> personList = new ArrayList<>(); Collections.addAll(personList, person1, person2, person3);? String jsonString = JSON.toJSONString(personList); System.out.println(jsonString); }}
Fastjson 中的 @JSONField 注解
@Data@AllArgsConstructor@NoArgsConstructorpublic class Person { // 可以通過(guò) name 來(lái)指定輸出的 JSON 名稱(chēng) @JSONField(name = "USERNAME", ordinal = 1) private String username;? // 可以使用 ordinal 指定 JSON 的字段順序 @JSONField(name = "AGE", ordinal = 2) private int age;? // 使用 serialize 指定是否進(jìn)行序列化 @JSONField(ordinal = 3, serialize = true) private String birthday;}
將 JSON 字符串轉(zhuǎn)換為 Java 對(duì)象
/** * JSON 轉(zhuǎn)換為對(duì)象 */@Testpublic void JSONtoJavaBean() { String json = "{"USERNAME":"小明","AGE":23,"birthday":"2020-08-22 23:15:52"}";? Person person = JSON.parseObject(json, Person.class); System.out.println(person);}?/** * JSON 轉(zhuǎn)換為集合 */@Testpublic void JSONtoList() { String json = "[{"USERNAME":"小明","AGE":21,"birthday":"2020-08-22 23:17:34"},{"USERNAME":"小紅","AGE":22,"birthday":"2020-08-22 23:17:34"},{"USERNAME":"小張","AGE":23,"birthday":"2020-08-22 23:17:34"}]n";? List<Person> personList = JSON.parseArray(json, Person.class); System.out.println(personList);}
想了解更多,歡迎關(guān)注我的微信公眾號(hào):Renda_Zhang
版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶(hù)自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請(qǐng)發(fā)送郵件至 舉報(bào),一經(jīng)查實(shí),本站將立刻刪除。