超詳細Maven技術應用指南

該文章,GitHub已收錄,歡迎老闆們前來Star!

GitHub地址: https://github.com/Ziphtracks/JavaLearningmanual

搜索關注微信公眾號“碼出Offer”,送你學習福利資源!

一、前言

在我們的項目資源中,你會發現需要導入的jar包越來越多,讓jar包的管理越來越沉重。它會表現為以下幾個缺點:

  • 每個項目都需要手動搜集和導入所需要的jar包
  • 項目中用到的jar包有版本更新,我們需要重新搜集並導入到項目中
  • 相同的jar包導入到不同的項目中,jar包會在本地存儲多份

針對上述問題,我們就需要使用統一的管理工具:Maven

二、了解Maven

2.1 什麼是Maven

Maven是一個基於項目對象模型(POM)的概念的純Java開發的開源的項目管理工具。主要用來管理Java項目,進行依賴管理(jar包依賴管理)和項目構建(項目編譯、打包、測試、部署)。此外還能分模塊開發,提高開發效率。

2.2 Maven的下載安裝

關於Maven的下載,我們需要下載它的解壓包。

Maven下載地址: https://us.mirrors.quenda.co/apache/maven/maven-3/3.6.3/binaries/

image-20200616171323409

下載后將Maven解壓到目錄中就可以了!

注意: 解壓的目錄與tomact服務器的形式是一樣的,不要有中文及特殊符號!

image-20200616171637526

2.3 Maven目錄結構解析

目錄名稱 描述
bin 存儲mvn的各種可執行文件
boot 含有plexus-classworlds類加載器框架,Maven 使用該框架加載自己的類庫
conf 存放settings.xml等配置文件
lib 存儲Maven運行時所需要的Java類庫
LICENSE/NOTICE/README.txt 針對Maven的版本、第三方軟件等簡要介紹

2.4 配置環境變量

Maven依賴Java環境的配置環境,所以要確保jdk版本在1.7以上,maven版本在3.3以上。

  • 配置環境變量與jdk環境變量配置是一樣的,在本機中創建MAVEN_HOME環境變量,並將maven的解壓路徑設置進去,點擊確定(路徑參考上圖解壓后的結果圖路徑)
  • 修改path環境變量,添加%MAVEN_HOME%\bin后,一路點擊確定即可!

2.5 測試

下載解壓、配置環境變量后,我們打開DOS命令窗口,鍵入mvn -v查看maven版本信息

  • 如果看到如下圖片maven的版本信息,證明maven安裝配置成功!
  • 在Maven的版本信息你就可以得知它依賴於jdk環境!

image-20200616172931556

2.6 Maven項目模型圖

三、Maven的配置

3.1 配置本地倉庫

本地倉庫簡單來說,就是在本地的maven中存儲管理所需jar包

  1. 首先,打開maven目錄conf文件夾中的settings.xml配置文件

  2. 其次,找到標號1的那一行配置信息,並複製此配置信息放在其下面

  3. 然後,在磁盤中創建一個目錄,作為存儲jar文件的本地倉庫

  4. 最後,將複製的此配置信息路徑替換成自己創建的本地倉庫目錄路徑,參考標號2的操作

image-20200616174928266

3.2 配置jdk

3.2.1 全局配置

由於Maven依賴於jdk環境,所以我們也需要在maven中配置jdk(我使用的jdk是主流的1.8版本)

  1. 打開settings.xml配置文件,找到<profiles>標籤,你會發現標籤內都是註釋的內容,我們需要在標籤內,寫入自己的jdk的配置信息。配置如下:
  2. 在maven中添加好jdk的配置信息后,我們需要在</profiles>結束標籤后添加<activeProfiles>標籤內容,讓配置好的<profiles>標籤中內容生效

注意: profile標籤中的id是此配置信息的名稱,在後面使用activeProfile標籤讓其配置生效的時候,需要保證id與activeProfile的名稱一致!(貼圖供大家參考!)

    <!-- 配置jdk -->
    <profile>
        <id>jdk1.8</id>
        <activation>
            <activeByDefault>true</activeByDefault>    
            <jdk>1.8</jdk>    
        </activation>    
        <properties>    
            <maven.compiler.source>1.8</maven.compiler.source>    
            <maven.compiler.target>1.8</maven.compiler.target>
            <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> 
        </properties>    
    </profile>
<!-- 使配置好的profiles標籤中內容生效 -->
<activeProfiles>
    <activeProfile>jdk1.8</activeProfile>
</activeProfiles>

image-20200616181057029

3.2.2 單個項目修改

後面我們會了解到maven項目是通過pom.xml進行構建信息配置和依賴信息配置。其中就包括配置編譯需要的jdk版本。所以我們直接修改pom文件就可以實現單個項目修改,但是我們並不推薦此種方式,因為這個方式需要每個項目都要修改,不具有可重用性!

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
</build>

四、倉庫

4.1 倉庫概念

  • 存儲依賴的地方,體現形式就是本地的一個目錄。
  • 倉庫中不僅存放依賴,而且管理着每個依賴的唯一標識(坐標),Java項目憑坐標獲取依賴。

4.2 倉庫分類

Maven倉庫可以分為本地倉庫和遠程倉庫,其中遠程倉庫又分為中央倉庫、公共倉庫和私服

  • 本地倉庫: 本地倉庫存放着項目中所需jar文件
  • 中央倉庫: Maven的中央倉庫是由Maven社區提供存儲jar文件的倉庫
  • 公共倉庫: 國內廠家提供的存儲jar文件的倉庫,比如:aliyun倉庫
  • 私服: 由公司創建的存儲jar文件的倉庫,可在公司範圍內共享,不對外開放

當項目中需要jar文件依賴時,會從倉庫中查找獲取,如果我們把所有倉庫都配置好。maven在查找獲取依賴的時候遵循一個依賴查找順序,如下:(如果本地倉庫找不到依賴就去私服下載,以此類推……)

依賴查找順序: 本地倉庫 – > 私服 – > 公共倉庫 – > 中央倉庫

image-20200616184606968

4.3 本地倉庫

本地倉庫: 本地目錄中存放所需jar包,需修改settings配置文件來配置本地倉庫

  • 使用過的依賴都會存儲在本地倉庫中,實現復用

4.4 遠程倉庫

4.4.1 中央倉庫

中央倉庫: Maven中央倉庫是由Maven社區提供的倉庫,不用任何配置,maven中內置了中央倉庫地址。其中就包含絕大多數流行的開源Java構件

  • https://mvnrepository.com/可以搜索需要的依賴的相關信息(倉庫搜索服務)
  • http://repo.maven.apache.org/maven2/為中央倉庫地址
4.4.2 公共倉庫

