我一直相信這句話,他山之石能夠攻玉。在本身能力不夠時,多學習別人的東西。這樣,對本身只有好處,沒有壞處。於是,通過將近一年的工做,研讀了公司所使用的框架。我本想往架構師的方向靠近,但,本身的能力可能還不夠,於是,不斷地給本身充電。css
公司的項目是先後端分離的,前端使用HTML5,css三、jquery、vue.js、bootstrap等,以SVN作代碼託管。後端採用maven構建項目,以git lab作代碼託管。確定有人會問,這兩個都是版本庫,但它們有什麼區別?若是想要了解的話,能夠參考該文檔:Svn與Git的區別。html
如今幾乎全部的公司都採用maven構建項目,不多會採用導入jar包的方式依賴第三方框架。前端
maven構建的項目有不少好處,首先其能夠統一管理jar包,也就是說,咱們在項目中不用手動導入jar包,咱們只要添加依賴便可,如代碼所示:vue
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${jdbc.version}</version> </dependency>
添加依賴以後,maven就會導入該jar包,導入jar包的順序爲:java
maven報出相應的錯誤時,也許,是咱們本地沒有該jar包,遠程倉庫也沒有該jar包,咱們能夠參考這篇博客:在maven的pom.xml中添加本地jar包。它會教你如何建立本地倉庫,並導入建立好的本地倉庫。mysql
【備註】這篇博客以架構師的角度來說解maven,因此,不具體講解maven各個標籤的含義。若是你想了解pom的各個標籤的含義,能夠參考這篇文檔:pom.xml詳解,或者,參考這篇教程:maven教程|菜鳥教程jquery
上面解說只是配置jar文件,可是,maven的功能遠不止這些,從咱們建立maven項目時,就已經進入到maven的開發環境中。css3
有人和我說過,學一項知識,什麼方式最快?那就是經過作項目。你在作項目的過程當中,確定會遇到不少問題,而你不得不去查找資料,從根源上認識到這個問題。於是,我以公司所作的某個項目爲例,來說解maven的依賴、繼承、聚合等關係。c++
咱們所說的maven中的關係,其實就是pom的關係,即項目對象模型(Project Object Model)的簡稱。git
首先,咱們在建立cloudCodeSale項目時,就已經建立了父pom文件,如圖所示:
上圖就是咱們的父pom文件,你很清楚的看到gav座標。同時,你從這張圖上,也能獲得其餘信息,其打包方式是 pom,其還關聯其餘module,module名稱和左邊的列表名稱同樣。這就是咱們所說的maven的聚合。父類同時聚合其子類。
聚合的條件有兩個:
既然全部的子模塊的pom都繼承父pom,爲何父pom要聚合子模塊的pom文件?這個問題很好。
由於對於聚合而言,當咱們在被聚合的項目上使用Maven命令時,實際上這些命令都會在它的子模塊項目上使用。這就是Maven中聚合的一個很是重要的做用。在實際開發的過程當中,咱們只須要打包(mvn install)父pom文件。
咱們在父pom上使用mvn celan、mvn compile和mvn package,其會自動對子模塊:platform-core、platform-core-controller、portal/member-portal、portal/platform-portal、platform-cms、platform-cms-controller、platform-custom
執行mvn celan、mvn compile和mvn package。不必一個一個地打包,這樣極容易出現錯誤,如圖所示:
若是不少模塊都須要相同的jar包,咱們能夠單獨寫在一個pom中,其餘模塊使用該模塊的公共部分,這就是咱們常說的父類。不管是java語言,仍是c++語言,或者如今的pom,其都體現這個思想。
咱們在上文也提到了子模塊,如今模塊platform-core講解。繼承父類的結構通常是這樣的:
<parent> <groupId>parent.groupId</groupId> <artifactId>parent.artifactId</artifactId> <version>parent.version</version> <relativePath>../pom.xml</relativePath> </parent>
relativePath是父pom.xml文件相對於子pom.xml文件的位置,針對被繼承的父pom與繼承pom的目錄結構是否是父子關係。若是是父子關係,則不用該標籤;若是不是,那麼就用該標籤。由於在當前項目中,platform-core模塊的目錄的pom在父目錄的pom中,其和父pom的目錄結構是父子關係,於是能夠省略relativePath該標籤,如圖所示:
parent標籤中的groupId、artifactId、version要和父pom中的標籤中一致。
正如咱們所知道的,maven構建項目,不只是由於其可以管理jar包,其還使模塊化開發更簡單了。於是,咱們在開發的過程當中,通常都分模塊化開發。模塊與模塊之間的信息是不通的,可是,咱們想要模塊間的之間可以通訊,這時,咱們就想到了java中的依賴關係。
好比,咱們有一個模塊,這個模塊封裝好了微信支付、支付寶支付、處理json格式、操做文件、ResultUtil、lambdaUtil、commonUtil等工具類,還有附件、頭像、用戶等實體類。這些工具類在任何項目中不會輕易改變,若是爲了知足某些需求而不得不得修改,須要獲得架構師的贊成。
於是,咱們能夠把它拿出來,單獨定義爲一個模塊,也就是platform-core模塊。可是,咱們還有一個模塊,在這個模塊中,根據不一樣的項目,其定義不一樣的實體類、dao層類、事務層類、枚舉類、接收前端傳來參數封裝成的query類、從數據庫中取出的數據封裝成的data類,到事務層可能會調用模塊plateform-core中的方法,好比調用第三方系統接口的HTTPClientUtil.doPost(String url, Map<String, String> param)
,判斷處理lambda表達式的LambdaUtil.ifNotBlankThen(String value, Consumer<String> function)
,等等。
這個自定義類的模塊,咱們可定義爲plateform-custom。plateform-custom須要用到platform-core中的方法,於是,這時,咱們就須要考慮依賴關係,怎麼添加對platform-core的依賴呢?如代碼所示:
<dependency> <groupId>com.zfounder.platform</groupId> <artifactId>platform-core</artifactId> </dependency>
咱們這邊是先後臺分離的,後臺用來錄入數據,前臺用來展現數據,於是,咱們有一個portal目錄,該目錄下有兩個子模塊。一個是member-portal模塊,一個是platform-portal模塊,前者接收前臺的接口參數,後者接收後臺的接口參數。但不論哪一個模塊,都須要依賴plateform-custom中的事務層方法,同時,咱們傳的參數,可能信息分發的platform-cms-controller中的接口,也多是核心接口platform-core-controller中的接口。於是,咱們這裏以member-portal模塊來舉例,依賴其餘模塊的代碼以下:
<dependencies> <dependency> <groupId>com.zfounder.platform</groupId> <artifactId>platform-core-controller</artifactId> </dependency> <dependency> <groupId>com.zfounder.platform</groupId> <artifactId>platform-cms-controller</artifactId> </dependency> <dependency> <groupId>com.zfounder.platform</groupId> <artifactId>platform-custom</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
這些模塊你會在上面的圖片找獲得。同時,咱們來看member-portal的pom文件繼承的父pom是怎麼寫的:
補充上面的繼承關係。這裏面用到了<relativePath>../../pom.xml</relativePath>
你會奇怪的是,爲何這裏面用到了呢?其和父pom不是父子關係,而是孫子關係。這裏使用到了兩次點點,這是什麼意思呢? ..表示上級目錄。舉個例子說明:
好比,在個人服務器上的www目錄中,有三個文件,分別是rsa_private_key.pem, rsa_private_key_pkcs8.pem, rsa_public_key.pem,還有一個testDir目錄,testDir目錄中還有目錄testDir,如今咱們經過cd ../testDir/testDir
進入到子目錄中,如今,咱們想返回到www的根目錄中,並查看rsa_public_key.pem文件的內容,於是,咱們能夠用cat ../../rsa_public_key.pem
命令,其首先返回兩級目錄,而後找到rsa_public_key.pem文件並打開該文件。
「被繼承的父pom與繼承pom的目錄結構是否是父子關係」也不是絕對的,主要是選擇繼承者的pom中的子目錄和父目錄之間的關係,其中間隔了幾層目錄。
激活文件在上文也提到了,咱們爲何須要激活文件?以下面的兩個配置文件,一個是測試環境的配置文件,名爲platform-dev.properties,一個是正式環境的配置文件,名爲platform-prd.properties。兩個配置文件中都存在與數據庫的鏈接,可是呢,數據庫的ip地址是不同的。如一下的代碼所示:
jdbc.url=jdbc:mysql://localhost/prd_database jdbc.username=prd_username jdbc.password=prd_password jdbc.validationQuery=select 1 from dual jdbc.removeAbandonedTimeout=180 jdbc.initialSize=10 jdbc.minIdle=30 jdbc.maxActive=100 jdbc.maxWait=30000 。。。
jdbc.url=jdbc:mysql://intranet_ip/dev_database jdbc.username=dev_username jdbc.password=dev_password jdbc.validationQuery=select 1 from dual jdbc.removeAbandonedTimeout=180 jdbc.initialSize=10 jdbc.minIdle=30 jdbc.maxActive=100 jdbc.maxWait=30000 。。。
咱們的在配置文件中配置好了數據項,可是呢,咱們怎麼切換不一樣的配置文件呢?換句話說,咱們怎麼想要打正式服的包放到正式服上,怎麼選擇platform-prd.properties的配置文件呢?反之,怎麼選擇platform-dev.properties配置文件?
這時,咱們就用到了maven當中的profile標籤,以下代碼所示:
<profiles> <profile> <id>dev</id> <activation> <activeByDefault>true</activeByDefault> </activation> <build> <filters> <filter>../../platform-dev.properties</filter> </filters> </build> </profile> <profile> <id>prd</id> <build> <filters> <filter>../../platform-prd.properties</filter> </filters> </build> </profile> </profiles>
這些配置文件時寫在member-portal、platform-portal、plateform-core和plateform-cms、plateform-customer模塊的pom中的。可是,plateform-core和plateform-cms的配置中的filter和上面連個略有差別,其filter是這樣的 <filter>../platform-dev.properties</filter>
和 <filter>../platform-prd.properties</filter>
,這就涉及到目錄點的問題。
maven項目除了依賴本項目的,其還會依賴第三方包,好比自動生成set和get方法的lombok包,處理json格式的阿里巴巴下的fastjson包等等,咱們也可使用這種格式的依賴:
<!--mysql jdbc驅動包 開始--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${jdbc.version}</version> </dependency> <!--mysql jdbc驅動包 結束-->
<!-- lombok驅動包 開始--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.10</version> </dependency> <!-- lombok驅動包 開始-->
咱們在沒有使用lombok以前,常常手動建立javabean的set個get方法,使用這個框架以後,其以註解的方式,能夠自動生成set和get方法。同時,其強大的功能遠不止這些,也能夠生成無參構造器、全參構造器,指定參數構造器、重寫toString方法、重寫Hashcode、equals方法等等。
如代碼所示:
/** * Created By zby on 17:37 2019/1/30 */ @AllArgsConstructor @NoArgsConstructor @Data @ToString @EqualsAndHashCode public class Address { /** * 收貨人 */ private String consignee; /** * 手機號碼 */ private String phone; /** * 所在地區 */ private String area; /** * 詳細地址 */ private String detail; /** * 標籤 */ private AddressTagEnum addressTag; }
想要更深層次的瞭解這個框架,能夠參考這個博客:Lombok使用詳解
<!-- fastjson驅動包 開始--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.28</version> </dependency> <!-- fastjson驅動包 結束-->
fastjson是阿里巴巴開源的框架,其用來處理服務器端的json格式的數據。好比,咱們須要將服務端的對象以json(JavaScript object Notation,js對象標記)格式傳輸到前端,可是,若是本身手動建立的話,勢必會很是的麻煩,因而,咱們藉助這個框架,幫助咱們生成json格式的對象。
同時,若是咱們要調用第三方接口,好比調用連連綁定銀行卡的接口,其返回給咱們的也是json對象的數據。可是,咱們須要將其轉化爲咱們定義的對象,調用其save方法,保存到數據庫中,對帳所用。
對於,將對象轉化爲json格式的對象,如代碼所示:
@Test public void test() { // 地址 Address address = new Address(); address.setAddressTag(AddressTagEnum.ADDRESS_TAG_COMPANY); address.setArea("杭州市...."); address.setConsignee("zby"); // 用戶 User user = new User(); user.setHobby(HobbyEnum.HOBBY_DANCING); user.setGender("男"); user.setUserName("蔣三"); // 訂單 OrderSnapshot orderSnapshot = new OrderSnapshot(); orderSnapshot.setAddress(address); orderSnapshot.setId(1L); orderSnapshot.setName("復讀機"); orderSnapshot.setOrderNo(Long.valueOf(System.currentTimeMillis()).toString() + "1L"); orderSnapshot.setUser(user); System.out.println(JSON.toJSON(orderSnapshot)); }
其輸出結果如圖所示:
可是,相似於解析json格式的數據,不僅有fastjson框,還有org.json框架、Jackson框架。但通過有人驗證呢,仍是fastjson的效率更高一些。能夠參考這篇博客:Gson、FastJson、org.JSON到底哪個效率更高,速度更快
org.json也是經過maven配置的,如代碼所示:
<!-- json驅動包 開始--> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20140107</version> </dependency> <!-- json驅動包 開始-->
若是想要深層次瞭解org.json,能夠參考這篇博客:Java使用org.json.jar構造和解析Json數據
想要更深層次的瞭解fastjson,能夠參考這篇博客:Fastjson 簡明教程
若是從事java-web開發,通常會用到spring框架,這方面的教程太多了,筆者就不在這介紹,但咱們會用到spring的這些框架:
<!--spring 相關配置開始--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency>
spring會集合不少框架,好比具備攔截效果的shiro框架,持久層的hibernate和mybatis框架等等。spring經過配置文件經過註解或者配置文件的方式,實現依賴注入(dependency injection)和控制反轉(inversion of control)。經過@controller遍歷相應的接口,實現先後端的接口對接。spring能夠實現面向切面編程,實現某個業務點的單一執行。好比,專門處理事務的業務點。
spring並不難,很快就能掌握到其精髓。
若是想深刻了解,能夠參考這篇教程:Spring教程
hibernate框架就相似於mybatis框架,其專門處理持久層的技術。咱們將瞬時狀態的對象存儲到數據庫中,變成持久狀態的對象。咱們也能夠從數據庫中取數據,以瞬時態的對象返回到前端。這就是一存一取的框架。
其可使用註解的方式建立數據表,也能夠經過配置文件建立瞬時態的對象。但就目前爲止,在不少狀況下,咱們都是經過註解的方式,實現數據表的建立。導入hibernate相關的框架,以下所示:
<!--hibernate相關配置 開始--> <!--hibernateh核心框架--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> </dependency> <!--hibernateh驗證器--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> </dependency> <!--hibernateh緩存技術--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> </dependency> <!--Java Persistence API ORM映射元數據 查詢語言--> <dependency> <groupId>org.hibernate.java-persistence</groupId> <artifactId>jpa-api</artifactId> </dependency> <!--hibernate相關配置 結束-->
hibernate和mybatis具備一樣的功能,若是想要了解mybatis,能夠參考這篇教程:mybatis教程
想要深刻理解hibernate,可參考這篇教程:hibernate教程_w3cschool
咱們上面說了hibernate框架,但前提是,咱們須要導入jdbc的框架包,如代碼所示:
<!-- 數據庫驅動包相關 開始--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- 數據庫驅動包相關 結束-->
這個驅動包主要處理java與數據庫的鏈接,實現數據的增、刪、改、查。咱們沒有用到這個包,可是hibernate用到了這個包,於是,咱們須要導入這個包,以避免數據庫報錯。
這個包有什麼用嗎?咱們既然經過hibernate實現與數據庫的交互,那麼就須要在初始化時建立鏈接池。如今鏈接池有不少種,咱們爲何選擇了它Druid。
<!-- Druid驅動包相關 開始--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </dependency> <!-- Druid驅動包相關 結束-->
它是目前最好的數據庫鏈接池,在功能、性能、擴展性方面,都超過其餘數據庫鏈接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已經在阿里巴巴部署了超過600個應用,通過一年多生產環境大規模部署的嚴苛考驗。Druid是阿里巴巴開發的號稱爲監控而生的數據庫鏈接池!
時代在變化,咱們也應該應世而生,與時俱進,纔不會和時代脫軌。
咱們使用Druid來實現數據的配置,如代碼所示:
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="maxActive" value="${jdbc.maxActive}"/> <property name="initialSize" value="${jdbc.initialSize}"/> <property name="removeAbandoned" value="true"/> <property name="removeAbandonedTimeout" value="${jdbc.removeAbandonedTimeout}"/> <property name="testOnBorrow" value="true"/> <property name="minIdle" value="${jdbc.minIdle}"/> <property name="maxWait" value="${jdbc.maxWait}"/> <property name="validationQuery" value="${jdbc.validationQuery}"/> <property name="connectionProperties" value="clientEncoding=UTF-8"/> </bean>
大家能夠看到,value值是形參,而不是具體的值。由於咱們根據不一樣的打包方式,其傳入形參對應的實參不一樣。這也就是咱們上文提到的,platform-dev.properties和platform-prd.properties配置文件,以及maven配置的激活文件。
若是想要深刻了解阿里巴巴的Druid框架,能夠參考這篇博客:DRUID鏈接池的實用 配置詳解
短信業務通常固定不變,由架構師封裝好,其餘人直接調用便可,於是,該框架能夠寫進plateform-core模塊中,其配置的代碼以下所示:
<!-- 阿里短息驅動包配置 開始 --> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-dysmsapi</artifactId> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> </dependency> <!-- 阿里短息驅動包配置 結束 -->
咱們在開發的過程當中,常常會使用到日誌,來記錄相應的錯誤、警告、信息。好比,我在使用連連支付作提現業務時,提現成功後其會回調咱們的接口,從而顯示在服務端的Tomcat頁面中。再好比,咱們在登陸時,其會在Tomcat中顯示相關信息,如圖所示:
咱們都知道日誌分爲幾種級別。這裏就再也不贅述了。日誌分爲好多種,咱們推薦使用slf4j+logback模式。由於logback自身實現了slf4j的接口,無須額外引入適配器,另外logback是log4j的升級版,具有比log4j更多的優勢,咱們能夠經過以下配置進行集成:
<!-- 日誌驅動包配置 開始 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.7</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.7</version> </dependency> <!-- 日誌驅動包配置 結束 -->
咱們這時就用到了plateform-prd.properties文件和plateform-dev.properties文件,由於,咱們須要在這裏面配置日誌的輸出位置。而後,在logback.xml中以參數的形式,調用文件中的輸出位置,如圖所示:
若是想要了解更多的配置文件信息,請參考這篇博客:使用 logback + slf4j 進行日誌記錄
咱們在開發的過程當中,常常用到Commons家族的驅動包,好比文件操做的io包,MD5加密和解密用的codec包。固然,咱們也會用到java自帶的local_policy驅動包,但有時須要替換替換該驅動包,不然,就會報出Illegal Key Size的錯誤。文件上傳下載的fileupload驅動包,操做字符串類型的lang3包,配置的驅動包以下所示:
<!--comon包相關配置--> <commons-io.version>2.4</commons-io.version> <commons-lang3.version>3.4</commons-lang3.version> <commons-codec.version>1.10</commons-codec.version> <commons-fileupload.version>1.3.1</commons-fileupload.version> <!-- apache common 開始 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons-lang3.version}</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>${commons-io.version}</version> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>${commons-codec.version}</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>${commons-fileupload.version}</version> </dependency> <!-- apache common 結束 -->
咱們能夠用其分割字符串,判斷字符串是否爲空格,判斷字符串是否爲空等等。如如下代碼所示:
public static void main(String[] args) { String keyword = "1-1-2"; if (StringUtils.isNotBlank(keyword)) { System.out.println("keyword = " + keyword); } String[] keys = StringUtils.split(keyword, "-"); for (String key : keys) { System.out.println("key=" + key); } }
咱們有時還會用其操做時間類,好比格式化時間等等,入一下代碼:
@Test public void testDate(){ String date1= FastDateFormat.getInstance("yyyy-MM-dd").format(System.currentTimeMillis()); System.out.println("System.currentTimeMillis:"+date1); String date2= FastDateFormat.getInstance("yyyy-MM-dd").format(new Date()); System.out.println("new Date:"+date2); }
其功能遠不止這些,具體能夠參考這篇博客:commons-lang3工具包
見名知意,IO即input和output的簡寫,即輸入流和輸出流。於是,咱們常用到java自帶的InputStream或FileInputStream的字節輸入流,以及OutputStream或FileOutputStream的輸出流。若是更高級的話,那麼,就使用到了帶有緩存效果的bufferReader輸入流和bufferWrite輸出流。這裏面用到了裝飾設計模式。什麼是裝修設計模式,能夠自行學習。
上面的操做比較複雜,咱們就用到了apache下的io驅動包。這裏就當作拋磚引玉了,想要有更深的瞭解,能夠參考這篇博客:io包工具類
codec包是Commons家族中的加密和解密用的包,這裏不作任何解釋,具體能夠參考這篇博客:Commons Codec基本使用
咱們若是作java-web開發,常常會有文件上傳和文件下載的功能。這時,咱們就考慮到了Apache下面的 fileupload包,這能夠完成文件的上傳和下載。這裏的文件不僅僅是指doc文件,也會指圖片和視頻文件。
具體想要有更多的理解,能夠參考這篇文檔:commons-fileupload上傳下載
咱們在web開發時,常常會涉及到權限問題,好比哪些頁面不須要登陸就能看,而哪些頁面只能登陸才能看。當用戶在打開該頁面以前,就進入到相應的過濾器中,來作相關業務的判斷。若是經過,就進入到controller層;不經過,則拋出相應的異常給前端。這裏就須要相應的權限控制。
說到權限控制,咱們不得不提到shiro框架。其有三大核心組件Subject, SecurityManager 和 Realms。這個百度百科上也說了,能夠查看其解說內容:java安全框架
<!-- shiro驅動包 開始 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> </dependency> <!--shiro驅動包 結束 -->
公司也會作相應的配置,配置以下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!-- 緩存管理器 --> <bean id="cacheManager" class="com.*.shared.framework.SpringCacheManagerWrapper"> <property name="cacheManager" ref="springCacheManager"/> </bean> <bean id="springCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheManager" ref="ehcacheManager"/> </bean> <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> <property name="configLocation" value="classpath:ehcache.xml"/> </bean> <!-- 憑證匹配器 --> <bean id="credentialsMatcher" class="com.*.RetryLimitHashedCredentialsMatcher"> <constructor-arg ref="cacheManager"/> <property name="hashAlgorithmName" value="md5"/> <property name="hashIterations" value="2"/> <property name="storedCredentialsHexEncoded" value="true"/> </bean> <!-- Realm實現 --> <bean id="userRealm" class="com.**.shared.web.listener.MemberSecurityRealm"> <!--<property name="credentialsMatcher" ref="credentialsMatcher"/>--> <property name="cachingEnabled" value="false"/> <!--<property name="authenticationCachingEnabled" value="true"/>--> <!--<property name="authenticationCacheName" value="authenticationCache"/>--> <!--<property name="authorizationCachingEnabled" value="true"/>--> <!--<property name="authorizationCacheName" value="authorizationCache"/>--> </bean> <!-- 會話ID生成器 --> <!--<bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>--> <!-- 會話Cookie模板 --> <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="platform-portal-sid"/> <property name="httpOnly" value="true"/> <property name="maxAge" value="7200"/> </bean> <!-- 會話管理器 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <property name="globalSessionTimeout" value="43200000"/> <property name="deleteInvalidSessions" value="true"/> <property name="sessionIdCookieEnabled" value="true"/> <property name="sessionIdCookie" ref="sessionIdCookie"/> </bean> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm"/> <property name="sessionManager" ref="sessionManager"/> <property name="cacheManager" ref="cacheManager"/> </bean> <!-- 至關於調用SecurityUtils.setSecurityManager(securityManager) --> <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/> <property name="arguments" ref="securityManager"/> </bean> <!-- Shiro的Web過濾器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" depends-on="securityManager,memberShiroFilerChainManager"> <property name="securityManager" ref="securityManager"/> </bean> <!-- 基於url+角色的身份驗證過濾器 --> <bean id="urlAuthFilter" class="com.zfounder.platform.core.shared.web.filter.UrlAuthFilter"> <property name="ignoreCheckUriList"> <list> <value>/**/common/enums/**</value> <value>/**/security/**</value> <value>/**/common/dd/**</value> <value>/**/pictures/**</value> <value>/**/common/sms/**</value> <value>/**/wx/**</value> </list> </property> </bean> <bean id="memberFilterChainManager" class="com.zfounder.platform.core.shared.web.listener.CustomDefaultFilterChainManager"> <property name="customFilters"> <util:map> <entry key="roles" value-ref="urlAuthFilter"/> </util:map> </property> </bean> <bean id="memberFilterChainResolver" class="com.**.shared.web.listener.CustomPathMatchingFilterChainResolver"> <property name="customDefaultFilterChainManager" ref="memberFilterChainManager"/> </bean> <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="shiroFilter"> <property name="targetObject" ref="shiroFilter"/> <property name="targetMethod" value="setFilterChainResolver"/> <property name="arguments" ref="memberFilterChainResolver"/> </bean> <!-- Shiro生命週期處理器--> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> </beans>
想要對其有更深的理解,請參考這篇博客:Shiro講解
<!--漢字轉拼音開源工具包--> <dependency> <groupId>com.github.stuxuhai</groupId> <artifactId>jpinyin</artifactId> </dependency> <!--網絡爬蟲的驅動包--> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> </dependency> <!--驗證碼生成工具包--> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> </dependency> <!--發送郵件--> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> </dependency>
由於篇幅的限制,這裏就再也不細說了,若是想要更深層次的瞭解,能夠參考如下博客:
圖片驗證碼的配置文件以下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" default-lazy-init="true"> <bean id="captchaProducer" class="com.google.code.kaptcha.impl.DefaultKaptcha"> <property name="config"> <bean class="com.google.code.kaptcha.util.Config"> <constructor-arg> <props> <prop key="kaptcha.border">${kaptcha.border}</prop> <prop key="kaptcha.border.color">${kaptcha.border.color}</prop> <prop key="kaptcha.textproducer.font.color">${kaptcha.textproducer.font.color}</prop> <prop key="kaptcha.textproducer.char.space">${kaptcha.textproducer.char.space}</prop> <prop key="kaptcha.textproducer.font.size">${kaptcha.textproducer.font.size}</prop> <prop key="kaptcha.image.width">${kaptcha.image.width}</prop> <prop key="kaptcha.image.height">${kaptcha.image.height}</prop> <prop key="kaptcha.textproducer.char.length">${kaptcha.textproducer.char.length}</prop> <prop key="kaptcha.textproducer.char.string">1234567890</prop> <prop key="kaptcha.textproducer.font.names">宋體,楷體,微軟雅黑</prop> <prop key="kaptcha.noise.color">${kaptcha.noise.color}</prop> <prop key="kaptcha.noise.impl">com.google.code.kaptcha.impl.NoNoise</prop> <prop key="kaptcha.background.clear.from">${kaptcha.background.clear.from}</prop> <prop key="kaptcha.background.clear.to">${kaptcha.background.clear.to}</prop> <prop key="kaptcha.word.impl">com.google.code.kaptcha.text.impl.DefaultWordRenderer</prop> <prop key="kaptcha.obscurificator.impl">com.google.code.kaptcha.impl.ShadowGimpy</prop> </props> </constructor-arg> </bean> </property> </bean> </beans>
裏面的佔位符來源於plateform-dev.properties或者plateform-prd.properties,這就是咱們maven激活的配置文件的做用。
咱們在開發完一個功能後,首先會想到測試它走不走得通。咱們可能會在main方法中測試,一個項目類中能夠寫多個main方法。若是每一個功能類中都寫一個main方法,未免會形成代碼的混亂,一點都不美觀和儒雅。
java爲何一直推崇面向對象,任何在現實中真實的、虛擬的事物,均可以將其封裝爲爲java中的對象類。對象與對象之間以方法做爲消息傳遞機制,以屬性做爲數據庫存儲的機制。
若是咱們在每一個功能中都寫一個main方法,勢必會破壞這種對象的美觀性。於是,咱們把測試的數據以對象的方式操做,這樣,將其封裝爲一個測試包,好比,在我寫的spring框架中,就把測試類單獨拿出來,如圖所示:
<!-- 測試依賴包 開始--> <!-- spring test --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!-- 路徑檢索json或設置Json --> <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>${jsonpath.version}</version> <scope>test</scope> </dependency> <!-- testng --> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>${testng.version}</version> </dependency> <!-- 單元測試的powermock --> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-testng</artifactId> <version>${powermock.version}</version> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>${powermock.version}</version> </dependency> <!--測試相關 結束-->
以上是幾種測試包的依賴,一個是spring的測試包,這裏因爲篇幅的限制,就不作詳細的介紹了,網上有不少這方面的教程,想要深刻的瞭解,可參考這篇博客:Spring-Test(單元測試)
咱們有時也會用到TestNG框架,它是Java中的一個測試框架,相似於JUnit 和NUnit,功能都差很少,只是功能更增強大,使用也更方便。測試人員通常用TestNG來寫自動化測試,開發人員通常用JUnit寫單元測試。若是你是測試人員,想對其有更全面的瞭解,能夠參考這篇教程:TestNG教程,或者這篇博客::testNG經常使用用法總結
若是想要更深層次的瞭解powermock,能夠參考這篇博客:PowerMock從入門到放棄再到使用
若是想要更深層次的瞭解JsonPath,能夠參考這篇博客:JsonPath教程
咱們在開發的過程當中,會把圖片存放到服務器的某個文件夾下,即某個磁盤上。若是圖片過大,會佔用服務器的磁盤,於是,咱們須要將圖片縮略,來減小對內存的佔用。這時,咱們若是使用java原生的圖片縮略圖,是很是複雜的,於是,咱們可使用如下框架對圖片進行操做。
<!--圖片處理驅動包 開始--> <dependency> <groupId>net.coobird</groupId> <artifactId>thumbnailator</artifactId> </dependency> <!--圖片處理驅動包 結束-->
這裏再也不細說,想要有更多的瞭解,能夠參考這篇博客:Thumbnailator框架的使用
咱們在工做的過程當中,常常會將數據導出到Excel表,或將Excel表的數據導入數據庫。咱們之前使用poi框架,可是,超過必定量的時候,會佔用大量的內存,從而下降導入的效率。阿里巴巴如今開放出操做Excel表的easyexcel框架,對百萬級的導入影響不是很大。
如下是maven配置兩個驅動依賴:
<!--阿里巴巴的easyexcel驅動包 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>{latestVersion}</version> </dependency> <!--poi驅動包 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>${poi.version}</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>${poi-ooxml.version}</version> </dependency>
這兩個就再也不細說,若是想要對easyexcel更深的瞭解,能夠參考這篇博客:alibaba/easyexcel 框架使用。若是想要對poi有更深的瞭解,能夠參考這篇博客:Apache POI使用詳解
咱們在開發的過程當中,有時會用到guava驅動包。它是爲了方便編碼,並減小編碼錯誤,用於提供集合,緩存,支持原語句,併發性,常見註解,字符串處理,I/O和驗證的實用方法。
使用它有如下好處:
同時,又有增長Java功能和處理能力的函數式編程,提供了須要在應用程序中開發的許多實用程序類的,提供了標準的故障安全驗證機制,強調了最佳的作法等等。它的宗旨就是:提升代碼質量、簡化工做,促使代碼更有彈性、更加簡潔的工具。
咱們在項目中的配置包爲:
<!--guava驅動包 開始--> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> <!--guava驅動包 結束-->
若是想要對其有更深的瞭解,能夠參考這篇教程:guava入門教程
咱們在開發的過程當中,也許會用到這個框架。爲何要用到這個框架呢?咱們有時須要動態地將xml文件轉爲doc文件,這個時候,就用到了freemarker包,如圖所示:
截圖不是很全面,你會看到畫紅框的部分,這是一種佔位符的標記,就至關於java中的形參同樣。 當用戶點擊前端的下載按鈕時,有些數據是沒法直接轉換成doc的,由於咱們先把數據寫進xml中,再將xml轉化爲doc。具體如何轉換的能夠參考該博客:Java將xml模板動態填充數據轉換爲word文檔
咱們能夠引用這個包:
<!--freemarker驅動包 開始--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>${freemarker.version}</version> </dependency> <!--freemarker驅動包 結束-->
因爲篇幅限制,想要詳細瞭解,能夠參考這篇手冊: freemarker在線手冊
我記得當時在學java-web開發時,最開始用的就是servlet。接收客戶端的輸入,並通過一系列DB操做,將數據返回給客戶端。但使用純servlet不利於可視化界面。後來,使用了JSP開發,其是可視化界面。可是,當咱們啓動Tomcat後,JSP經過JSP引擎仍是會轉爲servlet。從本質上來講,JSP和servlet是服務端語言。
後來,工做了之後。後端就用了springMVC,hibernate框架等,前端使用的是HTML、jQuery等。慢慢地脫離了JSP和servlet。可是,並沒與徹底與servlet分隔開,咱們還時不時會用到servlet的一些類,好比HttpServletRequest,HttpServletResponse等類。
既然使用了spring MVC框架,爲何還要用servlet的東西,好比,咱們在導入和導出時,一個是接收前端導入的請求,一個是響應前端導出的請求。
private static void downloadExcel(HttpServletResponse response, File newFile, String fileName) throws IOException { InputStream fis = new BufferedInputStream(new FileInputStream( newFile)); String substring = fileName.substring(fileName.indexOf("/") + 1); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); response.reset(); response.setContentType("text/html;charset=UTF-8"); OutputStream toClient = new BufferedOutputStream( response.getOutputStream()); response.setContentType("application/x-msdownload"); String newName = URLEncoder.encode( substring + System.currentTimeMillis() + ".xlsx", "UTF-8"); response.addHeader("Content-Disposition", "attachment;filename=\"" + newName + "\""); response.addHeader("Content-Length", "" + newFile.length()); toClient.write(buffer); toClient.flush(); }
public static LinkedHashMap<String, List<JSONObject>> importMultiSheetExcel(HttpServletRequest request, LinkedHashMap<Integer, Integer> sheetDataStartRowMap, LinkedHashMap<Integer, String> sheetDataEndColMap) { LinkedHashMap<String, List<JSONObject>> resMap = new LinkedHashMap<>(); try { MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; ifNullThrow(multipartRequest, ResultCodeEnum.ILLEGAL_PARAM); MultipartFile file = multipartRequest.getFile("file"); Workbook work = getWorkbook(file.getInputStream(), file.getOriginalFilename()); ifNullThrow(work, ResultCodeEnum.ILLEGAL_PARAM); 。。。 }
雖然咱們如今使用了spring MVC,仍是用到了servlet,並且shiro裏面要使用到,如下是代碼的配置:
<!--servlet 開始--> <!--shiro裏面要使用到--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> </dependency> <!--servlet 結束--> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <!--servlet 結束-->
若是想要了解servlet的話,能夠參考該文檔:Java Servlet API中文說明文檔
有時,咱們在開發的過程當中,須要作全文檢索數據,就好比,我在Word文檔中,全文檢索某個詞、某句話等,如圖所示:
這就是web端的全文檢索。可是我作Java,固然,也須要全文檢索。於是,咱們就想到了Lucene。
它是一套用於全文檢索和搜尋的開源程式庫,由Apache軟件基金會支持和提供。提供了一個簡單卻強大的應用程式接口,可以作全文索引和搜尋。在Java開發環境裏,它是一個成熟的免費開源工具。就其自己而言,它是當前以及最近幾年最受歡迎的免費Java信息檢索程序庫。
咱們在java的maven庫中的配置爲:
<!-- lucene 開始 --> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>${lucene.version}</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-highlighter</artifactId> <version>${lucene.version}</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-common</artifactId> <version>${lucene.version}</version> </dependency> <!-- lucene 結束 -->
想要對其有更深的瞭解,能夠參考這篇筆記:Lucene學習筆記
咱們在開發的過程當中,總想着要在某個時間,執行什麼樣的事情,因而呢,咱們就至關了任務調度,好比:
咱們就能夠用到Quartz這個框架,咱們須要作一些配置,如圖所示:
咱們能夠在maven中的配置爲:
<!-- quartz驅動包 開始--> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>${quartz.version}</version> </dependency> <!-- quartz驅動包 結束-->
想要對其有根深多的瞭解,可參考這篇博客:Quartz使用總結
咱們常用到二維碼,好比,添加微信好友的二維碼,支付二維碼、掃一掃二維碼等等,那麼,這是怎麼實現的呢,其實,這有一個工具包,就是zxing工具包。它是谷歌旗下的工具類,咱們能夠用它來生成咱們想要的二維碼,可是,咱們先要在maven項目中配置它。如代碼所示:
<!-- 二維碼驅動包 開始--> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>${zxing.version}</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>${zxing.se.version}</version> </dependency> <!-- 二維碼驅動包 開始-->
想要對其有根深的瞭解,能夠參考這篇博客:zxing實現二維碼生成和解析
這個我也不大懂,也沒有操做過,若是想要了解的話,能夠參考這篇文檔:WebService中的WSDL詳細解析
咱們在maven中的怕配置爲:
<!-- WSDL驅動包 開始--> <dependency> <groupId>wsdl4j</groupId> <artifactId>wsdl4j</artifactId> <version>${wsdl4j.version}</version> </dependency> <!-- WSDL驅動包 結束-->
配置文件來源於框架中的如下文件,如圖所示:
全部的配置文件都來源於資源包。這裏就再也不細說。
要想成爲架構師,首先學習別人的東西,他山之石,能夠攻玉。