Java SpringMVC、空SpringBeans、servlet和Apache Thrift

Java SpringMVC、空SpringBeans、servlet和Apache Thrift,java,spring,servlets,thrift,Java,Spring,Servlets,Thrift,我有一个web应用程序,它有一个UserService,允许进行与用户相关的操作 我可以在我的@Controller类中自动连接UserServicebean,它工作正常 如果我添加第二个类型为ThriftServlet的servlet,如下所示: //register the thrift API servlet ServletRegistration.Dynamic thrift = servletContext.addServlet("thriftapi", new ThriftServl

我有一个web应用程序,它有一个
UserService
,允许进行与用户相关的操作

我可以在我的
@Controller
类中自动连接
UserService
bean,它工作正常

如果我添加第二个类型为
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
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
    }
}
我可以在调试日志中看到,自动连接确实发生了(时间戳和类被截断):

-创建singleton bean“thriftApiHandler”的共享实例
-正在创建bean“thriftApiHandler”的实例
-类[my.package.api.ThriftApiHandler]上注册的注入元素:my.package.service.UserService的AutoWiredFeldElement my.package.api.ThriftApiHandler.UserService
-急切地缓存bean“thriftApiHandler”,以允许解析潜在的循环引用
-bean“thriftApiHandler”的处理注入方法:my.package.service.UserService的AutoWiredFeldElement my.package.api.thriftApiHandler.UserService
但是
userService
(以及我尝试注入的任何其他bean)在任何thrift api方法中都始终为空

也许这与
TServlet
类如何从
HttpServlet
继承而不“知道”spring上下文有关

我觉得我缺少了一些与servlet上下文和共享bean等相关的东西,但我对SpringMVC还是相当陌生的。如果发布更多代码可以让这个问题更容易回答,请告诉我。

如果Spring无法解析
@Autowired
目标,它将始终失败(抛出异常)。如果您得到
null
,那么Spring实际上并没有管理您的对象,因此无法注入任何内容。这里就是这样

public ThriftServlet() {
    super(new MyService.Processor<ThriftApiHandler>(
        new ThriftApiHandler()), new TBinaryProtocol.Factory()); // here
}
公共储蓄服务(){
超级(新MyService.Processor)(
新ThriftApiHandler()),新TBinaryProtocol.Factory();//此处
}
您正在自己实例化您的
ThriftApiHandler
,而不是从Spring获得它


如果您想从Spring获取它,您需要从
ServlectContext
属性或您放置它的任何地方访问
ApplicationContext

我最终找到了它

  • @组件
    添加到
    ThriftServlet
  • 创建了一个名为
    ThriftProcessor
    (见下文)的新类,它也是一个
    @组件
  • ThriftServlet
    构造函数(见下文)更改为
    @Autowired
    ,并接受
    处理器
    参数
  • 调整了我的应用程序初始值设定项类,从Springbean中获取
    ThriftServlet
    ,而不是自己实例化它(注意:必须让
    ApplicationContext
    刷新自己,然后才能工作)
  • ThriftProcessor
    类:

    @Component
    public class ThriftProcessor extends MyService.Processor<ThriftApiHandler> {
    
        @Autowired
        public ThriftProcessor(ThriftApiHandler iface) {
            super(iface);
        }
    }
    
    @Component
    public class ThriftServlet extends TServlet {
    
        @Autowired
        public ThriftServlet(Processor<ThriftApiHandler> p) {
            super(p, new TBinaryProtocol.Factory());
        }
    }
    
    Initializer中的新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/*");
    

    如果有更好的方法,请说出来

    如果我将
    @组件添加到
    ThriftServlet
    ,我是否能够
    @Autowire
    一个
    ThriftApiHandler
    ?即使这样,我也不能在
    新的MyService.Processor(thriftApiHandler)
    构造函数中引用它,因为它不是静态的…@wwarren您不应该在构造函数中添加处理程序。servlet是在
    init
    方法中进行配置的,您可以在该方法中访问
    ServletContext
    <代码>制作你的
    ThrifServlet`a
    @组件
    如果不是由Spring管理的话,它不会改变任何东西。我想我已经解决了——看看下面的答案,并提出任何改进建议?是的,正如我所说,如果你想让Spring管理它们,你需要从Spring上下文中创建bean。你所做的似乎很好。我只需将
    ThriftProcessor
    构造函数更改为只包含
    ThriftApiHandler
    参数,no
    ApplicationContext
    (除非您有多个
    ThriftApiHandler
    bean。哦,是的,谢谢您-将其编辑到我的答案中!
    //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/*");