1. 程式人生 > >Thrift在Tomcat中以Servlet執行

Thrift在Tomcat中以Servlet執行

建立Servlet繼承自TServlet

以前在將Thrift服務在Tomcat中以Servlet執行時,需要自己實現協議轉換的“中間”Servlet,現在只需要繼承org.apache.thrift.server.TServlet就可以,(Thrift的基本知識在此不再冗述,讀者可自己檢視github。此處的例子基於其中的tutorial和shared示例)例項程式碼如下:
CalculatorServiceServlet.java

import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.
TServlet; public class CalculatorServiceServlet extends TServlet { public CalculatorServiceServlet() { super(new Calculator.Processor<>(new CalculatorHandler()), new TBinaryProtocol.Factory()); } }

注:
如果在請求的資料未到達Servlet前增加自定義的資料處理,可自己編寫繼承自HttpServlet類,替換TServlet,程式碼如下:

import
org.apache.thrift.TException; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TIOStreamTransport; import org.apache.thrift.transport.TTransport; public class TCommonServlet extends
HttpServlet { private final TProcessor processor; private final TProtocolFactory inProtocolFactory; private final TProtocolFactory outProtocolFactory; private final Collection<Entry<String, String>> customHeaders; public TCommonServlet(TProcessor processor, TProtocolFactory inProtocolFactory, TProtocolFactory outProtocolFactory) { this.processor = processor; this.inProtocolFactory = inProtocolFactory; this.outProtocolFactory = outProtocolFactory; this.customHeaders = new ArrayList(); } public TCommonServlet(TProcessor processor, TProtocolFactory protocolFactory) { this(processor, protocolFactory, protocolFactory); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { TTransport inTransport = null; Object var4 = null; //列印header中的內容 Enumeration enums = request.getHeaderNames(); while (enums.hasMoreElements()) { String key = (String) enums.nextElement(); System.out.println("key: " + key); System.out.println("value: " + request.getHeader(key)); } System.out.println("--------------"); try { response.setContentType("application/x-thrift"); if (null != this.customHeaders) { Iterator var5 = this.customHeaders.iterator(); while(var5.hasNext()) { Entry<String, String> header = (Entry)var5.next(); response.addHeader((String)header.getKey(), (String)header.getValue()); } } InputStream in = request.getInputStream(); OutputStream out = response.getOutputStream(); TTransport transport = new TIOStreamTransport(in, out); TProtocol inProtocol = this.inProtocolFactory.getProtocol(transport); TProtocol outProtocol = this.outProtocolFactory.getProtocol(transport); this.processor.process(inProtocol, outProtocol); out.flush(); } catch (TException var10) { throw new ServletException(var10); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void addCustomHeader(final String key, final String value) { this.customHeaders.add(new Entry<String, String>() { public String getKey() { return key; } public String getValue() { return value; } public String setValue(String valuex) { return null; } }); } public void setCustomHeaders(Collection<Entry<String, String>> headers) { this.customHeaders.clear(); this.customHeaders.addAll(headers); } }

CalculatorHandler.java

import org.apache.thrift.TException;

import java.util.HashMap;

public class CalculatorHandler implements Calculator.Iface {

    private HashMap<Integer, SharedStruct> log;

    public CalculatorHandler() {
        log = new HashMap<Integer, SharedStruct>();
    }

    @Override
    public void ping() throws TException {
        System.out.println("ping()");
    }

    @Override
    public int add(int num1, int num2) throws TException {
        System.out.println("add(" + num1 + "," + num2 + ")");
        return num1 + num2;
    }

    @Override
    public int calculate(int logid, Work w) throws InvalidOperation, TException {
        System.out.println("calculate(" + logid + ",{" + w.op + "," + w.num1 + "," + w.num2 + "})");
        int val = 0;
        switch (w.op) {
            case ADD:
                val = w.num1 + w.num2;
                break;
            case SUBTRACT:
                val = w.num1 - w.num2;
                break;
            case MULTIPLY:
                val = w.num1 * w.num2;
                break;
            case DIVIDE:
                if (w.num2 == 0) {
                    InvalidOperation io = new InvalidOperation();
                    io.whatOp = w.op.getValue();
                    io.why = "Cannot divide by 0";
                    throw io;
                }
                val = w.num1 / w.num2;
                break;
            default:
                InvalidOperation io = new InvalidOperation();
                io.whatOp = w.op.getValue();
                io.why = "Unknown operation";
                throw io;
        }
        SharedStruct entry = new SharedStruct();
        entry.key = logid;
        entry.value = Integer.toString(val);
        log.put(logid, entry);
        return 0;
    }

    @Override
    public void zip() throws TException {
        System.out.println("zip()");
    }

    @Override
    public SharedStruct getStruct(int key) throws TException {
        System.out.println("getStruct(" + key + ")");
        return log.get(key);
    }
}

web.xml

    <servlet>
        <servlet-name>CalculatorServiceServlet</servlet-name>
        <servlet-class>xxx.servlets.CalculatorServiceServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>CalculatorServiceServlet</servlet-name>
        <url-pattern>/CalculatorService</url-pattern>
    </servlet-mapping>

編譯打包成war包,部署到Tomcat中即可。客戶端程式碼如下:
Client.java

import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.THttpClient;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

public class ClientApp {

    public static void main(String[] args) {

        try {
            //TTransport transport = new TSocket("localhost", 9090); //訪問Thrift server
            //transport.open();
            THttpClient httpClient = new THttpClient("http://localhost:8080/CalculatorService"); //訪問Tomcat中Servlet


            TProtocol protocol = new TBinaryProtocol(httpClient);
            Calculator.Client client = new Calculator.Client(protocol);

            perform(client);
            //transport.close(); //
            httpClient.close();
        } catch (TTransportException tranx) {
            tranx.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        }
    }

    public static void perform(Calculator.Client client) throws TException {
        client.ping();
        System.out.println("ping()");

        int sum = client.add(1, 2);
        System.out.println("1+2=" + sum);

        Work work = new Work();
        work.op = Operation.DIVIDE;
        work.num1 = 1;
        work.num2 = 0;

        try {
            int quotient = client.calculate(1, work);
            System.out.println("Whoa we can divide by 0");
        } catch (InvalidOperation io) {
            System.out.println("Invalid operation: " + io.why);
        }

        work.op = Operation.SUBTRACT;
        work.num1 = 15;
        work.num2 = 10;

        try {
            int diff = client.calculate(1, work);
            System.out.println("15-10=" + diff);
        } catch (InvalidOperation io) {
            System.out.println("Invalid operation: " + io.why);
        }

        SharedStruct log = client.getStruct(1);
        System.out.println("Check log: " + log.value);
    }
}