天天看點

Java後端程式員1年工作經驗總結

java後端1年經驗和技術總結(1) 

1.引言 

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

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

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

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

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

不重視性能,隻求能實作功能,sql查詢是不是可以優化,是否有算法妙用,大對象是否要清除。 

不重視擴充性,子產品之間緊密耦合,常用方法不提取成工具類,調用關系混亂等問題。 

…… 

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

2.文法基礎

 2.1 Java類初始化順序 

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

2.2 值傳遞和引用傳遞 

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

Java後端程式員1年工作經驗總結

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

Java後端程式員1年工作經驗總結

如果你想學習java可以來這個群,首先是532,中間是259,最後是952,裡面可以學習和交流,也有資料可以下載下傳。

2.3 集合的使用 

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

Java後端程式員1年工作經驗總結

2.3 異常處理 

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

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

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

4.Java學習交流QQ群:532259952禁止閑聊,非喜勿進! 

2.4 面向對象思想 

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

共性的機會每個都需要用的建立基類,如每個控制層方法可能要通過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能夠為每一個線程維護變量副本,常用于在多線程中用空間換時間。 

5.Java學習交流QQ群:532259952禁止閑聊,非喜勿進!

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對象 

6.Spring data內建,注解方式配置屬性和實體。 

7.mybatis 插件。 

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

9.連接配接池技術 

4.2 Spring IOC 

4.1.1 Spring bean 

1.bean注入 注解方式友善易讀,引用第三方(資料庫連接配接,資料庫連接配接池,JedisPool等)采用配置檔案方式。 

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

3.bean生命周期:如下圖所示(圖檔來源于網際網路): 

Java後端程式員1年工作經驗總結

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 事務傳播 

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

事務傳播屬性: 

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

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

3. PROPAGATION_MANDATORY–支援目前事務,如果目前沒有事務,就抛出異常。 

4. PROPAGATION_REQUIRES_NEW–建立事務,如果目前存在事務,把目前事務挂起。 

5. PROPAGATION_NOT_SUPPORTED–以非事務方式執行操作,如果目前存在事務,就把目前事務挂起。 

6. PROPAGATION_NEVER–以非事務方式執行,如果目前存在事務,則抛出異常。 

事務隔離級别: 

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

2. ISOLATION_READ_UNCOMMITTED: 這是事務最低的隔離級别,充許令外一個事務可以看到這個事務未送出的資料。這種隔離級别會産生髒讀,不可重複讀和幻像讀。 

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

4. ISOLATION_REPEATABLE_READ: 這種事務隔離級别可以防止髒讀,不可重複讀。但是可能出現幻像讀。它除了保證一個事務不能讀取另一個事務未送出的資料外,還保證了避免下面的情況産生(不可重複讀)。 

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容器啟動過程

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 郵件 

很簡單小功能,工具類。 

時間有限,目前先寫這麼多技術棧。對于代碼書寫和、算法技巧問題,會抽時間寫在(2)中。