公共倉庫: 第三方維護的jar文件倉庫,比如阿里雲提供的倉庫。但是jar文件可能不如官方的中央倉庫全,有時候也會找不到,所以如果項目構建不成功,可以更改鏡像為官方的,下載完jar包再去改回來

  • aliyun倉庫地址:http://maven.aliyun.com/nexus/content/groups/public/

  • 因為Maven社區提供的中央倉庫在國外,國內使用下載依賴速度過慢,所以一般我們都配置國內的公共倉庫來代替中央倉庫

  • 使用時,需要在settings.xml配置文件中添加配置信息。打開settings.xml配置文件,找到<mirrors>標籤,你也會發現這是一個空標籤,最後標籤內填寫如下配置就OK!

    <!--setting.xml中添加如下配置-->
    <mirror>
        <id>aliyun</id>  
        <!-- 中心倉庫的 mirror(鏡像) -->
        <mirrorOf>central</mirrorOf>    
        <name>Nexus aliyun</name>
        <!-- aliyun倉庫地址 以後所有要指向中心倉庫的請求,都會指向aliyun倉庫-->
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>  
    </mirror>

image-20200616223651045

4.4.3 私服

私服: 公司創建存儲jar文件的倉庫,只對公司範圍共享,不對外開放。可以通過Nexus來創建、管理一個私服。

4.4.3.1 私服概念
  • 私服是架設在局域網的一種特殊的遠程倉庫,目的是代理遠程倉庫及部署第三方構件。

  • 有了私服之後,當 Maven 需要下載依賴時,直接請求私服,私服上存在則下載到本地倉庫;否則,私服請求外部的遠程倉庫,將構件下載到私服,再提供給本地倉庫下載。

  • 私服可以解決在企業做開發時每次需要的jar包都要在中心倉庫下載,且每次下載完只能被自己使用,不能被其他開發人員使用

  • 所謂私服就是一個服務器,但是不是本地層面的,是公司層面的,公司中所有的開發人員都在使用同一個私服

4.4.3.2 私服架構

我們可以使用專門的 Maven 倉庫管理軟件來搭建私服,比如:Apache Archiva,Artifactory,Sonatype Nexus。這裏我們使用Sonatype Nexus

  • 我們可以在圖中得到在無私服的情況下,我們都需要從遠程倉庫去獲取jar文件並存儲在本地倉庫,由於中央倉庫是國外的,所以下載速度比較慢等等原因,並存在很多缺點,比如我們公司內使用
  • 我們在圖中可清晰的看到,如果有私服的話,我們需要從私服中,查找jar文件,如果私服沒有該jar文件,就需要去中央倉庫或公共倉庫去下載,然後傳到私服中,最後傳入到自己的本地倉庫進行使用。假設公司員工再一次使用到該jar文件,它會先從私服中找有沒有這個jar文件,由於我們之前的員工已經將該jar文件存儲到了私服中,所以就省去了其他員工調用遠程倉庫的步驟。並且私服是公司內部局域網類型的,下載速度會比遠程倉庫快出很多倍
無私服 有私服
私服1 私服2
4.4.3.3 Nexus安裝(了解即可)
  • Nexus官網地址:https://blog.sonatype.com/

  • 下載地址:https://help.sonatype.com/repomanager2/download/download-archives—repository-manager-oss

下載我們需要下載Zip解壓包即可,將解壓包解壓到本地盤符中即可!

解壓后,你會看到nexus目錄為私服目錄,sonatype-work目錄中包含存儲私服下載的依賴。

4.4.3.4 Nexus登錄

訪問私服:http://localhost:8081/nexus/

登錄私服的賬號為admin,密碼為admin123

4.4.3.5 倉庫列表
倉庫類型 描述
group 包含多個倉庫,通過group庫的地址可以從包含的多個倉庫中查找構件
hosted 私服 服務器本地的倉庫,其中存儲諸多構件
proxy 代理倉庫,其會關聯一個遠程倉庫, 比如中央倉庫,aliyun倉庫,向該倉庫查找構件時,如果沒有會從其關聯的倉庫中下載
倉庫名 描述
Releases 存放項目的穩定發布版本,一個模塊做完后如果需要共享給他人,可以上傳到私服的該庫
Snapshots 對應不穩定的發布版本
3rd party 存放中央倉庫沒有的 ,如ojdbc.jar,可以上傳到私服的該庫中
倉庫列表
私服_list
4.4.3.6 倉庫組

而此時就有問題,私服中有很多倉庫,每個倉庫都有自己的url,則項目中配置哪個倉庫呢 ?

私服中有一個倉庫組,組中包含多個倉庫,可以指定倉庫組的url,即可從多個倉庫中獲取構件

關於倉庫的設置: 由於我們在使用私服的時候,本地倉庫沒有的jar文件,需要去私服找,私服沒有的話,就去中央倉庫找。所以我們需要把私服內的中央倉庫換為阿里雲倉庫,這樣可以保證我們國內的下載速度。

倉庫組 注意:proxy的倉庫排序在最後
私服_deploy2
4.4.3.7 手動上傳倉庫
4.4.3.8 Maven關聯私服

配置settings.xml,設置私服地址、認證等信息(關聯私服需要添加配置文件信息如下,找到父標籤,添加子標籤內容即可)

<servers>
    <server> 
        <id>nexus-public</id> <!-- nexus的認證id -->
        <username>admin</username> <!--nexus中的用戶名密碼-->
        <password>admin123</password> 
    </server>
</servers>
<profiles>
    <profile> 
        <id>nexus</id> 
        <repositories> 
            <repository> 
                <id>nexus-public</id> <!--nexus認證id 【此處的repository的id要和 <server>的id保持一致】-->
                <!--name隨便-->
                <name>Nexus Release Snapshot Repository</name> 
                <!--地址是nexus中倉庫組對應的地址-->
                <url>http://localhost:8081/nexus/content/groups/public/</url>
                <releases><enabled>true</enabled></releases> 
                <snapshots><enabled>true</enabled></snapshots> 
            </repository>
        </repositories> 
        <pluginRepositories> <!--插件倉庫地址,各節點的含義和上面是一樣的-->
            <pluginRepository> 
                <id>nexus-public</id> <!--nexus認證id 【此處的repository的id要和 <server>的id保持一致】-->
                <!--地址是nexus中倉庫組對應的地址-->
                <url>http://localhost:8081/nexus/content/groups/public/</url>
                <releases><enabled>true</enabled></releases> 
                <snapshots><enabled>true</enabled></snapshots> 
            </pluginRepository> 
        </pluginRepositories> 
    </profile>
</profiles>
<activeProfiles>
    <activeProfile>yourjdk</activeProfile>
    <!-- 使私服配置生效 -->
    <activeProfile>nexus</activeProfile>
</activeProfiles>
4.4.3.9 Meven項目部署到私服
  • 執行mvn deploy指令即可將項目部署到私服對應的倉庫中,此時項目中的打包方式多為jar
  • 但需要提前在項目的pom.xml中配置部署私服倉庫位置,如下:

