歡迎光臨
每天分享高質量文章

Java後端1年經驗和技術總結

作者:木公松

https://www.cnblogs.com/sjlian/p/7137459.html

1.引言

畢業已經一年有餘,這一年裡特別感謝技術管理人員的器重,以及同事的幫忙,學到了不少東西。這一年裡走過一些彎路,也碰到一些難題,也受到過做為一名開發卻經常為系統維護和釋出當救火隊員的苦惱。遂決定梳理一下自己所學的東西,為大家分享一下。

經過一年意識到以前也有很多認識誤區,比如:

偏愛收集,經常收集各種資料影片塞滿一個個硬碟,然後心滿意足的看著容量不行動。

不重基礎,總覺得很多基礎東西不需要再看了,其實不懂的地方很多,計算機程式方面任何一個結果都必有原因,不要只會用不知道原理,那是加工廠出來的。現在ide檢視程式碼那麼方便,ctrl+點選就進入了JDK檢視實現細節。

好高騖遠,在計算機基礎不牢固的情況下,總想著要做架構,弄分散式,搞大資料之類。

不重視效能,只求能實現功能,sql查詢是不是可以最佳化,是否有演演算法妙用,大物件是否要清除。

不重視擴充套件性,模組之間緊密耦合,常用方法不提取成工具類,呼叫關係混亂等問題。

……

本文重點不在這些,故只列舉了一小部分,下麵進入正題。

2.語法基礎

2.1 Java類初始化順序

這是所有情況的類初始化順序,如果實際類中沒有定義則跳過:父類靜態變數——父類靜態程式碼塊——子類靜態程式碼塊——父類非靜態變數——父類非靜態程式碼塊——父類建構式——子類非靜態變數——子類非靜態程式碼塊——子類建構式

2.2 值傳遞和取用傳遞

可能很多人對此不屑一顧,心想老子都工作一年了,對這些還不熟悉嗎?但實際情況並非這樣,JDK中東西全部熟悉了嗎?以一個最簡單的例子開始,你覺得下圖中程式碼執行完之後fatherList中的元素是什麼?

這是一個最基礎的值傳遞和取用傳遞的例子,你覺得好簡單,已經想躍躍欲試的挑戰了,那麼請看下麵的,StringBuffer很好理解,但是當你執行一遍之後發現是不是和預想中的輸出不一樣呢?String不是取用型別嗎,怎麼會這樣呢?如果你無法理解,那麼請看下String的實現原始碼,瞭解下其在記憶體中分配的實現原理。

2.3 集合的使用

這部分幾乎每個人都會用到,而且大家還都不陌生。下圖來源於網際網路,供大家複習一下。但是利用集合的特性進行巧妙的組合運用能解決最佳化很多複雜問題。Set不可重覆性,List的順序性,Map的鍵值對,SortSet/SortMap的有序性,我在工作中有很多複雜的業務都巧妙的使用了這些,涉及到公司保密資訊,我就不貼出程式碼了。工作越久越發現這些和越巧妙。

2.4 異常處理
  1. 看著try、catch、finally非常容易,如果和事務傳播結合在一起,就會變得極其複雜。

  2. finally不一定必須執行,return在catch/finally中處理情況(建議親自操刀試一下)。

  3. catch中可以繼續拋自定義異常(並把異常一步步傳遞到控制層,利用切麵抓取封裝異常,傳回給呼叫者)。

2.5 面向物件思想

一提起面向物件,大家都知道抽象、封裝、繼承、和多型。但是實際工作經驗中又知道多少呢,對於專案中如何巧用估計更不要提了。

共性的機會每個都需要用的建立基類,如每個控制層方法可能要透過security獲取一個登入使用者id,用於根據不同的使用者操作不同的資料,可以抽象出一個應用層基類,實現獲取id的protect方法。同理DAO層可以利用泛型提取出一個包含增刪改查的基類。

多型的Override:基類的取用變數不僅可以指向基類的實體物件,也可以指向其子類的實體物件,如果指向子類的實體物件,其呼叫的方法應該是正在執行的那個物件的方法。在策略樣式中使用很普遍。

提到面向物件,就不可避免的要說設計樣式,在工作中,一個技術大牛寫的一個類似策略樣式(更複雜一點),十分巧妙的解決了各種業務同一個方法,並且實現了訂單、工單、業務的解耦,看得我是非常佩服。我想很多面試中都會問道單例樣式吧,還沒有理解的建議去看一看。

