Access HttpServletRequest using @Context annotaion in business layer

我怕爱的太早我们不能终老 提交于 2020-01-13 20:41:29

问题


I am able to access HttpServletRequest by using @Context annotation in my rest service. But unable to access the same in repository class.I do not want to pass the request form MyService to MyRespository while calling methods.

@Path("/someUrl")
public MyService{

@Context
private HttpServletRequest request;

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

}

But same annotation not working for my Repository class

@Repository
public MyRepository
{

@Context
private HttpServletRequest request;

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

it injection null request. Not sure why this is not working.


回答1:


The problem is the way Jersey (and its DI framework HK2) is integrated, is that Spring components can be injected into Jersey (HK2) components, but not vice versa. HttpServletRequest is bound as a Jersey component.

What you can do is create an HK2 service, that wraps the Spring repo, and the HttpServletRequest. IMO, it is better design anyway. A repository shouldn't be concerned with the HttpServletRequest, it is only concerned with data.

So you can have

public class MyService {

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

    @Context
    private HttpServletRequest request;

}

Then bind the service with 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
    }
}

And register the binder with Jersey

public class JerseyConfig extends ResourceConfig {

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

Then you can inject MyService into your resource class.

If you don't want to go this route, then you need to make MyRepository an HK2 service, or use a an HK2 Factory to wrap the repository, and explicitly inject it. Something like

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 */}
}

Then register the factory

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

If you do the above, then you just use the MyRepository, instead of adding the service layer. Basically you need to get the repo from Spring, and explicitly inject it with the HK2 ServiceLocator (which is the HK2 analogue of the Spring ApplicationContext).



来源:https://stackoverflow.com/questions/35937641/access-httpservletrequest-using-context-annotaion-in-business-layer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!