注意: 如上的 repository的 id 依然是要和settings.xml中配置的server中的id 一致,才能通過私服的認證

<project>
        ...
    <dependencies>
        .....
    </dependencies>

    <!-- 在項目的pom.xml中 配置私服的倉庫地址,可以將項目打jar包部署到私服 -->
    <distributionManagement>
        <repository>
            <id>nexus-public</id> <!-- nexus認證id -->
            <url>http://localhost:8081/nexus/content/repositories/releases</url>
        </repository>
        <snapshotRepository>
            <id>nexus-public</id> <!-- nexus認證id -->
            <url>http://localhost:8081/nexus/content/repositories/snapshots</url>
        </snapshotRepository>
    </distributionManagement>
</project>

五、IDEA中的Maven操作

5.1 創建Maven項目

創建Maven項目
image-20200616215847109
指定項目名稱和項目位置
image-20200616220455702
5.1.1 節點配置解析
節點 詳細描述
groupId 這是項目組的編號,這在組織或項目中通常是獨一無二的。 例如,一家銀行集團 com.company.bank擁有所有銀行相關項目。
artifactId 這是項目的 ID。這通常是項目的名稱。 例如,consumer-banking。 除了 groupId 之外,artifactId 還定義了 artifact 在存儲庫中的位置。
version 這是項目的版本。與 groupId 一起使用,artifact 在存儲庫中用於將版本彼此分離。 例如:com.company.bank:consumer-banking:1.0com.company.bank:consumer-banking:1.1
5.1.2 語義化版本號
  • 規則:正式穩定版本從v0.1.0開始,配套軟件公共API
  • 注意:正式版發布后不可修改,只能在下一個版本中發布新內容
版本類型 詳細描述
主要版本 當你做了不兼容的API 修改(正式版發布、架構升級)
次要版本 當你做了向下兼容的功能性新增(功能增減)
修訂版本 當你做了向下兼容的問題修正(BUG修復、查缺補漏)
5.1.3 擴展(SNAPSHOT)

在使用maven過程中,我們在開發階段經常性的會有很多公共庫處於不穩定狀態,隨時需要修改併發布,可能一天就要發布一次,遇到bug時,甚至一天要發布N次。我們知道,maven的依賴管理是基於版本管理的,對於發布狀態的artifact,如果版本號相同,即使我們內部的鏡像服務器上的組件比本地新,maven也不會主動下載的。如果我們在開發階段都是基於正式發布版本來做依賴管理,那麼遇到這個問題,就需要升級組件的版本號,可這樣就明顯不符合要求和實際情況了。但是,如果是基於快照版本,那麼問題就自熱而然的解決了,而maven已經為我們準備好了這一切。

maven中的倉庫分為兩種,snapshot快照倉庫和release發布倉庫。snapshot快照倉庫用於保存開發過程中的不穩定版本,release正式倉庫則是用來保存穩定的發行版本。定義一個組件/模塊為快照版本,只需要在pom文件中在該模塊的版本號后加上-SNAPSHOT即可(注意這裏必須是大寫),如下:

<groupId>cc.mzone</groupId>
<artifactId>m1</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>

maven會根據模塊的版本號(pom文件中的version)中是否帶有-SNAPSHOT來判斷是快照版本還是正式版本。如果是快照版本,那麼在mvn deploy時會自動發布到快照版本庫中,會覆蓋老的快照版本,而在使用快照版本的模塊,在不更改版本號的情況下,直接編譯打包時,maven會自動從鏡像服務器上下載最新的快照版本。如果是正式發布版本,那麼在mvn deploy時會自動發布到正式版本庫中,而使用正式版本的模塊,在不更改版本號的情況下,編譯打包時如果本地已經存在該版本的模塊則不會主動去鏡像服務器上下載

在maven的約定中,依賴的版本分為兩類——SNAPSHOT和RELEASE。SNAPSHOT依賴泛指以-SNAPSHOT為結尾的版本號,例如1.0.1-SNAPSHOT。除此之外,所有非-SNAPSHOT結尾的版本號則都被認定為RELEASE版本,即正式版,雖然會有beta、rc之類說法,但是這些只是軟件工程角度的測試版,對於maven而言,這些都是RELEASE版本。所以一般我們需要上傳到發布倉庫的時候可以在<version>標籤內直接寫版本即可,不需要再添加任何標籤!

5.2 IDEA關聯Maven

在IDEA中關聯本地安裝的maven,後續就可以通過idea來使用maven管理項目(我使用的aliyun倉庫)

在全局設置中關聯Maven
image-20200616222756521
Maven項目展示 (缺少test包下resources文件夾)
image-20200616224937892

5.3 IDEA創建測試包下resources文件夾

我們在使用IDEA創建Maven項目時,IDEA是沒有幫我們創建test包下的resources文件夾。但是Maven規範中是包含這個文件夾的,所以我們需要手動創建並聲明該文件夾

創建存放測試配置的文件夾
image-20200616225355373
指定文件夾名稱 (下拉框選擇resources文件夾創建即可)
image-20200616225859663
文件目錄結構展示 (完整Maven規範目錄結構)
image-20200616230042781

5.4 Maven項目目錄結構解析

注意: 項目中的創建包、創建類、執行,都與普通項目無異

目錄名稱 描述
src/main/java 用於創建包,存放編寫的源代碼(.java文件)
src/main/resources 存放項目中所需配置文件,比如:c3p0.properties
src/test/java 用於創建包,存放編寫的測試代碼(.java文件)
src/test/resources 存放項目中測試代碼所需配置文件
根目錄/pom.xml 項目對象模型(project object model),maven項目核心文件,其中定義項目構建方式,聲明依賴等

5.5 Maven項目類型

根據項目類型,在pom.xml文件中添加相應配置。

  • 項目類型分為Java項目和JavaWeb項目

  • 如果項目為Java項目需要在<project>標籤內添加 jar

  • 如果項目為JavaWeb項目需要在<project>標籤內添加 war

注意: Maven可以根據項目類型來確定打包方式,比如Java項目打包成jar包JavaWeb項目打包成war包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mylifes1110</groupId>
    <artifactId>firstmaven</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--
        設置項目類型,打包方式:
        如果為Java項目則使用jar
        如果為JavaWeb項目使用war
    -->
    <packaging>jar</packaging>
<!--    <packaging>war</packaging>-->
</project>

5.6 IDEA中導入依賴

5.6.1 導入依賴須知

建好項目后,需要導入需要的jar包,要通過坐標來在倉庫中查找導入

  • 每個構件都有自己的坐標,其坐標分為groupId、artifactId、version 三種,翻譯後為項目標識、項目名稱、版本號
  • 在maven項目中只需要配置坐標,maven便會自動加載對應依賴。刪除坐標則會移除依賴
