1. 程式人生 > >【maven】maven-thrift-plugin 外掛使用 + Java專案中thrift使用的正確姿勢

【maven】maven-thrift-plugin 外掛使用 + Java專案中thrift使用的正確姿勢

1.首先介紹下maven-thrift-plugin外掛在java中使用

該外掛可以讓我們在maven中使用 編譯.thrift檔案,在大型專案中尤其有用。下面看下如何使用:

假設這裡要提供一個HelloService的thrift服務:

namespace java com.liyao.service
service HelloService{
    string helloString(1:string para)
}

然後新建一個maven的專案,在src/main下新建一個thrift的目錄存放我們的所有.thrift檔案,然後在該目錄下新建上面的HelloService.thrift。目錄結構如下:


接著需要在pom中匯入依賴和編譯的外掛。

(1)因為我們這裡要生成thrift對應的java檔案,所以一定要匯入thrift相關的依賴,也就是libthrift的jar包;

(2)原生的maven並不會為我們編譯thrift檔案,所以需要在build中加入maven-thrift-plugin外掛;

所以maven的pom檔案如下:

<?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.liyao</groupId>
  <artifactId>thrift_plugin_project</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>thrift_project</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <!-- https://mvnrepository.com/artifact/org.apache.thrift/libthrift -->
    <dependency>
      <groupId>org.apache.thrift</groupId>
      <artifactId>libthrift</artifactId>
      <version>0.9.3</version>
    </dependency>
  </dependencies>

  <build>
      <plugins>
          <plugin>
              <groupId>org.apache.thrift.tools</groupId>
              <artifactId>maven-thrift-plugin</artifactId>
              <version>0.1.11</version>
              <configuration>
                  <!--<thriftExecutable>/usr/local/bin/thrift</thriftExecutable>-->
                  <!--<thriftSourceRoot>src/main/thrift</thriftSourceRoot>-->
                  <!--<outputDirectory>src/main/java</outputDirectory>-->
              </configuration>
              <executions>
                  <execution>
                      <id>thrift-sources</id>
                      <phase>generate-sources</phase>
                      <goals>
                          <goal>compile</goal>
                      </goals>
                  </execution>
                  <!--<execution>-->
                      <!--<id>thrift-test-sources</id>-->
                      <!--<phase>generate-test-sources</phase>-->
                      <!--<goals>-->
                          <!--<goal>testCompile</goal>-->
                      <!--</goals>-->
                  <!--</execution>-->
              </executions>
          </plugin>
      </plugins>
  </build>
</project>

在外掛部分,我們執行了外掛的compile目標,並且將其繫結在generate-sources階段。

為什麼要繫結在這個階段?而不是compile階段呢?因為我們thrift外掛的作用是生成java檔案,而在maven執行compile階段時,java檔案必須生成完畢才能進行編譯,因此,該外掛的執行必須在compile之前,所以放在generate-sources階段比較合適。

我們可以為外掛做一些配置:

thriftExecutable,指的是thrift編譯器的位置,如果我們配置了環境變數,可以不指定。驗證環境變數可以使用thrift --version命令。

thriftSourceRoot,thrift原始檔的目錄,預設會從src/main/thrift下讀取。

outputDirectory,生成java檔案的目錄。其實這個一般不需要配置,因為java檔案的包名是在.thrift檔案以namespace的形式定義的。

所以上面的pom檔案沒有做任何配置。

接著執行:

mvn clean install 命令即可生成一個jar包。


隨後,我們就可以在自己的專案中通過依賴的方式引入生成的java檔案。

再新建一個專案,該專案使用之前的jar檔案:

pom:

<?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.liyao</groupId>
    <artifactId>thrift_project</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>thrift_project</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.liyao</groupId>
            <artifactId>thrift_plugin_project</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.thrift/libthrift -->
        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.9.3</version>
        </dependency>
    </dependencies>
</project>

服務實現類:

import com.liyao.service.HelloService;
import org.apache.thrift.TException;

public class HelloServiceImpl implements HelloService.Iface {
    @Override
    public String helloString(String s) throws TException {
        return s;
    }
}

啟動服務:

import com.liyao.service.HelloService;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;

public class Server {
    public static void main(String args[]){
        try {
            System.out.println("服務端開啟....");
            TProcessor tprocessor = new HelloService.Processor<HelloService.Iface>(new HelloServiceImpl());
            TServerSocket serverTransport = new TServerSocket(50005);
            TServer.Args tArgs = new TServer.Args(serverTransport);
            tArgs.processor(tprocessor);
            tArgs.protocolFactory(new TBinaryProtocol.Factory());
            TServer server = new TSimpleServer(tArgs);
            server.serve();
        }catch (TTransportException e) {
            e.printStackTrace();
        }
    }
}