3.多執行緒

3.1 執行緒安全

這個是老生常談的問題了,但是確實是問題和bug高發區。執行緒同步問題不需要單獨寫了,想必大家都清楚,不太熟悉的建議百度一下。

3.1.1 執行緒安全問題

  1. 程式碼中如果有同步操作,共享變數要特別註意(這個一般都能意識到)

  2. 多個操作能修改資料表中同一條資料的。(這個容易被忽略,業務A可能操作表a,業務B也可以操作表a,業務A、B即使在不同的模組和方法中,也會引起執行緒安全問題。例如如果一個人訪問業務A介面,另一個人訪問業務B介面,在web中每個業務請求都是會有單獨的一個執行緒進行處理的,就會出現執行緒安全問題)。

  3. 不安全的型別使用,例如StringBuffer、StringBuild,HashTable、HashMap等。在工作中我就遇到過有人在for迴圈進行list的remove,雖然編譯器不報錯,程式可以執行,但是結果卻可想而知。

  4. Spring的bean預設是單例的,如果有類變數就要特別小心了(一般情況下是沒人在控制層、業務層、DAO層等用類變數的,用的話建議是final型別,例如日誌log,gson等)。

  5. 多個系統共享資料庫情況,這個其實和分散式系統類似

使用者重覆提交問題(即使程式碼中從資料庫讀取是否存在進行限制不能解決問題)

3.1.2 執行緒安全解決

在需要同步的地方採用安全的型別。

JDK鎖機制,lock、tryLock,synchronized,wait、notify、notifyAll等

Concurrent併發工具包,在處理一些問題上,誰用誰知道。強烈建議檢視原始碼!

資料表加鎖。(除非某個表的訪問頻率極低,否則不建議使用)

涉及分散式的,採用中介軟體技術例如zookeeper等解決。

3.2 非同步

非同步使用場景不影響主執行緒,且響應較慢的業務。例如IO操作,第三方服務(簡訊驗證碼、app推送、雲儲存上傳等)。

如果非同步任務很多,就需要使用任務佇列了,任務佇列可以在程式碼級別實現,也可以利用redis(優勢太明顯了)。

3.3 多執行緒通訊

這方面文章非常多,這裡不在詳述。

  1. 共享變數方式(共享檔案、全域性變數,訊號量機制等)

  2. 訊息佇列方式

  3. 忙等,鎖機制

3.4多執行緒實現
  1. 整合Thread類,重寫(這裡的重寫指的是override)run方法,呼叫start方法執行。

  2. 實現Runable介面,實現run方法,以Runable實體建立thread物件。

  3. 實現Callable介面,實現call方法,FutureTask包裝callable介面,FutureTask物件建立thread物件,常用語非同步操作,建議使用匿名內部類,方便閱讀和使用。

額外需要說明的是:

  1. 理解thread的join方法;

  2. 不要認為volitate是執行緒安全的(不明白原因的建議去看jvm執行時刻記憶體分配策略);

  3. sleep時間片結束後並不保證立馬獲取cpu。

  4. ThreadLocal能夠為每一個執行緒維護變數副本,常用於在多執行緒中用空間換時間。

4. 開源框架

4.1 Hibernate、Mybatis

相信每一個java程式員對這些都不陌生,這裡不再詳述。

需要說明的主要以下幾點:

  1. hibernate一級快取(內建session快取),二級快取(可裝配sessionFactory快取),二級快取會引起併發問題。

  2. hibernate延遲載入原理理解。

  3. hibernate 的get、load方法,sava、persist、savaOrUpdate方法區別

  4. session重建了關聯關係卻並沒有同資料庫進行同步和更新   5.hibernate session關聯關係:detached物件、persistent物件

  5. Spring data整合,註解方式配置屬性和物體。

  6. mybatis 外掛。

  7. 分頁查詢(資料庫)。

  8. 連線池技術

4.2 Spring IOC

4.2.1 Spring bean

  1. bean註入 註解方式方便易讀,取用第三方(資料庫連線,資料庫連線池,JedisPool等)採用配置檔案方式。

  2. bean作用域:Singleton,prototype,request,session,global session

  3. bean生命週期:如下圖所示(圖片來源於網際網路) 

4.3 Spring AOP