節點 描述
project 工程的根標籤。
modelVersion 模型版本需要設置為 4.0。
groupId 這是工程組的標識。它在一個組織或者項目中通常是唯一的。例如,一個銀行組織 com.companyname.project-group 擁有所有的和銀行相關的項目。
artifactId 這是工程的標識。它通常是工程的名稱。例如,消費者銀行。groupId 和 artifactId 一起定義了 artifact 在倉庫中的位置。
version 這是工程的版本號。在 artifact 的倉庫中,它用來區分不同的版本。例如:com.company.bank:consumer-banking:1.0 com.company.bank:consumer-banking:1.1
5.6.2 查找依賴

依賴查找服務需要在如下網址中查找依賴,獲取依賴坐標后,在maven項目中的pom.xml文件中導入

  • 依賴查找服務地址: https://mvnrepository.com/
查找jar文件
image-20200616111418839
jar文件的選擇
image-20200616112444879
Copy依賴坐標
image-20200617003002005
5.6.3 導入依賴

在項目的pom.xml文件中添加依賴

  • 首先添加<dependencies>標籤
  • 最後添加複製好的依賴坐標

注意: 導入依賴可以導入多個所需jar文件的依賴,依次在<dependencies>標籤內添加依賴坐標即可

導入依賴
image-20200617003853705
5.6.4 同步依賴

導入依賴后,你會發現pom.xml文件中的依賴坐標是紅色報錯的,而在IDEA的右下角有那麼一個框。這時候需要點擊框內提示信息在maven倉庫中同步下載依賴到項目中

同步下載依賴到項目中
image-20200617004515463
5.6.5 查看依賴

導入並同步下載好的依賴,可以通過項目和IDEA中Maven控制面板查看

查看依賴
image-20200617005635304

5.7 基於Maven創建Web項目

5.7.1 修改web項目打包方式

pom.xml文件中設置 <packaging>war/packaging>修改打包方式為web項目

5.7.2 導入web依賴

基於Maven項目,我們導入了maven所需依賴,如果創建web項目的話,還需要導入JSPServletJSTL依賴,使Maven項目具有web編譯環境。(在pom.xml文件中添加以下依賴)

        <dependency>
            <!-- jstl 支持 -->
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <!-- servlet編譯環境 -->
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <!-- jsp編譯環境 -->
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>

image-20200617123210482

5.7.3 創建web項目目錄結構

web項目在IDEA中有web規範目錄文件夾的,比如webapp、WEB-INF、web.xml、index.jsp。而由於Maven項目中沒有該規範目錄,這就需要我們自己創建目錄結構了!

創建web項目目錄結構有以下注意點:

  • webapp文件夾必須是基於main目錄下創建的,與java文件夾同級
  • webapp文件夾IDEA自動識別此文件夾,給與了特殊藍色圓點標識
  • 在WEB-INF目錄下創建的的web.xml是一個空的xml文件,我們需要在該文件中鍵入如下web.xml空白模板信息,只需要將下面的模板複製到項目中的web.xml文件中即可!
  • 創建的文件夾以及文件名稱千萬不要寫錯!

注意: 在創建項目的時候,其實我們是可以指定使用IDEA來創建來創建web項目的目錄結構的,創建項目時需要勾選Create from archetype。只是IDEA為我們構建的項目架構是有版本差異的,而且還附加了很多對我們無用的註解等等,所以我們一般都手動創建,IDEA自動構建作為了解就好!

xml空白模板

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
</web-app>
IDEA自動構建項目結構
image-20200617164915737
手動構建web項目結構
基於main目錄下創建webapp文件夾
image-20200617124249878
image-20200617124319926
基於webapp目錄創建WEB-INF文件夾
image-20200617124624648
基於WEB-INF目錄創建web.xml文件
image-20200617125038803
image-20200617125055216
xml文件內容展示
image-20200617125729115
基於webapp目錄創建index.jsp文件
image-20200617125613861
目錄展示 (完整的web項目目錄結構)
image-20200617125808227
5.7.4 tomact的引入

關於Tomact服務的引入,需要我們手動添加tomact服務

添加tomact服務后,如果對tomact服務器在IDEA中的開發流程不熟悉的小夥伴,不要灰心。請參考tomact服務器基礎和開發步驟即可,此文章中詳細講到了關於tomact的各種知識點!

添加tomact服務
image-20200617131801103

5.8 pom文件的其他標籤操作

5.8.1 build標籤修改默認打包名

默認的打包名稱:artifactid+verson.打包方式

我們可以通過build中finalName修改,如下操作:

<build>
  <finalName>maven_name</finalName>
</build>  
5.8.2 引入插件

dependencies引入開發需要的jar包,有時候我們還需要引入一些常用的插件,比如:jdk、tomact、分頁插件等等

插件配置位置也是在<build>標籤中,如下:

<build>
<plugins>
    <!-- java編譯插件,配jdk的編譯版本 -->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <encoding>UTF-8</encoding>
      </configuration>
    </plugin>
    <!-- tomcat插件 -->
    <plugin>
      <groupId>org.apache.tomcat.maven</groupId>
      <artifactId>tomcat7-maven-plugin</artifactId>
      <configuration>
        <port>8080</port>
        <path>/</path>
        <uriEncoding>UTF-8</uriEncoding>
        <server>tomcat7</server>
      </configuration>
    </plugin>
  </plugins>
</build>
5.8.3 控制打包資源

如果在java文件夾中添加java類,會自動打包編譯到classes文件夾下。但是xml文件默認不會被打包,需要我們手動指定打包。可以使用<resources>標籤來指定要打包資源的文件夾要把哪些靜態資源打包到classes根目錄下

<!--打包指定靜態資源-->
<build>
<resources>
    <resource>
      <!-- 指定要打包資源的文件夾 要把哪些靜態資源打包到 classes根目錄下-->
      <directory>src/main/resources</directory>
      <includes>
        <include>**/*.xml</include>
        <include>**/
*.properties</include>
      </includes>
    </resource>
    <resource>
      <directory>src/main/resources</directory>
      <excludes>
        <exclude>spring/*</exclude>
      </excludes>
      <includes>
        <include>*.xml</include>
        <!--<include>*/
*.properties</include>-->
      </includes>
    </resource>
  </resources>
</build>

六、依賴的生命周期

6.1 什麼是依賴的生命周期

jar文件的生效時間段可以成為依賴的生命周期

6.2 依賴的生命周期分類與詳解

前三個是常用的依賴生命周期設置,而後兩個製作了解即可,幾乎用不到!

標識 周期
compile 缺省值(默認依賴生命周期),適用於所有階段(測試運行,編譯,運行,打包)
provided 類似compile,期望JDK、容器或使用者會提供這個依賴。如servlet-api.jar;適用於(測試運行,編譯)階段
test 只在測試時使用,適用於(編譯,測試運行)階段,如 junit.jar
runtime 依賴在編譯器不使用,只在運行時使用,如 mysql的驅動jar,適用於(運行,測試運行)階段
system Maven不會在倉庫中查找對應依賴,在本地磁盤目錄中查找;適用於(編譯,測試運行,運行)階段

