问题
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