基本概念:關註點、切麵Aspect、切入點pointcut、連線點joinpoint、通知advice、織入weave、引入introduction。

Spring AOP支援5中型別通知,分別是MethodBeforeAdvice、AfterReturningAdvice、ThrowsAdvice、MethodInterceptor、IntroductionInterceptor(吐槽一下名字太長)

實現方式如下:

  1. 基於代理的AOP

  2. 基於@Aspect註解驅動的切麵。(強烈推薦:可讀性好,易維護,易擴充套件,開發快)

  3. 純POJO切麵。

  4. 註入式Aspect切麵。

4.4 Srping事務

4.4.1 事務傳播

概念:某些操作需要保證原子性,如果中間出錯,需要事務回滾。如果某個事務回滾,那麼呼叫該事務的方法中的事務的作出如何的動作,就是事務傳播。

短時間內寫不清楚,建議訪問 http://www.cnblogs.com/yangy608/archive/2010/12/15/1907065.html 檢視。

事務傳播屬性:

  1. PROPAGATION_REQUIRED–支援當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。

  2. PROPAGATION_SUPPORTS–支援當前事務,如果當前沒有事務,就以非事務方式執行。

  3. PROPAGATION_MANDATORY–支援當前事務,如果當前沒有事務,就丟擲異常。

  4. PROPAGATIONREQUIRESNEW–新建事務,如果當前存在事務,把當前事務掛起。

  5. PROPAGATIONNOTSUPPORTED–以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

  6. PROPAGATION_NEVER–以非事務方式執行,如果當前存在事務,則丟擲異常。

事務隔離級別:

  1. ISOLATION_DEFAULT: 這是一個PlatfromTransactionManager預設的隔離級別,使用資料庫預設的事務隔離級別.另外四個與JDBC的隔離級別相對應

  2. ISOLATIONREADUNCOMMITTED: 這是事務最低的隔離級別,充許令外一個事務可以看到這個事務未提交的資料。這種隔離級別會產生臟讀,不可重覆讀和幻像讀。

  3. ISOLATIONREADCOMMITTED: 保證一個事務修改的資料提交後才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的資料

  4. ISOLATIONREPEATABLEREAD: 這種事務隔離級別可以防止臟讀,不可重覆讀。但是可能出現幻像讀。它除了保證一個事務不能讀取另一個事務未提交的資料外,還保證了避免下麵的情況產生(不可重覆讀)。

  5. ISOLATION_SERIALIZABLE 這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。除了防止臟讀,不可重覆讀外,還避免了幻像讀。

4.5 其他Spring 技術棧
  • spring boot 輕量級啟動框架

  • spring security 使用者許可權管理,根據角色和使用者,實現UserDetailsService,進行自定義許可權管理。

  • spring task 程式碼級定時任務,註解方式,使用起來非常方便。需要註意的是,如果某次定時任務出了異常而沒有進行處理,會導致接下來定時任務失效。如果各個任務相互獨立,可以簡單用try,catch包圍(之前就吃過這方面的虧)。

  • spring data 註解方式定義物體,屬性等

  • spring mvc 簡單明瞭的mvc框架。url傳值、陣列傳值、物件傳值、物件陣列等傳值型別,上傳/下載檔案型別需要註意。

  • spring restful 註意命名,對命名要求很嚴格。

  • spring shell 命令列方式執行命令,救火、匯入匯出資料等用起來非常方便、製作報表。  

5. Web基礎

5.1 web容器啟動
  1. web.xml載入順序: listener -> filter -> servlet

  2. webt容器啟動過程,java新手很怕配置檔案,理解完這些有助於熟悉配置檔案 http://blog.csdn.net/u014431852/article/details/47042895

5.2 Servlet、Interceptor、Listener、Filter
  • Servlet 接收請求傳迴響應,最原始的web業務處理類。

  • Interceptor 攔截器,可以實現HandlerInterceptor介面自定義攔截器,在日誌記錄、許可權檢查、效能監控、通用行為等場景使用,本質是AOP。

  • Listener 監聽器 常用於統計線上人數等縱向功能。

  • Filter 過濾器 在請求介面處理業務之前改變requset,在業務處理之後響應使用者之前改變response。如果某些資料不加密,很容易用抓包工具加filter作弊。

5.3 web專案結構

5.3.1 mvn結構

熟練掌握幾種常見的mvn專案結構,mvn可以自動生成,這裡不再詳述。