6.3 依賴生命周期的使用

關於依賴生命周期的使用,需要在期望指定生命周期的依賴內添加<scope>標籤,在此標籤內添加所需依賴標識。

complie

jstl依賴默認沒有compile標識的生命周期。因為在依賴中不指定生命周期就是默認指定適用於所有階段的生命周期,其默認標識為compile。

image-20200617135847510

provided

servlet和jsp依賴默認指定provided標識的生命周期。因為我們在servlet或jsp代碼時是需要這兩個依賴的,但是我們將項目部署到tomact中,本地tomact目錄的lib文件夾下也會有一些jar文件,所以這造成了一種依賴衝突。為了避免這種依賴衝突我們需要指定依賴的生命周期為編譯和測試運行階段。這樣我們在書寫代碼時,編譯期也有有依賴可以使用,不會飄紅,而在過了編譯期後項目部署到了tomact中,該依賴聲生命就會被結束掉了,不會影響tomact服務器內置依賴的使用!

image-20200617135818392

test

在maven項目中,項目結構是區分main主文件和test測試文件的。如果我們在使用Junit單元測試時,指定依賴的生命周期為test,那該依賴只適用於test測試文件內,在其他文件的階段默認沒有單元測試的依賴。

簡單來說,在test文件夾內創建的測試類,使用@Test註解不會有任何問題。如果換做在main文件夾和其他文件夾中創建測試類,使用@Test註解就會因沒有依賴注入而報錯。

image-20200617140515452

runtime

我們在添加mysql驅動的依賴時,你會發現它並沒有指定生命周期為runtime。這是因為我們在書寫jdbc工具類的操作時,如果在編譯期沒有mysql驅動的依賴,它並不會飄紅報錯。如果沒有依賴只有在我們運行的時候才會發生報錯,並告知mysql驅動依賴未找到。所以,這就顯得runtime這個依賴生命周期十分的雞肋。因此,可以不指定該生命周期。

image-20200617141145812

system

當依賴的生命周期設置為system時,表示該依賴項是我們自己提供的,不需要Maven到倉庫裏面去找。
指定scope為system需要與另一個屬性元素systemPath一起使用,它表示該依賴項在當前系統的位置,使用的是絕對路徑。由於此類依賴不是通過 Maven 倉庫解析的,而且往往與本機系統綁定,可能造成構建的不可移植,因此應該慎用。systemPath 元素可以引用環境變量。

image-20200617142301138

七、maven的構建命令

7.1 項目的構建過程

7.2 常用構建命令

一般命令的鍵入在IDEA中的框中鍵入命令就可以!

image-20200617170717904

命令 描述
mvn compile(常用) 編譯項目,生成target文件
mvn package(常用) 打包項目,生成war或jar文件
mvn clean(常用) 清理編譯或打包后的項目結構
mvn install(常用) 打包後上傳到Maven本地倉庫
mvn source:jar 打包項目,生成jar包
mvn deploy 只打包,不測試
mvn site 生成站點
mvn test 執行測試源碼

7.3 maven項目的生命周期

maven項目的生命周期分為了三個階段,而這三個階段相互獨立、互不影響

  1. 清理生命周期(Clean Lifecycle): 該生命周期負責清理項目中多餘信息,保持資源和代碼的整潔性。一般用來清空目錄下的文件
  2. 默認構建生命周期(Default Lifeclyle): 該生命周期表示項目的構建過程,其中定義了一個項目構建要經歷的不同階段
  3. 站點管理生命周期(Site Lifecycle): site生命周期的目的是建立和發布項目站點,Maven能夠基於POM所包含的信息,自動生成一個友好的站點

clean

該生命周期主要是對項目編譯生成的文件進行清理,清理的話主要是清理編譯後項目中的target文件夾,清理后還可以通過編譯指令重新生成。

  • 命令: mvn clean

default

該生命周期的主要目的是項目的編譯 -> 測試 -> 打包 -> 發布

  • 命令: mvn deploy
  • 其中default生命周期分為23個階段,如下列舉比較重要的幾個階段
  • validate:驗證工程是否正確,所有需要的資源是否可用。
  • compile:編譯項目的源代碼。
  • test:使用合適的單元測試框架來測試已編譯的源代碼。這些測試不需要已打包和布署。
  • Package:把已編譯的代碼打包成可發布的格式,比如jar。
  • integration-test:如有需要,將包處理和發布到一個能夠進行集成測試的環境。
  • verify:運行所有檢查,驗證包是否有效且達到質量標準。
  • install:把包安裝到maven本地倉庫,可以被其他工程作為依賴來使用。
  • Deploy:在集成或者發布環境下執行,將最終版本的包拷貝到遠程的repository,使得其他的開發者或者工程可以共享。

site

該生命周期的主要是建立和發布項目站點,Maven能夠基於POM所包含的信息,自動生成一個友好的站點

  • 命令: mvn site

注意: 低版本的site插件可能引發失敗現象!升級高版本site插件即可!

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-site-plugin</artifactId>
  <version>3.7.1</version>
</plugin>

7.4 maven命令與插件的關係

maven命令是操作maven項目的重要方式,但是我們要知道maven命令只是支配maven插件工作的一個方式,其工作核心主要還是maven插件。maven內嵌了項目操作的插件,我們只需要通過執行命令來調用插件來完成項目的編譯、測試、發布等工作

注意: 執行一次命令可能會觸發多個插件工作

八、傳遞依賴和衝突解決

8.1 什麼是傳遞依賴

假如有Maven項目A,項目B依賴A,項目C依賴B。那麼我們可以說 C依賴A。也就是說,依賴的關係為:C – > B – > A, 那麼我們執行項目C時,會自動把B、A都下載導入到C項目的jar包文件夾中,這就是依賴的傳遞性。

8.2 什麼是依賴衝突

依賴衝突我在上文中也提到過,依賴衝突是當直接引用或者間接引用出現了相同的jar包擁有不同版本的時候。

舉個例子:A依賴於B,B依賴於C,此時C的版本為V1.0;如果此時引入的C依賴還有一個V2.0,那麼我們的A傳遞依賴於C,此時C的版本為V2.0。這時候就是一個衝突,直接或間接的都引用了C,而C版本有兩個!

8.3 手動解決依賴衝突

如果我不想在C依賴中出現B,那麼就可以主動的使用依賴排除技術,排除B依賴的引用,如下操作需要添加排除依賴的配置信息(<exclusions>標籤和其中信息,其中兩個id標籤是需要排除依賴的id):

     <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.12.RELEASE</version>

            <!--手動排除依賴-->
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>

        </dependency>
     </dependencies>

8.4 自動解決依賴衝突

8.4.1 自動解決依賴衝突的途徑

