【问题标题】:Access HttpServletRequest using @Context annotaion in business layer在业务层使用@Context注解访问HttpServletRequest
【发布时间】:2016-06-26 13:06:17
【问题描述】:

我可以通过在我的休息服务中使用@Context 注释来访问 HttpServletRequest。但无法在存储库类中访问相同的内容。我不想在调用方法时将请求表单 MyService 传递给 MyRespository。

@Path("/someUrl")
public MyService{

@Context
private HttpServletRequest request;

@Get
public void someMethod()
{
   myRepository.someMethod();
}

}

但相同的注释不适用于我的 Repository 类

@Repository
public MyRepository
{

@Context
private HttpServletRequest request;

public void someMethod()
{
 //need request here
}
}

it 注入空请求。不知道为什么这不起作用。

【问题讨论】:

  • 您使用的是哪个 Jersey 版本?
  • @peeskillet - 我使用的是 jersey 2.11 版本

标签: java spring rest jersey jersey-2.0


【解决方案1】:

问题在于 Jersey(以及 DI 框架 HK2)的集成方式,即 Spring 组件可以注入 Jersey (HK2) 组件,反之则不行。 HttpServletRequest 绑定为 Jersey 组件。

您可以做的是创建一个 HK2 服务,它包含 Spring 存储库和 HttpServletRequest。 IMO,无论如何它是更好的设计。存储库不应该关心HttpServletRequest,它只关心数据。

所以你可以拥有

public class MyService {

    @Inject // or @Autowired (both work)
    private MyRepository repository;

    @Context
    private HttpServletRequest request;

}

然后用HK2绑定服务

import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.process.internal.RequestScoped;

public class AppBinder extends AbstractBinder {

    @Override
    public void configure() {
        bindAsContract(MyService.class).in(RequestScoped.class);
        // note, if `MyService` is an interface, and you have 
        // an implementation, you should use the syntax
        //
        // bind(MyServiceImpl.class).to(MyService.class).in(...);
        //
        // Then you inject `MyService`. Whatever the `to(..)` is, 
        // that is what you can inject
    }
}

并向 Jersey 注册活页夹

public class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {
        register(new AppBinder());
    }
}

然后你可以将MyService 注入到你的资源类中。

如果你不想走这条路,那么你需要让MyRepository成为一个HK2服务,或者使用一个HK2Factory来包装存储库,并显式注入它。类似的东西

import javax.inject.Inject;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.api.ServiceLocator;
import org.springframework.context.ApplicationContext;

public class MyRepositoryFactory implements Factory<MyRepository> {

    private final MyRepository repo;

    @Inject
    public MyRepositoryFactory(ApplicationContext ctx, ServiceLocator locator) {
        MyRepository r = ctx.getBean(MyRepository.class);
        locator.inject(r);
        this.repo = r;
    }


    @Override
    public MyRepository provide() {
        return repo;
    }

    @Override
    public void dispose(MyRepository t) {/* noop */}
}

然后注册工厂

@Override
public void configure() {
    bindFactory(MyRepositoryFactory.class).to(MyRepository.class).in(Singleton.class);
}

如果您执行上述操作,那么您只需使用MyRepository,而不是添加服务层。基本上你需要从 Spring 获取 repo,并使用 HK2 ServiceLocator (这是 Spring ApplicationContext 的 HK2 类似物)显式注入它。

【讨论】:

    猜你喜欢
    • 2023-03-11
    • 1970-01-01
    • 2011-03-05
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 2010-09-30
    相关资源
    最近更新 更多