簡體   English   中英

SpringMVC,空的Spring Bean,Servlet和Apache Thrift

[英]SpringMVC, null spring beans, servlets and Apache Thrift

我有一個具有UserService的Web應用程序,以允許進行與用戶相關的操作。

我可以將UserService bean自動連接到任何@Controller類中,並且工作正常。

如果我像這樣添加第二個類型為ThriftServlet servlet:

//register the thrift API servlet
ServletRegistration.Dynamic thrift = servletContext.addServlet("thriftapi", new ThriftServlet());
thrift.setLoadOnStartup(2);
thrift.addMapping("/api/*");

ThriftServlet看起來像這樣:

public class ThriftServlet extends TServlet {

    // constructor
    public ThriftServlet() {
        super(new MyService.Processor<ThriftApiHandler>(
            new ThriftApiHandler()), new TBinaryProtocol.Factory());
    }
}

然后我用@Component裝飾了ThriftApiHandler以便進行bean注入(或者我認為),使其看起來像這樣:

@Component
public class ThriftApiHandler implements MyService.Iface {

    @Autowired
    UserService userService;

    @Override
    public String myServiceMethod(String someParam) throws SomeException, TException {
        // userService is null when this is called by a client application
    }
}

我可以在調試日志中看到確實在進行自動裝配(時間戳和類已被刪除):

<snip> - Creating shared instance of singleton bean 'thriftApiHandler'
<snip> - Creating instance of bean 'thriftApiHandler'
<snip> - Registered injected element on class [my.package.api.ThriftApiHandler]: AutowiredFieldElement for my.package.service.UserService my.package.api.ThriftApiHandler.userService
<snip> - Eagerly caching bean 'thriftApiHandler' to allow for resolving potential circular references
<snip> - Processing injected method of bean 'thriftApiHandler': AutowiredFieldElement for my.package.service.UserService my.package.api.ThriftApiHandler.userService

但是在任何節儉的api方法中, userService (以及我嘗試插入的任何其他bean)始終為null。

也許與TServlet類是如何從HttpServlet繼承而來的,並且不“了解” spring上下文有關?

我覺得我缺少與servlet上下文和共享bean等有關的東西,但是對於SpringMVC來說我還是很陌生。 如果發布更多代碼會使此問題更易於回答,請告訴我。

如果Spring無法解析@Autowired目標,它將始終失敗(引發異常)。 如果您得到null ,那么Spring實際上並沒有管理您的對象,因此無法注入任何東西。 就是這種情況。

public ThriftServlet() {
    super(new MyService.Processor<ThriftApiHandler>(
        new ThriftApiHandler()), new TBinaryProtocol.Factory()); // here
}

您將自己實例化ThriftApiHandler ,而不是從Spring獲取它。

如果要從Spring獲取它,則需要從ServlectContext屬性或放置在其他任何位置的ApplicationContext訪問ApplicationContext

我終於弄清楚了...

  1. ThriftServlet類中添加了@Component
  2. 創建了一個名為ThriftProcessor的新類(參見下文),它也是一個@Component
  3. ThriftServlet構造函數(請參見下文)更改為@Autowired並接受Processor參數
  4. 調整了我的應用程序初始值設定項類,以從春季bean獲取ThriftServlet而不是自己實例化(注意:必須告訴ApplicationContext刷新自身,然后才能起作用)

ThriftProcessor類:

@Component
public class ThriftProcessor extends MyService.Processor<ThriftApiHandler> {

    @Autowired
    public ThriftProcessor(ThriftApiHandler iface) {
        super(iface);
    }
}

ThriftServlet類:

@Component
public class ThriftServlet extends TServlet {

    @Autowired
    public ThriftServlet(Processor<ThriftApiHandler> p) {
        super(p, new TBinaryProtocol.Factory());
    }
}

初始化器中的新servlet配置:

//register the thrift API servlet using a spring bean
ServletRegistration.Dynamic thrift = servletContext.addServlet("thriftapi", (ThriftServlet) ctx.getBean("thriftServlet")); // get thriftServlet from springbeans!
thrift.setLoadOnStartup(2);
thrift.addMapping("/api/*");

如果有“更好”的方法,請這樣說!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM