2014-06-05 28 views
0

我有一個使用TServlet類通過HTTP公開7個不同Apache Thrift servlet的系統(Java with Spring Framework)。目前,他們都需要自己的Servlet,ServletMappings,Processors,Handlers等,因此實現客戶端也必須保存不同服務的所有各種URL的內部列表。使用Apache Thrift和TServlet執行服務多路複用

據我所知,阿帕奇節儉使用TServer及其衍生物使用TMultiplexingProcessor當支持複用,但是因爲我使用Spring和我的servlet,處理程序和處理器是得到自動連接到彼此所有的Spring Bean,我不知道該如何繼續。

這裏的服務的一個如何得到有線了一個例子:

UserServiceHandler.java

@Component 
public class UserServiceHandler implements UserService.Iface { 
    @Override 
    public User getUser(String userId) throws TException { 
     // implementation logic goes here 
    } 
} 

UserServiceProcessor.java

@Component 
public class UserServiceProcessor extends UserService.Processor<UserServiceHandler> { 

    private UserServiceHandler handler; 

    @Autowired 
    public UserServiceProcessor(UserServiceHandler iface) { 
     super(iface); 
     handler = iface; 
    } 

    public UserServiceHandler getHandler() { 
     return handler; 
    } 

    public void setHandler(UserServiceHandler handler) { 
     this.handler = handler; 
    } 

} 

UserServiceServlet.java

@Component 
public class UserServiceServlet extends TServlet { 
    private UserServiceProcessor processor; 

    @Autowired 
    public UserServiceServlet(UserServiceProcessor p) { 
     super(p, new TBinaryProtocol.Factory()); 
     processor = p; 
    } 
} 

Servlet的註冊

ServletRegistration.Dynamic userService = servletContext.addServlet("UserServiceServlet", (UserServiceServlet) ctx.getBean("userServiceServlet")); 
userService.setLoadOnStartup(1); 
userService.addMapping("/api/UserService/*"); 
// This same block repeated 7 times for each *ServiceServlet with different mappings 

我想有所有7個服務處理程序映射到一個URL像/api/*。這甚至有可能嗎?我想我將不得不創建一個單獨的servlet和處理器,但我不確定它們應該是什麼樣子。我的處理器擴展了UserService.Processor等。

回答

1

好的,想通了。可能不是最好的方式,所以我歡迎批評。

這裏是我的粗略步驟:

  1. 保持處理類,他們的方式。
  2. 創建擴展TMultiplexedProcessor
  3. 創建擴展TServlet
  4. 所有處理器的新類的新類(例如UserServiceProcessorhandler性質和相應的getter和setter

這裏是我的ApiMultiplexingProcessor

@Component 
public class ApiMultiplexingProcessor extends TMultiplexedProcessor { 

    UserServiceHandler userServiceHandler; 
    ReportServiceHandler reportServiceHandler; 
    // ... more service handlers can go here 

    @Autowired 
    public ApiMultiplexingProcessor(UserServiceProcessor userServiceProcessor, ReportServiceProcessor reportServiceProcessor) { 
     this.registerProcessor("UserService", userServiceProcessor); 
     this.registerProcessor("ReportService", reportServiceProcessor); 
     // add more registerProcessor lines here for additional services 

     userServiceHandler = userServiceProcessor.getHandler(); 
     reportServiceHandler = reportServiceProcessor.getHandler(); 
     // set any additional service handlers here 
    } 

    // getters and setters for the handlers 

    public UserServiceHandler getUserServiceHandler() { 
     return userServiceHandler; 
    } 

    public void setUserServiceHandler(UserServiceHandler userServiceHandler) { 
     this.userServiceHandler = userServiceHandler; 
    } 

    public ReportServiceHandler getReportServiceHandler() { 
     return reportServiceHandler; 
    } 

    public void setReportServiceHandler(ReportServiceHandler reportServiceHandler) { 
     this.reportServiceHandler = reportServiceHandler; 
    } 
} 

所以解釋了一下上面的,如果添加任何新加的S服務,你需要添加* ServiceHandler類作爲這個類的字段,並創建getter和setter等。

所以現在我們已經有了,我們可以創建一個新的單個servlet,它將被添加到servlet上下文中。

這裏是我的ApiServlet

@Component 
public class ApiServlet extends TServlet { 
    private ApiMultiplexingProcessor processor; 

    @Autowired 
    public ApiServlet(ApiMultiplexingProcessor p) { 
     super(p, new TBinaryProtocol.Factory()); 
     processor = p; 
    } 
} 

然後你只需要添加這個servlet的servlet上下文(從豆)爲前:

ServletRegistration.Dynamic api = servletContext.addServlet("ApiServlet", (ApiServlet) ctx.getBean("apiServlet")); 
api.setLoadOnStartup(1); 
api.addMapping("/api/*"); 
// yay now we have a single URL and a single servlet 

這一切可幫助別人在我的情況下,很享受!

P.S.確保在調整客戶端時使用TMultiplexedProtocol,以便在與服務器交談時可以傳遞服務名稱,例如

TTransport transport = new THttpClient(new Uri("https://myapp.com/api/")); 
TProtocol protocol = new TBinaryProtocol(transport); 
TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "UserService"); 
UserService.Client userServiceClient = new UserService.Client(mp);