自動解決依賴通途問題的兩個途徑分為:短路優先原則先聲明優先原則

8.4.2 短路優先原則

首先,先看如下依賴關係

  1. A – > B – > C – > D – > E(V1.0)
  2. A – > F – > E(V2.0)

解釋: 1中,A依賴於B,B依賴於C,C依賴於D,D依賴於E,此時E的版本為V1.0版本(2中解釋基本相似)

所謂短路優先,就是路徑段的依賴有限被加載使用,這裏我們可以看到2中的路徑是最短的路徑,所以maven在加載依賴的時候,是使用2中的這一條依賴和版本

8.4.3 先聲明優先原則

針對依賴路徑長度相同的情況,則使用先聲明優先原則,看如下依賴關係

  1. A – > B – > C(V1.0)
  2. A – > D – > C(V2.0)

此時路徑優先原則不能解決問題時,maven需要判斷在A項目的<depencies>標籤內,B和D的哪個依賴聲明在前面,如果B依賴聲明早於D依賴,那麼就使用1中的這一條依賴和版本

微信公眾號 本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司“嚨底家”!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

Spring系列.事務管理

Spring提供了一致的事務管理抽象。這個抽象是Spring最重要的抽象之一, 它有如下的優點:

  • 為不同的事務API提供一致的編程模型,如JTA、JDBC、Hibernate和MyBatis數據庫層 等;
  • 提供比大多數事務API更簡單的,易於使用的編程式事務管理API;
  • 完美整合Spring數據訪問抽象;
  • 支持Spring聲明式事務管理;

這篇博客就來介紹Spring事務管理相關的內容。

事務簡介

什麼是事務

事務(Transaction)一般是指對數據庫的一個或一組操作單元。

事務的作用

1、為數據庫操作提供了一個從失敗中恢復到正常狀態的方法,同時提供了數據庫即使在異常狀態下仍能保持一致性的方法。
2、當多個應用程序在併發訪問數據庫時,可以在這些應用程序之間提供一個隔離方法,以防止彼此的操作互相干擾。

當一個事務被提交給了DBMS(數據庫管理系統),則DBMS需要確保該事務中的所有操作都成功完成且其結果被永久保存在數據庫中,如果事務中有的操作沒有成功完成,則事務中的所有操作都需要被回滾,回到事務執行前的狀態(要麼全執行,要麼全都不執行);同時,該事務對數據庫或者其他事務的執行無影響,所有的事務都好像在獨立的運行。

事務的特點

事務具有4個屬性:原子性、一致性、隔離性、持久性。這四個屬性通常稱為ACID特性。

原子性(Atomicity):事務作為一個整體被執行,包含在其中的對數據庫的操作要麼全部被執行,要麼都不執行。
一致性(Consistency):事務應確保數據庫的狀態從一個一致狀態轉變為另一個一致狀態。一致狀態的含義是數據庫中的數據應滿足完整性約束。
隔離性(Isolation):多個事務併發執行時,一個事務的執行不應影響其他事務的執行。
持久性(Durability):一個事務一旦提交,他對數據庫的修改應該永久保存在數據庫中。

事務的隔離級別

在多個事務併發操作的過程中,如果控制不好隔離級別,就有可能產生臟讀、不可重複讀或者幻讀等讀現象。數據操作過程中利用數據庫的鎖機制或者多版本併發控制機制獲取更高的隔離等級。但是,隨着數據庫隔離級別的提高,數據的併發能力也會有所下降。所以,如何在併發性和隔離性之間做一個很好的權衡就成了一個至關重要的問題。

ANSI/ISO SQL定義的標準隔離級別有四種,從高到底依次為:可序列化(Serializable)、可重複讀(Repeatable reads)、提交讀(Read committed)、未提交讀(Read uncommitted)。

  1. 讀未提交
    未提交讀(READ UNCOMMITTED)是最低的隔離級別。通過名字我們就可以知道,在這種事務隔離級別下,一個事務可以讀到另外一個事務未提交的數據。未提交讀會導致臟讀

事務在讀數據的時候並未對數據加鎖。

務在修改數據的時候只對數據增加行級共享鎖。

  1. 讀已提交
    提交讀(READ COMMITTED)也可以翻譯成讀已提交,通過名字也可以分析出,在一個事務修改數據過程中,如果事務還沒提交,其他事務不能讀該數據。讀已提交會導致不可重複讀

事務對當前被讀取的數據加 行級共享鎖(當讀到時才加鎖),一旦讀完該行,立即釋放該行級共享鎖;
事務在更新某數據的瞬間(就是發生更新的瞬間),必須先對其加 行級排他鎖,直到事務結束才釋放。

  1. 可重複讀
    可重複讀能保障一個事務在事務內讀到的某條數據是一致的。但是可重複讀不能解決幻讀的問題。就是在事務還沒結束時,其他事務又插入了一條新的數據。

事務在讀取某數據的瞬間(就是開始讀取的瞬間),必須先對其加 行級共享鎖,直到事務結束才釋放;
事務在更新某數據的瞬間(就是發生更新的瞬間),必須先對其加 行級排他鎖,直到事務結束才釋放

  1. 序列化
    可序列化(Serializable)是最高的隔離級別,前面提到的所有的隔離級別都無法解決的幻讀,在可序列化的隔離級別中可以解決。

事務在讀取數據時,必須先對其加 表級共享鎖 ,直到事務結束才釋放;
事務在更新數據時,必須先對其加 表級排他鎖 ,直到事務結束才釋放。

下面是臟讀、不可重複讀和幻讀的解釋。

臟讀就是指當一個事務正在訪問數據,並且對數據進行了修改,而這種修改還沒有提交(commit)到數據庫中,這時,另外一個事務也訪問這個數據,然後使用了這個數據。因為這個數據是還沒有提交的數據,那麼另外一個事務讀到的這個數據是臟數據,依據臟數據所做的操作可能是不正確的。
不可重複讀:在一個事務內,多次讀同一個數據。在這個事務還沒有結束時,另一個事務也訪問該同一數據。那麼,在第一個事務的兩次讀數據之間。由於第二個事務的修改,那麼第一個事務讀到的數據可能不一樣,這樣就發生了在一個事務內兩次讀到的數據是不一樣的,因此稱為不可重複讀,即原始讀取不可重複。
幻讀指的是一個事務在前後兩次查詢同一個範圍的時候,后一次查詢看到了前一次查詢沒有看到的數據行。幻讀專指“新插入的行”是不可重複讀(Non-repeatable reads)的一種特殊場景

Spring事務

Spring事務模型的優勢

事務可以分為本地事務和全局事務,這兩種事務都有一定程度的局限性,Spring框架的事務管理支持解決全局和本地事務模型的局限性。

