Thrift在Tomcat中以Servlet執行
阿新 • • 發佈:2019-01-22
建立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);
}
}