5.3.2 mvn包管理

  1. 版本號儘量幾種在一個檔案中便於管理。

  2. spring milestone包解決spring包衝突問題。

  3. mvn dependency:tree命令分析所有包依賴,對於衝突的在pom檔案中 包圍起來

5.3.3 版本控制

  1. git、svn等

  2. 程式碼衝突解決方案

  3. 分支管理。

對於某個穩定版本上線後,如果在此基礎上開發新功能,一定要新建分支,在新分支上提交程式碼,最後在新版釋出時合併分支。修改運營環境bug切換到主分支進行修改

5.4 Http請求

5.4.1 請求方法

post、get、put、head、delete、copy、move、connect、link、patch,最常用的是前4、5個。

5.4.2 請求頭,狀態碼

常用的請求頭有Accept(下載檔案會特殊使用)、Accept-Charset(設定utf-8字符集)、Content-Type(json等配置)等常用的響應頭有Content-Type、Content-Type、Content-Length等,偏前端,不再詳述。

6. 系統架構

接觸的不是特別多,目前用到的只是伺服器主從備份。Nginx反向代理進行配置。

多個專案nginx配置。

Spring Mvc 用json資料進行互動,配置json轉換的servlet。

封裝傳回值。

自定義RunEnvironmentException(狀態碼,原因),改寫原有Exception,切麵ExceptionHandler抓取Exception並封裝到傳回值中(前後端松耦合)。

令人頭疼的使用者重覆(連續快速點選)提交問題,前端限制治標不治本;後端用sessonid在切麵上實現,又需要前端儲存,對所有請求資料加sessionId。最後用jedis中儲存,用介面名+使用者名稱當做key,根據不同的介面對不同的key可以單獨設定時間,不僅保證了重覆提交問題,也避免了惡意請求問題,同時還能自定義請求間隔。(期初擔心redis快取讀寫時間延誤導致限制失效,後來發現多慮了,對一般的小系統來說,經效能測試,發現即使請求頻率再提高100被也不會導致限制失效)。

testNg單元測試、效能測試,改寫測試。

切麵管理日期、許可權。快取等。

7. Nosql

1.Redis的java庫Jedis。

Jedispool配置。

專案中用到的有任務佇列、快取。

2.neo4j圖資料庫

處理社交、推薦

8. 服務端

linux作業系統熟悉以centos為例:

  • 常用簡單命令:ssh、vim、scp、ps、gerp、sed、awk、cat、tail,df、top,shell、chmod、sh、tar、find、wc、ln、|

  • 目錄結構明細:/etc/、~/、/usr/、/dev/、/home/、/etc/init.d/

  • 服務端:jdk、tomcat、nginx、mysql、jedis、neo4j啟動與配置(特別說明的是該死的防火牆,nginx啟動後一直訪問不了,查詢一下午查不到原因,最後發現是防火牆問題)

  • 監控伺服器狀態(cpu,磁碟,記憶體),定位pid,日誌檢視

  • nginx負載均衡、反向代理、配置

  • 自動化部署指令碼

  • 簡單shell指令碼書寫,避免大量人力勞動。

  • 監控系統,程式碼拋fatal異常自動發郵件,系統指標持續偏高自動發郵件。

9. 資料庫相關

10. 第三方介面對接

10.1 支付介面

微信支付坑比較多,用將近兩周時間才把微信支付所有完成。需要在微信後臺配置的地方太多。

而支付寶支付模組只用了2天時間就搞定了。

10.2 推送介面

為使用者定義tag、定義alias,註意當資料更新時需要同步更新tag、更新alias。如果沒採用非同步實現(使用者體驗就是好卡啊)

10.3 雲儲存

大量檔案上傳雲端(七牛雲),註意建立bucket

10.4 簡訊驗證

很簡單的第三方介面,引入依賴,直接呼叫即可。需要在第三方後臺設定模板等,註意限定使用者訪問次數。

10.5 郵件

很簡單小功能,工具類。

時間有限,目前先寫這麼多技術棧。


●本文編號603,以後想閱讀這篇文章直接輸入603即可

●輸入m獲取文章目錄

推薦↓↓↓

 

演演算法與資料結構

更多推薦18個技術類微信公眾號

涵蓋:程式人生、演演算法與資料結構、駭客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。

贊(0)

分享創造快樂