1. 全局事務
全局事務可以讓你跨多個事務進行工作,比如你的事務同事包含多個關係型數據庫,也可以包含關係型數據庫和JMS事務。一般情況下都是通過JTA來實現全局事務,但是JTA一般需要具體的應用容器來支持,這就導致代碼的通用性較低。

下面舉個全局事務的列子,方便理解。

在電商網站上,在消費者點擊購買按鈕后,交易後台會進行庫存檢查、下單、減庫存、更新訂單狀態等一連串的服務調用,每一個操作對應一個獨立的服務,服務一般會有獨立的數據庫,因此會產生分佈式事務問題。分佈式事務就是一種比較常見的全局事務。

2. 本地事務

本地事務和具體的某個事務關聯,比如說JDBC事務。本地事務比較簡單,但是不能實現分佈式事務的功能。

Spring提供了統一方便的事務編程模型,可以解決上面本地事務和全局事務的局限。使用Spring的事務API進行事務管理,底層可以適應各種事務資源。

Spring事務抽象

Spring為提供統一的事務編程模型,提供相關的接口。主要接口如下:

public interface PlatformTransactionManager {

    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

    void commit(TransactionStatus status) throws TransactionException;

    void rollback(TransactionStatus status) throws TransactionException;
}

上面接口的getTransaction方法接收一個TransactionDefinition參數,返回一個TransactionStatus 值。其中TransactionStatus 可能代表一個新的事務,或者返回一個已經存在本次調用棧中的事務。(TransactionStatus 和具體的線程綁定。可以自己寫代碼測試下)

TransactionStatus接口定義如下。

public interface TransactionStatus extends SavepointManager {

    boolean isNewTransaction();

    boolean hasSavepoint();

    void setRollbackOnly();

    boolean isRollbackOnly();

    void flush();

    boolean isCompleted();
}

聲明式事務管理

使用Spring的事務管理,推薦使用聲明式事務管理。Spring的聲明式事務管理是通過Spring的AOP功能實現的。

因為平時在開發過程中都是使用註解的方式使用聲明式事務。下面就介紹註解的方式。

step1:添加@EnableTransactionManagement註解

@Configuration
@EnableTransactionManagement
@MapperScan("com.csx.demo.spring.boot.dao")
public class MyBatisConfig {

}

step2:添加@Transactional註解到接口的實現。

@Service
@Transactional(readOnly = true,rollbackFor = Exception.class)
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public int saveSysUser(SysUser user) {
        int i = sysUserMapper.insert(user);
        return i;
    }
}

使用Spring的聲明式事務就這麼簡單。

當你使用Spring的AOP方式來使用事務的話,你添加@Transactional註解的方法一定要是public的,不然事務不會生效。

假如你需要讓非public的方法生效,你需要使用AspectJ 的AOP實現。(說明:Spring的AOP功能有兩種實現方式,一種是Spring自己實現的AOP功能,主要是通過JDK動態代理或者CGLIB動態代理實現的。還有一種方式是整合AspectJ 這個第三方AOP框架實現的)

另外,@Transactional註解可以添加到接口、接口中的方法定義、類和類裏面的方法。Spring團隊建議將註解加到具體的類和方法實現上,而不是加到接口定義上(原因見下面英文描述)。當然,您可以將@Transactional註釋放在接口(或接口方法)上,但是只有在使用基於接口的代理時,才會像您期望的那樣工作。

The fact that Java annotations are not inherited from interfaces means that, if you use class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj"), the transaction settings are not recognized by the proxying and weaving infrastructure, and the object is not wrapped in a transactional proxy.

@Transactional註解的配置

@Transactional註解可以進行以下配置。

Property Type Description
value String 一個項目中可以存在多個事務管理器,這個值用於指定具體使用哪個事務管理器。
propagation enum: Propagation 設置傳播機制
isolation enum: Isolation 設置隔離級別(只有當傳播機制設置成 REQUIRED or REQUIRES_NEW時這個配置才生效)
timeout int (in seconds of granularity) 設置超時時間(以秒為單位,只有當傳播機制設置成 REQUIRED or REQUIRES_NEW時這個配置才生效)
readOnly boolean 只讀事務配置(只有當傳播機制設置成 REQUIRED or REQUIRES_NEW時這個配置才生效)
rollbackFor Array of Class objects, which must be derived from Throwable. 回滾的異常
rollbackForClassName Array of class names. The classes must be derived from Throwable.
noRollbackFor Array of Class objects, which must be derived from Throwable. 不回滾的異常
noRollbackForClassName Array of String class names, which must be derived from Throwable.

假如我們沒有配置上面的屬性,這些屬性也都是有默認值的

  • The propagation setting is PROPAGATION_REQUIRED.
  • The isolation level is ISOLATION_DEFAULT.
  • The transaction is read-write.
  • The transaction timeout defaults to the default timeout of the underlying transaction system, or to none if timeouts are not supported.
  • Any RuntimeException triggers rollback, and any checked Exception does not.(默認回滾RuntimeException )

多事務管理器

有時候項目中可能會存在多個事務管理器,比如JDBC事務,比如JMS事務。這時候我們可以通過transactionManager屬性指定。

public class TransactionalService {

    @Transactional("jdbc")
    public void setSomething(String name) { ... }

    @Transactional("jms")
    public void doSomething() { ... }
}

上面的jdbc和jms是指兩個事務管理器在Spring容器中Bean的名字。

事務的傳播機制

在TransactionDefinition這個類中定義了6中傳播機制的類型。

1. PROPAGATION_REQUIRED

2. PROPAGATION_REQUIRES_NEW

3. PROPAGATION_NESTED

只支持JDBC事務。

編程式事務管理

Spring框架提供兩種方式來進行編程式事務管理:

  • The TransactionTemplate.
  • PlatformTransactionManager 的實現。

Spring團隊推薦使用第一種方式進行編程式事務管理。

1. 使用TransactionTemplate進行事務管理

下面是使用TransactionTemplate進行事務管理的一個例子。

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = TxApp.class)
public class TxTest {

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Test
    public void selectUserTest() {

        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        //同一個sqlSession創建的Mapper
        SysUserMapper mapper = sqlSession1.getMapper(SysUserMapper.class);
        SysUser sysUser = new SysUser();
        sysUser.setUsername("zyzl");
        sysUser.setPassword("11");

        //有返回值的操作
        transactionTemplate.execute(new TransactionCallback() {
            @Override
            public Object doInTransaction(TransactionStatus status) {
                try {
                    return mapper.insert(sysUser);
                } catch (Exception e) {
                    status.setRollbackOnly();
                    throw e;
                }
            }
        });

        //沒返回值的操作
        transactionTemplate.executeWithoutResult(new Consumer<TransactionStatus>() {
            @Override
            public void accept(TransactionStatus transactionStatus) {
                try {
                    mapper.insert(sysUser);
                } catch (Exception e) {
                    transactionStatus.setRollbackOnly();
                    throw e;
                }
            }
        });
    }

}

