長久以來統領javaee領域的鷹架以spring struts2 mybatis/hibernate引領;
Spring:
Spring is not just for Java services。 spring作為cgi標準的實現,並非僅是作為Java領域的框架,C#平台依舊可以獲益;spring提供了抽象化等各種方便的註解配置方式或bootde 一體化方案,極大簡化了Javaee的項目基礎;
在spring的使用過程中,兩面分化,一部分,輕量註解,一部分傾向於全註解。
首先註解的前提是必然要經歷代理的,動態,靜態,cglib代理。對於輕量註解,角度站在靜態或說是一次性註解,
比如controller註解,這些一次性的註解或者是編譯期的註解,在項目上下文初始化作為一個隱射一次性掃描,相關的有service等類似註解,提供了單例的輕量級物件實例。視為首選。這樣減少了運行期的代理,反射,這些動輒大動乾戈的消耗,也為運行期的堆疊節約了更好的資源。
另一類例如responsebody,這類屬於動態註解或運行期的註解,每次請求,都會執行該註解的反射。運行期的註解,想當然是要佔用資源的。
總的來講,不是必須的註解完全可以不註解,基於servlet基礎的request,response方式沒有解決不了的mvc,取參,傳參,返回等,完全不需要運行期的註解,運行期的註解看似減少了程式碼量,為了補住這過程的各種缺,會運行一個圓環的動態註解來執行一個被你用在方法內部的註解。對於寫在方法裡面的param註解,比起自己用request get 究竟少了哪些程式碼?不過是讓原本一步到位的處理,加入了一層程式碼攔截。
如何知道一個註解是否是運行期或編譯期的註解,很簡單,Ctrl+滑鼠點擊,會看見:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
Retention 這個枚舉類型完整清晰的說明了你所使用的註解的作用期。
用spring 大家都喜歡用單例,這是極好的方式,單例與並發本身毫無關係,除了你非要讓它產生資源標識競爭,
如果說你的項目中必須要出現許多prototype的對象,那表示你濫用或用錯了對象,mvc基本上都是入參,返回,每一個請求都是一個線程,一個單獨的request response 有他們進出的東西,完全是隔離的。由此說到mybatis,許多人用mybatis一個配置裡面各種resmapper,每次都是各種bean來回走,一個請求下來,作為參數以及結果的bean必須有一次,mybatis表面上面清晰了sql維護,是以極大程度拉低jdbc的效率為代價的,然後並沒有很多人在意,bean對他們來講,沒有什麼,不了解也不關心gc,出來問題就加內存,內存加到頂,解決的只是時間問題,以空間換取時間。同樣的參數與結果映射,那麼自己new 一個bean 使用jdk的map,哪個好,自然是jdk自身的map,
個人從來固執的認為,new一個jdk自身的對象,其消耗遠小於自己定義一個bean 。為什麼,Sorry,i do not know either。所以我從來都是map來,map走。使用mybatis,一定要緊密檢測,你的事物代理到你的類別上面了嗎,方法很簡單,在專案的log裡面,打開debug,看你的日誌是不是每次都是create a new sqlsession,要是這樣的話 就要注意了 你的mybatis的session沒有池化,沒有被事物代理,一個方法裡面如果出現了競爭性的sql,sorry 沒有任何錯誤,只是發現數據庫沒有執行你的sql。很快,會發現連接池用的很快,頻繁的會創建新的connection。當然如果可以不用mybatis,別猶豫,不用是對的。
為什麼一定要盡量使用靜態註解呢,很簡單,spring的類別基本上都是singleton,項目夠大,bean實例也就夠多,這些單例的東西,佔用了什麼呢。物件實例在堆空間,引用在堆疊裡面。那麼gc什麼時候會回收這些單例的物件呢?你認為呢?所以,在基於註解的時候,盡量減少動態代理的使用。留更多的資源給需要用的地方用。
以前我們會說無堆不可無棧,現在要變了jdk1.7的string常數池已經到堆裡面了。
編譯型與解釋性哪個比較好,當然是解析式的,編譯型的類似中介模型。因此建構一門優秀的編譯型語言,難度遠大於解釋性語言。
web的結構很清晰,首先依舊是上下文,然後是按照順序的一系列組件,我們最關鍵的是servlet組件,這個是javaee的標準,其餘的web組件是協議標準,誰都必要有。那麼會看見許多專案的servlet的mapping是/,這個是糟糕的方式,因為很簡單,js或者css從來沒有必要通過servlet來處理,因此mapping主要考慮到與web容器的服務端組件交互,一般給兩種標識,例如.do and .action .do需要權限認證之類,action屬於直接放行。 js等不需要進入servlet,由web上下文根據url直接去返回,然後就沒有在mvc裡面加一個mvc的攔截與放行,多此一舉,製造問題,解決問題,不是好方式。這樣不管有沒有nginx的介入,你的靜態資源對於web容器來說就是靜態走的,沒有跟servlet產生關係。 servlet只關係你需要其處理的東西。
js寫在哪裡好?
很多人習慣把js寫在jsp裡面或html裡面,這樣說糟糕的。
我們建置項目,必須希望我們的js與css是一定能夠被瀏覽器快取的。
那麼寫在頁面的script標籤裡面js,就是個標籤而已,跟div或者input沒有區別,不會被緩存,我查閱很多資料,看見的緩存,明顯的寫著,緩存的單位是文件。而不是標籤。所以把你的css js寫在檔案裡面,引入檔案進來,這樣檔案會被緩存,這一點,我並不完全確定,因為沒有直接肯定的答案,是我的猜想。
jsp實際上是servlet,因此是動態的頁面,每次都是需要加載class去動態翻譯,然後class裡面的write方法將頁面寫到http給瀏覽器,瀏覽器渲染,如果是html,那麼是靜態的。動態靈活,這個是毋庸置疑的,既然是servlet,那就是java對象,各種Java的標籤與方法稱為可能。靜態需要你自己去處理,靜態頁面使用類似巨集語言,不如直接用jsp。
頁面上面,一次載入多少資料好?
如果你的頁面展示的東西按照類別,按照列表,數據量很少,幾百條,類型現在外賣點餐app的展示方式,那麼,一次給出所有的分類跟數據,所以的處理在客戶端處理,整個過程中的類別切換,預覽,全部在頁面去處理,包括搜索,我們客戶端的js, A的手機或者電腦裡面執行的js不會跟B的手機或者電腦產生競爭吧,如果每次切換一個類型就去刷一個ajax,都是同一個web容器群,這樣才有競爭。操作越頻繁,競爭越大。這一點要緊密關係到實際的場景。
一次查詢回傳的資料的量的多少與效能並無很多關係,幾千幾萬個資料不過幾十KB等級。
查詢的次數,也就是互動到服務端的次數是影響整體效能的直接原因。
一次查詢的資料量多少與被查詢的表的大小是正比例,不會因為一次返回10條加快查詢,一次返回1W條,拖慢查詢,資料庫操作本質上就是集合應用,並沒有創建什麼。
調優的前提是給多少最合適,不是給的越多越合適,jdk或者tomcat在不同位數不同的os上面能夠消耗的內存都是有上限的。
使用nginx;
必要的時候使用快取;
根據是否需要選擇訊息中間件或其他中間件;
資料庫的分離或是主從等,一定是當前資料庫實在不能支撐業務量了。
單例是好的方式。
多執行緒是利刃,不區分具體哪種語言。
maven管理是好的方式,但是你的項目主體應該是webmvc,建立web的項目,嵌入maven作為組件使用,而不是建立一個maven工程,再去轉成web項目,除非是閒的。
使用spring,目前是最好的鷹架。
盡可能使用jdbc,能夠做到的話。
能夠在客戶端完成的事情,就不要去交互到服務端,客戶端的資源是廣袤的,服務端的資源的有限的。
盡量少發請求,少發請求的代碼是好代碼,除非是你是即時的應用。
每個程式碼裡面的工具都是工具,API是你最需要理解的,哪個好,哪個不好,沒有準確答案。
一切皆對象,對於Java來講是純粹的,代理是對象,反射是對象,對像是對象,基本資料型態不是對象。
除了基本類型之外的東西,都是透過物件來完成,不管多複雜的流程,都是透過對應的物件的方法結合方法的參數去完成的。一個class怎麼序列化,怎麼反序列化,說白了就是檔案的io與傳輸,然後載入到jvm,建構成物件。
rpc之所以rpc,調用的不是一個線程裡面的東西,調用的東西,被代理了,代理把你的需求轉成參數作為數據流發出去了,服務端,把你的請求流再轉成對象,再流化發回去,你再構造對象,透過對象來處理。
NIO是好的方式,netty是不錯的選擇,多執行緒的socket有超越netty的嗎?
zookeeper是好的分散式註冊等一系列方案的優秀工具。
這些東西都是原理加對象,用就要去使勁看。
以上是個人理解,歡迎指正。
更多JAVAEE專案結構以及並發隨想相關文章請關注PHP中文網!