客戶端測試:

import com.liyao.service.HelloService;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

public class Client {

    public static void main(String[] args) {
        System.out.println("客戶端啟動....");
        TTransport transport = null;
        try {
            transport = new TSocket("localhost", 50005);
            TProtocol protocol = new TBinaryProtocol(transport);
            HelloService.Client client = new HelloService.Client(protocol);
            transport.open();
            String result = client.helloString("liyao");
            System.out.println(result);
        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            if (null != transport) {
                transport.close();
            }
        }
    }
}

2.Java專案中使用thrift:

第一次學習java thrift的時候,我們都是手動執行thrift編譯器,然後把生成的java檔案複製進自己的專案中使用。但是這種方式在大型專案中不可取。

一是因為thrift編譯器的執行操作應該放在公共的機器上而不是每一個開發者在本地執行,本地執行可能導致很多不一致問題,如版本等。

二是從開發角度來說,thrift檔案本質定義的是一個介面,介面的實現方和使用方可能會同時開發,那麼比較好的流程是,雙方約定好thrift的介面和引數,然後由一方編寫thrift檔案,雙方評審,通過之後,把thrift檔案按照開始介紹的方式打成jar包再部署到maven的倉庫中。當然這個過程可能會引入版本控制等過程,可以把所有的thrift介面放在一個公共的專案中。如果新增一個介面,git會新增一個版本,然後通過部署工具部署到生產環境,部署工具後臺會執行maven的一命令,把生成的jar檔案部署到maven倉庫。這樣,雙方在各自的專案中只需要以dependence的方式引入介面的jar包,各自開發即可,互不影響。

順便記錄關鍵部分:

***************************
*** ONGOING MAINTENANCE ***
***************************

PLEASE NOTE: THIS CODE HAS BEEN CONTRIBUTED BACK TO ASF.

https://issues.apache.org/jira/browse/THRIFT-1536

Any future work I do on this plugin, will be as patches submitted to their version.
I am not planning to perform any further maintenance on this fork (or accept any patches / pull requests).

***********************
*** VERSION WARNING ***
***********************

Drop to the command line and type:

 thrift -version

To find out what version of the compiler you are using.


Older Compiler Versions (Less than 0.7.0)
===
You must use version 0.1.10 of this plugin.
+ Check out the source.
+ Switch to the old branch: git checkout -b old maven-thrift-plugin-0.1.10

And build/use that version.



Newer Compiler Versions (0.7.0 or newer)
===
0.7.0 should work fine with the latest version of this plugin.
However I have seen incompatibilities between the compiler and libthrift.

To resolve these check out the source for the compiler from the 0.7.0 branch (Do not trust the TAR BALLS)

svn co http://svn.apache.org/repos/asf/thrift/tags/thrift-0.7.0

That version should work fine with the maven version of lib thrift:

        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.7.0</version>
        </dependency>


Note: If you have problems building on OSX you might want to look at this article:

http://lueb.be/2009/02/23/installing-apache-thrift-on-mac-os-x-105-leopard/

The fastest way to build the compiler is:

$ svn co http://svn.apache.org/repos/asf/thrift/tags/thrift-0.7.0
$ cd thrift-0.7.0
$ cp /usr/X11/share/aclocal/pkg.m4 aclocal/
$ ./bootstrap.sh
$ ./configure
$ cd compiler/cpp/
$ make



***************************
*** Maven Thrift Plugin ***
***************************

A minimal configuration to invoke this plugin would be:

<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/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany.example</groupId>
    <artifactId>example-thrift</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>thrift-example</name>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.thrift.tools</groupId>
                <artifactId>maven-thrift-plugin</artifactId>
                <version>0.1.10</version>
                <configuration>
                    <thriftExecutable>/usr/local/bin/thrift</thriftExecutable>
                </configuration>
                <executions>
                    <execution>
                        <id>thrift-sources</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>thrift-test-sources</id>
                        <phase>generate-test-sources</phase>
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.5.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.5.8</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.14</version>
        </dependency>
    </dependencies>
</project>


You must:
+ Use Java 1.5 or newer due to the usage of Generics
+ Either ensure the "thrift" executable is in your PATH or set the
  <thriftExecutable> parameter to the correct location.
+ Define the executions you want (you probably don't need the testCompile
  unless you have custom thrift objects in your tests.
+ Include the dependencies on libthrift and slf4j or your compile will fail.


Once this is all done add your *.thrift files to the directory: src/main/thrift

Everything should then build with a: mvn clean install




You may also need to add the following to your settings.xml to download the
plugin:

            <pluginRepositories>
                <pluginRepository>
                    <id>dtrott</id>
                    <url>http://maven.davidtrott.com/repository</url>
                </pluginRepository>
            </pluginRepositories>