我們也可以通過TransactionTemplate來設定事務的隔離級別等屬性。

//設置隔離級別
transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
//設置超時時間
transactionTemplate.setTimeout(30);
//設置傳播機制
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

對於不同的事務操作,如果需要不同的隔離級別和傳播機制的話,請使用不同的transactionTemplate。也就是說,你要創建不同的transactionTemplate對象來進行操作。

2. 使用PlatformTransactionManager進行事務管理

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// explicitly setting the transaction name is something that can be done only programmatically
def.setName("SomeTxName");
// 設置傳播機制
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//開啟事務
TransactionStatus status = txManager.getTransaction(def);
try {
    // execute your business logic here
}
catch (MyException ex) {
    txManager.rollback(status);
    throw ex;
}
//提交事務
txManager.commit(status);

事務綁定事件

使用@TransactionalEventListener可以在事務提交前後,回滾后等階段觸發某些操作。但是這個功能暫時還沒想到很好的使用場景。後續有需要再來用。

@Component
public class MyComponent {

    @TransactionalEventListener
    public void handleOrderCreatedEvent(CreationEvent<Order> creationEvent) {
        // ...
    }
}

重要類和接口

  • PlatformTransactionManager:事務管理器,用於獲取事務,提交回滾事務;
  • TransactionDefinition:
  • TransactionStatus:代表一個事務

進一步閱讀

Distributed transactions in Spring, with and without XA is a JavaWorld presentation in which Spring’s David Syer guides you through seven patterns for distributed transactions in Spring applications, three of them with XA and four without.(Spring實現分佈式事務的介紹)

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

聚甘新

【巴塞爾公約】嚴控全球塑膠垃圾轉移,發展中國家齊說「YES」

轉載自塑料解毒;翻譯:許冰;校對:毛達

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司“嚨底家”!

※推薦評價好的iphone維修中心

聚甘新

法國新任環境部長:不排除改組法電公司

摘錄自2018年9月10日法廣報導

法國世界報在本周一(10日)發布了一篇對法國新任環境部長德魯吉的專訪,其中數點提到了法國電力公司。

法電公司此前一直要求政府儘快落實法國境內新一座壓水反應堆核電廠的建造。對此,德魯吉不置可否,但強調「法電公司首先要證明,壓水反應堆核電廠是能用的,現在情況沒有體現出來壓水反應堆核電廠可用,沒人能保證現有的壓水反應堆核電廠什麼時候能啟動。法電公司還需要證明,壓水反應堆核電廠在費用方面具有競爭力。」德魯吉表示,無論如何,除了法國最老舊的,仍然運轉的核電廠費森海姆被關閉之外,要關閉的核電廠還有很多。法國將在今年10月底公布系列核電廠反應堆的關閉日程表。

對於辭職的前任環境部長於洛曾經提到的改組法電公司的可能性,新任環境部長德魯吉表示,已經對改組與否有了想法。他表示,法電公司不僅要進行能源轉型,而且要關注企業債務問題。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

聚甘新

日本提議取消捕鯨禁令 保育組織斥危險又魯莽

摘錄自2018年9月10日自由時報報導

日本將在今年的國際捕鯨委員會(IWC)會議上,提議取消32年前制定的商業捕鯨禁令,希望建立「可持續捕鯨委員會」為商業捕鯨國家制定捕撈配額。保育人士憤怒表示,日本企圖公然推翻一直以來維持的狩獵禁令,若通過日本的提議,會導制危險的商業捕鯨行為。

《法新社》報導,為期一週的國際捕鯨委員會第67屆會議本週一(10日)在巴西弗洛里亞諾波利斯(Florianopolis)舉行,日本將提議廢止捕鯨禁令,稱小鬚鯨和其他鯨魚等總量已經恢復,建議IWC認同將恢復數量的物種訂定新的捕撈配額,建立「可持續捕鯨委員會」,替允許國民商業捕鯨的國家制定相關配額。日本還指出,實施捕鯨禁令不只是為了保育,也是為了再度開放捕鯨。

英國國際人道協會(HSI UK)也說,如果日本提案通過,將再次開放捕鯨季節,這會是幾十年來,最危險和魯莽企圖的商業捕鯨行為。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

聚甘新

建立台灣建築節能經驗:政策循序漸進  技術在地試驗

環境資訊中心特約記者 陳文姿報導

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

※教你寫出一流的銷售文案?

聚甘新

美研究:種植水稻產生溫室氣體被低估 包括中國

摘錄自2018年9月12日新華網報導

美國《國家科學院學報》前(10)日刊載的一項研究顯示,如把一氧化二氮排放考慮在內,水稻種植對全球變暖的影響可能比此前估計水平高出近一倍。

然而,包括中國、美國、印度在內的多數水稻生産國,目前都沒有將與水稻種植有關的一氧化二氮排放計入向聯合國提交的國家溫室氣體排放清單中。

美國環境保護基金組織的研究稱,近年來,水資源短缺導致越來越多的地區採用間歇性淹水法種植水稻,但在分析稻田對氣候的影響時,間歇性淹水稻田釋放的高水平一氧化二氮此前並未被計算在內,導致水稻種植對全球變暖的影響被嚴重低估。

一氧化二氮,又稱氧化亞氮,是重要的長效溫室氣體。在20年到100年時段中,其捕獲大氣熱量的能力是甲烷的數倍。最新研究顯示,間歇性淹水稻田釋放的一氧化二氮水平高達持續性淹水稻田的30到45倍,後者釋放的主要溫室氣體是甲烷。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司“嚨底家”!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

MIT 認為核電不可或缺,小型模組式核反應爐為發展重點

摘錄自2018年9月12日科技新報美國報導

麻省理工能源研究計畫(MITEI)最新研究,若要在低成本與對社會影響低的情況下實現低碳未來,核能是不可或缺的元素之一,建議應捨棄傳統的大型電廠,發展成本低與裝置更靈活的小型模組式核反應爐。

先前美國核能管理委員會(NRC)也放行英商 NuScale Power 的模組式反應爐的第一階段審核,根據官網資料,該小型核反應爐大小 23×5 公尺,重量僅 700 公噸,熱容量達 160 MWt、可產生 50 MW 電力,其發電性能不差、體積更是遠比傳統的核反應爐還要小。

處於實驗室階段的第四代核電廠行波反應爐也屬於模組式設計,製造成本則比傳統核反應爐更加便宜,有別於 LWR 等前幾代核技術,行波反應爐不需要濃縮鈾,使用核廢料貧化鈾就可以運行,自產的核廢料也能回收利用。假如該技術成功跨出商業化門檻,核廢料問題將可大大減少。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

聚甘新

第二屆中國重慶國際電動汽車產業展

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司“嚨底家”!

※推薦評價好的iphone維修中心

聚甘新

2017第八屆廣州國際新能源汽車工業展覽會

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

聚甘新