本系列文章將整理到我在GitHub上的《Java面試指南》倉庫,更多精彩內(nèi)容請到我的倉庫里查看
喜歡的話麻煩點下Star哈
文章首發(fā)于我的個人博客:
本文是微信公眾號【Java技術(shù)江湖】的《走進(jìn)JavaWeb技術(shù)世界》其中一篇越平,本文部分內(nèi)容來源于網(wǎng)絡(luò)捐韩,為了把本文主題講得清晰透徹,也整合了很多我認(rèn)為不錯的技術(shù)博客內(nèi)容,引用其中了一些比較好的博客文章风响,如有侵權(quán)嗜浮,請聯(lián)系作者羡亩。
該系列博文會告訴你如何從入門到進(jìn)階,從servlet到框架周伦,從ssm再到SpringBoot夕春,一步步地學(xué)習(xí)JavaWeb基礎(chǔ)知識,并上手進(jìn)行實戰(zhàn)专挪,接著了解JavaWeb項目中經(jīng)常要使用的技術(shù)和組件及志,包括日志組件片排、Maven、Junit速侈,等等內(nèi)容率寡,以便讓你更完整地了解整個Java Web技術(shù)體系,形成自己的知識框架倚搬。為了更好地總結(jié)和檢驗?zāi)愕膶W(xué)習(xí)成果冶共,本系列文章也會提供每個知識點對應(yīng)的面試題以及參考答案。
如果對本系列文章有什么建議每界,或者是有什么疑問的話捅僵,也可以關(guān)注公眾號【Java技術(shù)江湖】聯(lián)系作者,歡迎你參與本系列博文的創(chuàng)作和修訂眨层。
前言
學(xué)習(xí)一個新東西前庙楚,如果能對他有一個比較直觀的印象與定位,那么接下來的學(xué)習(xí)過程就會順暢很多趴樱。所以本文主要是我對Mybatis的一個簡單入門性的總結(jié)介紹(前提還是需要些必要的概念認(rèn)知)馒闷。
PS:文末有參考列表
Mybatis是什么
Mybatis是一個持久層框架,用于數(shù)據(jù)的持久化叁征。主要表現(xiàn)為將SQL與POJO進(jìn)行一個映射纳账,將SQL從代碼中解耦∞嗵郏基本概念如圖:
使用時疏虫,以User為例,UserMapper定義了findById
接口帅涂,該接口返回一個User對象议薪,接口的實現(xiàn)為一個xml配置文件。該xml文件中定義對應(yīng)接口中的實現(xiàn)所需要的SQL媳友。從而達(dá)到將SQL與代碼解耦的目標(biāo)斯议。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.UserMapper">
<select id="findById" parameterType="int" resultType="User">
select user_id id,user_name userName,user_age age from t_user where user_id=#{id}
</select>
</mapper>
MyBatis 是Apache的一個Java開源項目,是一款優(yōu)秀的持久層框架醇锚,它支持定制化 SQL哼御、存儲過程以及高級映射。Mybatis可以將Sql語句配置在XML文件中焊唬,避免將Sql語句硬編碼在Java類中恋昼。
特點
1.Mybatis通過參數(shù)映射方式,可以將參數(shù)靈活的配置在SQL語句中的配置文件中赶促,避免在Java類中配置參數(shù)(JDBC)
2.Mybatis通過輸出映射機(jī)制液肌,將結(jié)果集的檢索自動映射成相應(yīng)的Java對象,避免對結(jié)果集手工檢索(JDBC)
3.Mybatis可以通過Xml配置文件對數(shù)據(jù)庫連接進(jìn)行管理
核心類介紹
1.SqlSessionaFactoryBuilder :該類主要用于創(chuàng)建 SqlSessionFactory, 這個類可以被實例化鸥滨、使用和丟棄嗦哆,一旦創(chuàng)建了 SqlSessionFactory谤祖,就不再需要它了。 因此 SqlSessionFactoryBuilder 實例的最佳作用域是方法作用域(也就是局部方法變量)老速。
2.SqlSessionFactory :該類的作用了創(chuàng)建 SqlSession, 從名字上我們也能看出, 該類使用了工廠模式, 每次應(yīng)用程序訪問數(shù)據(jù)庫, 我們就要通過 SqlSessionFactory 創(chuàng)建 SqlSession, 所以 SqlSessionFactory 和整個 Mybatis 的生命周期是相同的. 這也告訴我們不能創(chuàng)建多個同一個數(shù)據(jù)的 SqlSessionFactory, 如果創(chuàng)建多個, 會消耗盡數(shù)據(jù)庫的連接資源, 導(dǎo)致服務(wù)器夯機(jī). 應(yīng)當(dāng)使用單例模式. 避免過多的連接被消耗, 也方便管理粥喜。
3.SqlSession :SqlSession 相當(dāng)于一個會話, 每次訪問數(shù)據(jù)庫都需要這樣一個會話, 大家可能會想起了 JDBC 中的 Connection, 很類似, 但還是有區(qū)別的, 何況現(xiàn)在幾乎所有的連接都是使用的連接池技術(shù), 用完后直接歸還而不會像 Session 一樣銷毀. 注意: 他是一個線程不安全的對象, 在設(shè)計多線程的時候我們需要特別的當(dāng)心, 操作數(shù)據(jù)庫需要注意其隔離級別, 數(shù)據(jù)庫鎖等高級特性, 此外, 每次創(chuàng)建的 SqlSession 都必須及時關(guān)閉它, 它長期存在就會使數(shù)據(jù)庫連接池的活動資源減少, 對系統(tǒng)性能的影響很大, 我們一般在 finally 塊中將其關(guān)閉. 還有, SqlSession 存活于一個應(yīng)用的請求和操作, 可以執(zhí)行多條 Sql, 保證事務(wù)的一致性。SqlSession在執(zhí)行過程中橘券,有包含了幾大對象:
3.1.Executor :執(zhí)行器额湘,由它調(diào)度 StatementHandler、ParameterHandler旁舰、ResultSetHandler 等來執(zhí)行對應(yīng)的 SQL锋华。其中 StatementHandler 是最重要的。
3.2.StatementHandler :作用是使用數(shù)據(jù)庫的 Statement(PreparedStatement)執(zhí)行操作箭窜,它是四大對象的核心供置,起到承上啟下的作用,許多重要的插件都是通過攔截它來實現(xiàn)的绽快。
3.3.ParamentHandler :用來處理 SQL 參數(shù)的。
3.4.ResultSetHandler :進(jìn)行數(shù)據(jù)集的封裝返回處理的紧阔。
4.Mapper :映射器是一些由你創(chuàng)建的坊罢、綁定你映射的語句的接口。映射器接口的實例是從 SqlSession 中獲得的, 他的作用是發(fā)送 SQL, 然后返回我們需要的結(jié)果. 或者執(zhí)行 SQL 從而更改數(shù)據(jù)庫的數(shù)據(jù), 因此它應(yīng)該在 SqlSession 的事務(wù)方法之內(nèi), 在 Spring 管理的 Bean 中, Mapper 是單例的擅耽。
功能架構(gòu):我們把Mybatis的功能架構(gòu)分為三層
(1)API接口層:提供給外部使用的接口API活孩,開發(fā)人員通過這些本地API來操縱數(shù)據(jù)庫。接口層一接收到調(diào)用請求就會調(diào)用數(shù)據(jù)處理層來完成具體的數(shù)據(jù)處理乖仇。
(2)數(shù)據(jù)處理層:負(fù)責(zé)具體的SQL查找憾儒、SQL解析、SQL執(zhí)行和執(zhí)行結(jié)果映射處理等乃沙。它主要的目的是根據(jù)調(diào)用的請求完成一次數(shù)據(jù)庫操作起趾。
(3)基礎(chǔ)支撐層:負(fù)責(zé)最基礎(chǔ)的功能支撐,包括連接管理警儒、事務(wù)管理训裆、配置加載和緩存處理,這些都是共用的東西蜀铲,將他們抽取出來作為最基礎(chǔ)的組件边琉。為上層的數(shù)據(jù)處理層提供最基礎(chǔ)的支撐。
框架結(jié)構(gòu):
(1)加載配置:配置來源于兩個地方记劝,一處是配置文件变姨,一處是Java代碼的注解,將SQL的配置信息加載成為一個個MappedStatement對象(包括了傳入?yún)?shù)映射配置厌丑、執(zhí)行的SQL語句定欧、結(jié)果映射配置)渔呵,存儲在內(nèi)存中。
(2)SQL解析:當(dāng)API接口層接收到調(diào)用請求時忧额,會接收到傳入SQL的ID和傳入對象(可以是Map厘肮、JavaBean或者基本數(shù)據(jù)類型),Mybatis會根據(jù)SQL的ID找到對應(yīng)的MappedStatement睦番,然后根據(jù)傳入?yún)?shù)對象對MappedStatement進(jìn)行解析类茂,解析后可以得到最終要執(zhí)行的SQL語句和參數(shù)。
(3)SQL執(zhí)行:將最終得到的SQL和參數(shù)拿到數(shù)據(jù)庫進(jìn)行執(zhí)行托嚣,得到操作數(shù)據(jù)庫的結(jié)果巩检。
(4)結(jié)果映射:將操作數(shù)據(jù)庫的結(jié)果按照映射的配置進(jìn)行轉(zhuǎn)換,可以轉(zhuǎn)換成HashMap示启、JavaBean或者基本數(shù)據(jù)類型兢哭,并將最終結(jié)果返回。
執(zhí)行流程:
1.獲取SqlsessionFactory:根據(jù)配置文件(全局夫嗓、sql映射)初始化configuration對象迟螺,
2.獲取sqlSession:創(chuàng)建一個DefaultSqlSession對象,包含Configuration及Executor(根據(jù)全局配置文件中defaultExecutorType創(chuàng)建對應(yīng)的Executor)
3.獲取接口代理對象MapperProxy:DefaultSqlSession.getMapper拿到Mapper接口對應(yīng)的MapperProxy
4.執(zhí)行增刪改查
1舍咖、調(diào)用DefaultSqlSession增刪改查
2矩父、創(chuàng)建StatementHandler (同時創(chuàng)建ParameterHandler,ResultSetHandler)
3、調(diào)用StatementHandler預(yù)編譯參數(shù)以及設(shè)置參數(shù)值排霉,使用ParameterHandler給sql設(shè)置參數(shù)
4窍株、調(diào)用StatementHandler增刪改查
5、ResultSetHandler封裝結(jié)果
與Hibernate的異同
Mybatis開始逐漸流行起來攻柠,必然有其原因球订,簡單了解了一下它與同為持久層框架的Hibernate的異同。
- 映射模式
從上面的簡單概念可以知道Mybatis實際上著力點在POJO與SQL的映射瑰钮。而Hibernate則主要是POJO與數(shù)據(jù)庫表的對象關(guān)系映射冒滩。前者掌控力度更細(xì),代碼量會相對多一點飞涂,后者靈活性則差一點旦部,更為自動化一些,與PHP里的Eloquent
屬于同類型较店。 - 性能
Mybatis基于原生JDBC士八,相比于對JDBC進(jìn)行二次封裝的Hibernate性能會更好一點。 - 開發(fā)與維護(hù)
Hibernate配置好實體類后梁呈,使用起來是比較簡潔婚度,舒服的,但是前期學(xué)習(xí)曲線比較陡,后期調(diào)優(yōu)比較麻煩蝗茁。Mybatis對SQL掌控的顆粒更細(xì)一點醋虏,相比較而言看上去簡陋些。由于直接映射SQL哮翘,遷移性是個問題颈嚼。
參考文章
https://segmentfault.com/a/1190000009707894
https://www.cnblogs.com/hysum/p/7100874.html
http://c.biancheng.net/view/939.html
https://blog.csdn.net/android_hl/article/details/53228348
微信公眾號
個人公眾號:黃小斜
黃小斜是跨考軟件工程的 985 碩士,自學(xué) Java 兩年饭寺,拿到了 BAT 等近十家大廠 offer阻课,從技術(shù)小白成長為阿里工程師。
作者專注于 JAVA 后端技術(shù)棧艰匙,熱衷于分享程序員干貨限煞、學(xué)習(xí)經(jīng)驗、求職心得和程序人生员凝,目前黃小斜的CSDN博客有百萬+訪問量署驻,知乎粉絲2W+,全網(wǎng)已有10W+讀者健霹。
黃小斜是一個斜杠青年旺上,堅持學(xué)習(xí)和寫作,相信終身學(xué)習(xí)的力量糖埋,希望和更多的程序員交朋友抚官,一起進(jìn)步和成長!
原創(chuàng)電子書:
關(guān)注公眾號【黃小斜】后回復(fù)【原創(chuàng)電子書】即可領(lǐng)取我原創(chuàng)的電子書《菜鳥程序員修煉手冊:從技術(shù)小白到阿里巴巴Java工程師》
程序員3T技術(shù)學(xué)習(xí)資源: 一些程序員學(xué)習(xí)技術(shù)的資源大禮包阶捆,關(guān)注公眾號后,后臺回復(fù)關(guān)鍵字 “資料” 即可免費無套路獲取钦听。
考研復(fù)習(xí)資料:
計算機(jī)考研大禮包洒试,都是我自己考研復(fù)習(xí)時用的一些復(fù)習(xí)資料,包括公共課和專業(yè)的復(fù)習(xí)視頻,這里也推薦給大家朴上,關(guān)注公眾號后垒棋,后臺回復(fù)關(guān)鍵字 “考研” 即可免費獲取。
mybatis新手上路
MyBatis簡介
Mybatis是Apache的一個Java開源項目痪宰,是一個支持動態(tài)Sql語句的持久層框架叼架。Mybatis可以將Sql語句配置在XML文件中,避免將Sql語句硬編碼在Java類中衣撬。與JDBC相比:
- Mybatis通過參數(shù)映射方式乖订,可以將參數(shù)靈活的配置在SQL語句中的配置文件中,避免在Java類中配置參數(shù)(JDBC)
- Mybatis通過輸出映射機(jī)制具练,將結(jié)果集的檢索自動映射成相應(yīng)的Java對象乍构,避免對結(jié)果集手工檢索(JDBC)
- Mybatis可以通過Xml配置文件對數(shù)據(jù)庫連接進(jìn)行管理。
MyBatis整體架構(gòu)及運行流程
Mybatis整體構(gòu)造由 數(shù)據(jù)源配置文件扛点、Sql映射文件哥遮、會話工廠岂丘、會話、執(zhí)行器和底層封裝對象組成眠饮。
1.數(shù)據(jù)源配置文件
通過配置的方式將數(shù)據(jù)庫的配置信息從應(yīng)用程序中獨立出來奥帘,由獨立的模塊管理和配置。Mybatis的數(shù)據(jù)源配置文件包含數(shù)據(jù)庫驅(qū)動仪召、數(shù)據(jù)庫連接地址寨蹋、用戶名密碼、事務(wù)管理等返咱,還可以配置連接池的連接數(shù)钥庇、空閑時間等。
一個SqlMapConfig.xml基本的配置信息如下:
<pre><configuration>
<properties resource="db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="{jdbc.url}"></property>
<property name="username" value="{jdbc.password}" />
</dataSource>
</environment>
</environments>
</configuration></pre>
2.Sql映射文件
Mybatis中所有數(shù)據(jù)庫的操作都會基于該映射文件和配置的sql語句咖摹,在這個配置文件中可以配置任何類型的sql語句评姨。框架會根據(jù)配置文件中的參數(shù)配置萤晴,完成對sql語句以及輸入輸出參數(shù)的映射配置吐句。
Mapper.xml配置文件大致如下:
<pre><!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sl.dao.ProductDao">
<select id="selectProductById" resultType="com.sl.po.Product" parameterType="int">
select * from products where id = #{id} </select>
</mapper></pre>
3.會話工廠與會話
Mybatis中會話工廠SqlSessionFactory類可以通過加載資源文件,讀取數(shù)據(jù)源配置SqlMapConfig.xml信息店读,從而產(chǎn)生一種可以與數(shù)據(jù)庫交互的會話實例SqlSession嗦枢,會話實例SqlSession根據(jù)Mapper.xml文件中配置的sql,對數(shù)據(jù)庫進(jìn)行操作。
4.運行流程
會話工廠SqlSessionFactory通過加載資源文件獲取SqlMapConfig.xml配置文件信息屯断,然后生成可以與數(shù)據(jù)庫交互的會話實例SqlSession文虏。
會話實例可以根據(jù)Mapper配置文件中的Sql配置去執(zhí)行相應(yīng)的增刪改查操作。
在SqlSession會話實例內(nèi)部殖演,通過執(zhí)行器Executor對數(shù)據(jù)庫進(jìn)行操作氧秘,Executor依靠封裝對象Mappered Statement,它分裝了從mapper.xml文件中讀取的信息(sql語句趴久,參數(shù)丸相,結(jié)果集類型)。
Mybatis通過執(zhí)行器與Mappered Statement的結(jié)合實現(xiàn)與數(shù)據(jù)庫的交互彼棍。
執(zhí)行流程圖:
測試工程搭建
- 新建maven工程
2. 添加依賴pom.xml
<pre><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.sl</groupId>
<artifactId>mybatis-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<junit.version>4.12</junit.version>
<mybatis.version>3.4.1</mybatis.version>
<mysql.version>5.1.32</mysql.version>
<log4j.version>1.2.17</log4j.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>{mybatis.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>{log4j.version}</version>
</dependency>
</dependencies>
</project></pre>
3.編寫數(shù)據(jù)源配置文件SqlMapConfig.xml
<pre><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="{jdbc.url}"></property>
<property name="username" value="{jdbc.password}" />
</dataSource>
</environment>
</environments>
<!—申明mapper文件 -->
<mappers>
<mapper resource="mapper/productMapper.xml"></mapper>
</mappers>
</configuration></pre>
4.編寫SQL映射配置文件productMapper.xml
<pre><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sl.mapper.ProductMapper">
<select id="selectAllProduct" resultType="com.sl.po.Product"> select * from products </select>
</mapper></pre>
5.編寫測試代碼TestClient.java
<pre>//使用productMapper.xml配置文件
public class TestClient { //定義會話SqlSession
SqlSession session =null;
@Before public void init() throws IOException { //定義mabatis全局配置文件
String resource = "SqlMapConfig.xml"; //加載mybatis全局配置文件 //InputStream inputStream = TestClient.class.getClassLoader().getResourceAsStream(resource);
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream); //根據(jù)sqlSessionFactory產(chǎn)生會話sqlsession
session = factory.openSession();
} //查詢所有user表所有數(shù)據(jù)
@Test public void testSelectAllUser() {
String statement = "com.sl.mapper.ProductMapper.selectAllProduct";
List<Product> listProduct =session.selectList(statement); for(Product product:listProduct)
{
System.out.println(product);
} //關(guān)閉會話
session.close();
}
}</pre>
<pre>public class Product { private int Id; private String Name; private String Description; private BigDecimal UnitPrice; private String ImageUrl; private Boolean IsNew; public int getId() { return Id;
} public void setId(int id) { this.Id = id;
} public String getName() { return Name;
} public void setName(String name) { this.Name = name;
} public String getDescription() { return Description;
} public void setDescription(String description) { this.Description = description;
} public BigDecimal getUnitPrice() { return UnitPrice;
} public void setUnitPrice(BigDecimal unitprice) { this.UnitPrice = unitprice;
} public String getImageUrl() { return Name;
} public void setImageUrl(String imageurl) { this.ImageUrl = imageurl;
} public boolean getIsNew() { return IsNew;
} public void setIsNew(boolean isnew) { this.IsNew = isnew;
}
@Override public String toString() { return "Product [id=" + Id + ", Name=" + Name + ", Description=" + Description + ", UnitPrice=" + UnitPrice + ", ImageUrl=" + ImageUrl + ", IsNew=" + IsNew+ "]";
}
}</pre>
6.運行測試用例
微信公眾號
個人公眾號:程序員黃小斜
?
黃小斜是 985 碩士灭忠,阿里巴巴Java工程師,在自學(xué)編程座硕、技術(shù)求職弛作、Java學(xué)習(xí)等方面有豐富經(jīng)驗和獨到見解,希望幫助到更多想要從事互聯(lián)網(wǎng)行業(yè)的程序員們华匾。
?
作者專注于 JAVA 后端技術(shù)棧缆蝉,熱衷于分享程序員干貨、學(xué)習(xí)經(jīng)驗、求職心得刊头,以及自學(xué)編程和Java技術(shù)棧的相關(guān)干貨黍瞧。
?
黃小斜是一個斜杠青年,堅持學(xué)習(xí)和寫作原杂,相信終身學(xué)習(xí)的力量印颤,希望和更多的程序員交朋友,一起進(jìn)步和成長穿肄!
原創(chuàng)電子書:
關(guān)注微信公眾號【程序員黃小斜】后回復(fù)【原創(chuàng)電子書】即可領(lǐng)取我原創(chuàng)的電子書《菜鳥程序員修煉手冊:從技術(shù)小白到阿里巴巴Java工程師》這份電子書總結(jié)了我2年的Java學(xué)習(xí)之路年局,包括學(xué)習(xí)方法、技術(shù)總結(jié)咸产、求職經(jīng)驗和面試技巧等內(nèi)容矢否,已經(jīng)幫助很多的程序員拿到了心儀的offer!
程序員3T技術(shù)學(xué)習(xí)資源: 一些程序員學(xué)習(xí)技術(shù)的資源大禮包脑溢,關(guān)注公眾號后僵朗,后臺回復(fù)關(guān)鍵字 “資料” 即可免費無套路獲取,包括Java屑彻、python验庙、C++、大數(shù)據(jù)社牲、機(jī)器學(xué)習(xí)粪薛、前端、移動端等方向的技術(shù)資料搏恤。
技術(shù)公眾號:Java技術(shù)江湖
如果大家想要實時關(guān)注我更新的文章以及分享的干貨的話违寿,可以關(guān)注我的微信公眾號【Java技術(shù)江湖】
這是一位阿里 Java 工程師的技術(shù)小站。作者黃小斜熟空,專注 Java 相關(guān)技術(shù):SSM陨界、SpringBoot、MySQL痛阻、分布式、中間件腮敌、集群阱当、Linux、網(wǎng)絡(luò)糜工、多線程弊添,偶爾講點Docker、ELK捌木,同時也分享技術(shù)干貨和學(xué)習(xí)經(jīng)驗油坝,致力于Java全棧開發(fā)!
Java工程師必備學(xué)習(xí)資源:
關(guān)注公眾號后回復(fù)”Java“即可領(lǐng)取 Java基礎(chǔ)、進(jìn)階澈圈、項目和架構(gòu)師等免費學(xué)習(xí)資料彬檀,更有數(shù)據(jù)庫、分布式瞬女、微服務(wù)等熱門技術(shù)學(xué)習(xí)視頻窍帝,內(nèi)容豐富,兼顧原理和實踐诽偷,另外也將贈送作者原創(chuàng)的Java學(xué)習(xí)指南坤学、Java程序員面試指南等干貨資源
?