paulwong

          懷舊框架集合

          最近在公司用JUP框架做項目,發現這個框架是別人基于SpringSide封裝的,所以打算學習下,SpringSide,其中遇到了很多坑,做個記錄,網上關于這方面的資料都有些老了,而且SpringSide最新的版本是SpringSide-Utils,老一點的版本為v4.2.2.GA,以下分別對這兩個版本分別介紹下,主要內容來自于網上。


          一些資料:


          Github源碼地址:  https://github.com/springside/springside4

          OSchina源碼地址: https://git.oschina.net/calvin1978/springside4

          官方文檔:  https://github.com/springside/springside4/wiki

          SpringSide網址: http://springside.github.io/


          1、SpringSide簡介


          SpringSide--Pragmatic Enterprise Application KickStart and Common Library Stack,這么長的一個名字下來,不用解釋大家都知道是做什么的了----以Spring Framework為core,提供一個Pragmatic的企業應用開發基礎以及企業應用中各主題的最佳實踐展示。 


          愿景:為使用Spring框架的開發者提供一個非Demo版的復雜、正式而體現最佳使用實踐的參照系統。為JavaEEer必須面對的問題提供合乎Pragmatic原則的解決方案。 


          SpringSide的四個部分--
          Springside-Bookstore:  一個Full Feature的書店示例,兼有書店前臺和后臺管理,作為典型企業應用的微縮版。 
          SpringSide-Core :SpringSide封裝的核心代碼。  
          SpringSide-Templates: 讓用戶可以快速復制粘貼構建出自己應用的代碼模版,分Application與Plugins兩部分。 
          SpringSide-Generator: 自動整合SpringSide-Application/Plugins生成項目,生成CRUD代碼的Eclipse Plugins 和Ant 腳本。


          來看看SpringSide的作者,江南白衣的對它的介紹:


          SpringSide是什么?為什么要發起這個項目? 

          SpringSide是以Spring Framework為核心的,Pragmatic風格的JavaEE應用參考示例,是Java世界中的主流技術選型,最佳實踐的總結與演示。因為基于Spring也因為對Spring理念的認同,項目起名SpringSide,另外還有個好記的中文名字——“春天的旁邊”。 

          想起做這個項目,是在六七年前元旦輾轉反側的夜晚,想著自己應該為世界留下點什么。寫一本書還是做一個開源項目呢? 總感覺書印出來了就沒法改了,對我這種完美主義者有點難受。而開源項目,就可以永遠年輕,永遠生長,永遠重構…… 

          然后,做什么項目呢?那時候,淘寶們還沒有開始大規模開源自己的技術。國內的原創框架更多是在自娛自樂。所以SprinSide選了一條更低端的路線,將那時候已經太多而不是太少的開源項目粘合在一起,用好,也算是一樁功德了。

          SpringSide包含哪些演示項目? 這些項目采用或演示了哪些技術? 

          SpringSide里含有QuickStart 與 Showcase 一小一大兩個示例項目。 

          QuickStart是一個迷你的TodoList應用,濃縮了一個普通JavaEE應用所需的柴米油鹽各種基礎技術,從典型的CRUD界面,到趕時髦的Rest API,以及最基礎的用戶管理功能,可以作為很多項目的初始骨架。 


          Showcase 則一個五花八門的JavaEE技術大雜燴大派對,如安全、緩存、日志、消息中間件、定時任務等等等等。


          SpringSide 4和之前版本相比,有哪些較大改進?
           


          SSH 與 SSH2 發展到高潮后,Spring也進入了一個后Spring的時代,受到各種新興語言與框架如Play! Framework的圍攻。SpringSide 4,演示的就是這個后Spring時代的演進,如何使得avaEE依然是個體面的選擇。 

          一些變動包括 DAO框架轉用Spring Data JPA + Hibernate, MVC框架轉用Spring MVC 3, Restful框架轉用Spring MVC + Spring RestTemplate, CSS框架轉用Twitter Bootstrap,安全框架轉用Apache Shiro 等等,Selenium升級到WebDriver。 


          所有變動的目標,都是在代碼越來越簡單的同時,也保持對工業化大規模開發的支持。比如有些新興語言框架,高手自己可以寫得很快,但不一定適合很多普通程序員一起合作開發與維護。所以有些過度簡化的演進,比如完全拋棄XML純用Annotation的ApplicationContext定義方式,SpringSide并沒有使用。


          如何基于SpringSide創建新的項目?
           

          SpringSide也是利用Maven的Archetype插件來創建新項目的,在每次版本發布時都會把前面所說的QuickStart項目打包成一個模板項目。用戶只要用標準的maven archetype指令,就可以基于QuickStart項目生成自己的項目。

          SpringSide采用什么開源協議?對商用有什么限制? 

          用的是所知最開放的Apache License2,任何的Copy&Paste都是歡迎的。如果有哪個更開放的告訴我吧,因為實在對靠開源賺錢沒有過任何想法。

          有沒有其他開發者參與貢獻? 

          4.0這個大版本暫時只有我一個在主導。不過github真的是一個非常社交化的開源平臺,沒有了sourceforge、google code那種固定的開發團隊的概念。現在誰都可以闖進SpringSide來,改它幾行代碼,然后向我發起一個Pull Request就可以了。題外話,像Nutz那樣精細的貢獻者記錄,真是值得表揚又讓人羨慕的事情。


          SpringSide的發布周期?未來的發展方向?
           


          項目堅持了六七年,四個大版本,期間服務器遷徙數次,也有過多次跳票的不良記錄。所以很難說出一個固定的發布周期來。最近自己比較希望能做到與白天的項目一樣,固定三周一個的迭代,但也并不總能如愿。希望大家能相信我的人品,項目或遲或早,總是會發布的…… 

          至于未來的發展方向,一方面會繼續做細JavaEE普通應用的演示,使它與一般的玩具型演示項目有更顯眼的區別。一方面會展示更多互聯網項目的新潮技術,如NoSQL、ZooKeeper等,畢竟這看起來更有趣。


          2、SpringSide4技術選型


          1. Web

          MVC Framwork: SpringMVC3.0 Restful的風格終于回歸了MVC框架的簡單本質,對比之下Struts2概念太復雜更新又太懶了。

          Template:JSP2.0且盡量使用JSP EL而不是taglib,萬一要寫taglib也用純JSP來編寫,一向是SpringSide的推薦,Freemarker們始終有點小眾, 而Thymeleaf與美工配合度非常高,可惜也是太少用戶了。

          Layout Decoration: Tiles的配置都太復雜了,SiteMesh2好些,但Sitemesh3爛尾了。

          JavaScript Library: 隨大流用了JQuery。其實Dojo的面向對象語法更優美,但用戶數和插件社區差了點。

          CSS Framework: 最熱火的Twitter Bootstrap,提供了簡便的布局能力和基本的頁面美化。

          JavaScript/CSS Compressor: 還是隨便選的YUI Compressor

          ValidationJQuery Validation Plugin這種客戶端校驗的客戶體驗更好,而spring MVC集成hibernateValiator的服務端校驗則可以避免惡意用戶跳過頁面直接發送請求,校驗規則也更多,需要混合使用。


          2. WebService

          SOAP WebService: JAX-WS2.0的注解 + Apache CXF 無疑是最成熟的,一說起Axis1/2我都要打冷顫。

          Restful Service: JAX-RS 1.0 + Jersey/CXF,夠標準。但直接使用Spring MVC能使架構更簡單。 如果追求極致的性能標,直接寫Servlet也沒啥。

          Restful Client: 剛出來的JAX-RS 2.0標準,實際是用Jersey的client api做藍本的, 而直接使用Spring的RestTemplate可以減少第三方包的引入。

          為了隔絕變化影響,隱藏細節,對外暴露的DTO和應用內部的領域對象是不同的類型,用Dozer進行復制。

          請求參數的校驗,JSR303 Bean Validator的實現Hibernate Validator沒太多的競爭對手。


          3. Database

          數據庫設計基本原則: 見DataBase的相關章節

          ORM Framework: 快速開發的應用里,領域對象肯定是用JPA標注的。至于API用Hibernate還是JPA,因為那個極簡便的,DAO只要寫接口就好了的Spring-Data-JPA,所以選了JPA。 當然,JPA的實現還是用Hibernate

          追求高性能的應用,如各種Web服務,當然就是MyBatis了。如果項目再簡單點,Spring JDBC其實也不錯。

          傳統數據庫: 無非OracleMySQL的選擇,如果你恨MySQL依然是Oracle家的東西,可以考慮越來越多人用的,語法和Oracle很像的Postgresql。

          NOSQL數據庫: 國內用的比較多的還是RedisMongoDBRedis更像一個數據結構服務器,暴露各種數據結構的專有API。而MongoDB將數據存成BSON格式,也提供類似SQL的查詢語句,更像一個schema-less的數據庫。

          數據庫連接池: Apache DBCP本來一統江湖,現在被人批評又慢又復雜,所以有了Tomcat JDBC,另外溫少的Druid也是一個選擇。

          Cache: 在JVM里的緩存,最老牌最多人用的依然是Ehcache,一些更強大的DataGrid方案如HazelCast,JBoss的Infinispan反而沒什么人用。另外最簡單的JVM內緩存是Guava的Cache

          而中央式的緩存,Memcached已經成為了事實標準。而且當主創撒手不管后,社區現在反而有著穩定的更新。 Client方面,比較穩健選擇的還是Spymemcached


          3. Services

          Security Framework: 選擇Apache Shiro是因為SpringSecurity的代碼復雜度已經超過了它的實際需要,擴展困難痛苦。另一個原因是SpringSecurity的基本API居然只支持基于角色的判斷,e.g. hasRole("Administrator"),而Shiro同時還支持我們其實更常用的基于Permission的判斷,e.g. hasPermission("User:Edit")。

          JMS: ActiveMQ是最多人選用的應用服務器無關的JMS實現,JBoss的HornetQ同樣只是JBoss的用戶在使用。Spring自帶的JMS封裝很好用。但還有更高級的如支持跨平臺的AMQP協議的RabbmitMQ。

          Schedule: 對于固定時間間隔的任務,JDK自帶的Executor已足夠好。Cron式定時執行,Spring的Scheduler也能滿足。而且Spring的提供的純XML配置也讓Scheduler變得很簡單,Quartz更大的優勢體現在保證集群中有且僅有一臺服務器執行任務。另外,SpringSide還演示了基于Redis做了一個適合海量的只需單次觸發的任務。

          JMXJolokia能將JMX中的MBean以Restful+JSON的方式暴露出來,使JMX這個古老的,在平臺互通中顯得有點封閉的協議重新煥發了青春。而Spring-Jmx將普通POJO注釋一下就變成MBean也非常方便。

          其他Production Feature: 用Hystrix對訪問資源進行并發、延時、短路控制,防止系統雪崩。而監控方便包括自己寫的Metrics ReporterGraphite


          4. Utilizes

          General: Apache Commons Lang說是伴著我們長大的也不為過,3.0版連package名也改了,全面支持泛型。 Guava 是Google新鮮推出的優雅產品。但說它會一桶天下又不定,因為它有時候太新潮了,反而用不慣。比如StringUtils我還是喜歡用Apache的,IO也同樣是Apache Commons IO的好使。

          XML: 用JDK自帶的JAXB就算了,不折騰。

          JSON: GSon雖然系出名門而且接口優雅,但Jackson的功能更加豐富到匪夷所思,而且比GSon快很多。

          Email: Spring自帶的Email封裝挺好用的。

          LoggingSlf4j作為入口,早就替代了Apache Common Logging了,下面的實現Log4j 1.x 被批判太多同步方法太慢,Log4j作者的后作Logback就好很多了,但社區似乎不甘心log在一家QOS公司手里,又在推動log4j2.0的發展,目前還是beta版。另外選擇Logstash做日志的中央式處理。

          最后,Freemarker雖然不用來做頁面Template,平時用來生成點東西也不錯的。 JodaTime這種要直接加入JDK的就不多說它了。HttpClient建議用Apache HttpClient好過JDK自帶。


          5. Test

          Unit Test: JUnit始終是正統,TestNG的功能如測試用例分組它也慢慢支持了。AssertJ 是目前最好的Assert語句庫。

          Mock: Mockito的API比老牌的EasyMock更為優雅,而PowerMock則能配合Mockito完成static方法,函數內部new 出來的對象這些Mockito做不了的mock。

          Functional TestSelenium與WebDriver的合并后,最大改進是原來基于javascript的方案, 變成了直接調用瀏覽器的核心API,性能好了。

          Performance/Stability Test: [Jmeter]作為測試工具是最成熟的,Gatling還需要時間成熟。


          6. Development Environment

          JDK6這樣沒什么兼容性問題又成熟得一塌糊涂的版本建議大家都升級吧。JDK7也不錯,有G1垃圾收集器和Try-Catch新語法的語法糖。

          Jetty7是因為它的嵌入式版本做得好,集成測試不用部署直接就開跑了。開發時一般也不用Eclipse插件,直接自己在代碼里啟動了,省下打包拷貝War文件的時間。Tomcat現在也有嵌入式版本了,而Jetty最新版要JDK7。

          H2 Database,既是嵌入式的,又可以持久化到文件用Web Console查看,性能還是嵌入式中最好的。

          Maven,在項目構建腳本不復雜的時候的首選,否則就只能ant+ivy了,或者像hibernate和spring一樣,用gradle.

          另外,用Log4jdbc在開發時查看實際執行的SQL。

          最后,用Jenkins做持續集成, Sonar做代碼質量檢查,是大部分好項目的共同愛好。



          以下是對SpringSide-Utils的一個簡單介紹:


          1.SpringSide-Utils簡介


          把在唯品會兩年的實踐抽取出來,做一個大大大的公共類庫。一邊封裝 Guava 和 Apache Common Lang,一邊參考移植各門各派的精華:


          框架/容器隨身自帶:Spring,Netty,Tomcat,Jetty,ElasticSearch

          專門的類庫:Jodd,  Apache Common IO,Common Collections,JCTool,OpenHFT,AndroidUtilCode

          大廠的開源類庫:Facebook JCommon,twitter commons,linkedin-utils


          內庫中包含了文本、數字、日期、并發、集合、文件、反射、安全等方面的內容等著大家一一探索,這里又再嘮叨一下性能,性能,性能。

          新庫的設計目標,是把最佳實踐都封裝起來,讓大家使用類庫時,默認就獲得最優的性能。


          2.日期

          2.1 DateFormatUtil

          日期與String相互轉換時,JDK的SimpleDateFormat,又慢,又非線程安全。

          在不能全面轉為Joda Time時,使用Common Lang的FastDateFormat,又快,又線程安全,還能緩存實例。

          2.2 CachingDateFormatter

          FastDateFormat再快,日期格式化還是個消耗很大的事情。

          參考Logback和Log4j2,在打印當前時間的場景里,將同一時刻的結果緩存。


          3. 文本

          3.1 StringBuilderHolder

          ThreadLocal地重用StringBuilder,節約長字符串拼接時的內存消耗,節約成倍復制擴容的CPU消耗,是OpenHFT等好幾個類庫的共同選擇。

          3.2 HashUtil

          ThreadLocal地重用SHA1的MessageDiggest,減少每次創建MessageDigest的消耗,也是Tomcat,Facebook等好幾個類庫的共同選擇。

          3.3 JsonMapper

          封裝Jackson的實現,并提供不序列化“值為NULL的屬性”等選擇。

          3.4 TextValidator

          判斷是否合法的電話,身份證之類的正則表達式校驗,Pattern必須得預先編譯而不要每次創建,但總有匆忙的同學忘記這點。

          3.5 MoreStringUtil

          Common Lang的StringUtils已經很好用了。不過字符串操作的消耗總是很大,這里針對一些操作,給出更極致的性能優化,比如split()。


          4. 集合

          4.1 原子類型集合

          當集合中的元素是原子類型,而不是對象的時候。直接以原子類型來存儲,不但節約內存(int vs Integer, 4 bytes vs 16 bytes),甚至內部的數據結構也能完全不一樣,從而大幅提高性能。

          從Netty中移植了IntOjbectHashMap 和 LongObjectHashMap,性能約提升50%。后面還會有IntArrayList等等。


          4.2  MapUtil, ListUtil ...


          各種集合類的Util的創建函數,強迫大家去思考Array Base 集合類的初始大小,避免了容量不足時的成倍擴容; HashMap的加載因子,減少哈希沖突。


          在集合為空或只有一個元素時,使用Java Collections的特殊數據結構,進一步節約內存。


          4.3 其他擴展類型


          1. Guava


          MuitlSet :as MapCounter,不用再自己處理“如果有就+1,沒有就放個元素進去”的煩事


          MultiMap: as MultiValueMap


          WeakConcurrentHashMap: 鍵值為弱引用的并發Map,只此一家


          RangeMap:定義一段范圍的Key,對應一個Value,類似一致性哈希環之類的最合適


          2. Common Collections:


          UniqueArrayList


          MultiKeyMap


          Flat3Map:如果少于3個元素直接訪問屬性,否則才訪問真正的HashMap


          3. Jodd

          SortedArrayList


          4. JCTools


          針對 “多個生產者一個消費者”, “一個生產者多個消費者” 等特定場景優化的Queue。


          5. 并發


          5.1 JSR166e


          JDK的不同版本,不斷推出性能更優的并發實現,但如果考慮多JDK版本到的兼容就讓人發愁了。好在有Doug Lea大神的JSR166e項目。


          1. ThreadLocalRandom


          Random本身有全局鎖,JDK7的ThreadLocalRandom通過在ThreadLocal里放Random避免了鎖。


          2. LongAdder


          作為計數器,AtomicLong雖然能通過CAS避免鎖,但如果線程競爭激烈時依然有很大的損耗。JDK8的LongAdder,根據并發情況,將計數器智能的拆開成若干個,等取值時再求和。


          3. ConcurrentHashMapV8


          JDK5開始的ConcurrentHashMap是經典的分散鎖模式,而JDK8的ConcurrentHashMap,優化后居然取消了鎖。


          5.2 ThreadPoolBuilder


          比JDK Executors,提供更好的線程池設置,比如FixedPool的隊列最大長度,CachedPool的最大線程數等。


          另提供一個從Tomcat移植的QueueableCachedPool,“支持可變的線程數,跑滿線程時任務放隊列”這種符合大家想想的場景。


          5.3 ThreadLocalContext


          提供ThreadLocal HashMap存放上下文的示例,并給出更高效的,使用EnumMap的建議。


          6. 反射

          6.1 BeanMapper

          基于orika封裝,同時避免了一些低效API的使用,比如不給出來源集合的類型,讓框架自己去反射"iterator"函數的返回值來獲取類型的惡劣行為。

          更給出了預生成Type類型的最高效的用法。


          6.2 FastMethodInvoker

          基于cglib,通過代碼生成實現最快速的反射調用。比如反射調用A類的“hello” 方法,它就直接生成一個調用a.hello()的FastMethod子類.

          7. 其他

          7.1 ExceptionUtil

          異常構造時,獲取當前Stack Trace是一個很耗時的過程,把Stack Trace打印也同樣消耗。

          如果是一個比較清楚出處的異常,可以通過static定義的靜態異常。

          但如果異常的message會變化,就不能靜態定義唯一的異常了,此時可使用克隆異常,依然避過構造函數。

          7.2 SystemPropertiesUtil

          Properties本質上是一個有鎖的HashTable,所以不能頻繁的調用System.getProperty()。提供了一個以回調方式獲取變化的ListenableProperties。

          posted on 2020-10-09 19:14 paulwong 閱讀(309) 評論(0)  編輯  收藏 所屬分類: SPRING

          主站蜘蛛池模板: 集贤县| 金湖县| 南城县| 嘉祥县| 太谷县| 鹤峰县| 稻城县| 靖江市| 綦江县| 报价| 建宁县| 阜平县| 宽甸| 铜鼓县| 淮安市| 富裕县| 祁阳县| 固原市| 稻城县| 丽水市| 普陀区| 漠河县| 兴仁县| 滨州市| 从化市| 彭水| 清镇市| 磐安县| 个旧市| 辽阳县| 平远县| 昭苏县| 婺源县| 万州区| 泾源县| 镇坪县| 油尖旺区| 安图县| 五莲县| 孟津县| 富裕县|