長久以來統領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是好的分布式注冊等一系列方案的優秀工具。
這些東西都是原理加對象,用就要去使勁看。
以上是個人理解,歡迎指正。