我已经使用Spring Rest完成了项目.现在,我们有一个小型休息项目,并计划与Jersey JAX-RS一起使用.我是新手,因此推荐SO和其他博客来成功实现具有依赖项注入的Rest api.
有以下代码.
AppConfig.java
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/")
public class AppConfig extends Application {
@Override
public Set<Class<?>> getClasses() {
System.out.println("AppConfig");
final Set<Class<?>> s = new HashSet<Class<?>>();
s.add(Controller.class);
s.add(AppFeature.class);
return s;
}
}
AppBinder.java
import org.glassfish.hk2.utilities.binding.AbstractBinder;
public class AppBinder extends AbstractBinder {
@Override
protected void configure() {
System.out.println("AppBinder");
bind(ReflectionService.class).to(ReflectionService.class);
}
}
AppFeature.java
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
public class AppFeature implements Feature {
@Override
public boolean configure(FeatureContext context) {
System.out.println("AppFeature");
context.register(new AppBinder());
return true;
}
}
Controller.java
@Path("/")
public class Controller {
@Inject
Service service;
public Controller(){
System.out.println("Controller created");
}
// other methods
}
Service.java
@Singleton
public class Service
public Service(){
System.out.println("Service instance created");
}
// other methods
}
我假设Controller和Service的每个实例都是在Tomcat 8服务器启动时创建的,并且依赖项注入已完成.但是在启动过程中,将其放在控制台上
INFO: Registering the Jersey servlet application, named
com.sample.auto2.AppConfig, at the servlet mapping /*, with the
Application class of the same name.AppConfig
AppConfig
Nov 15, 2016 12:22:20 PM org.glassfish.jersey.server.ApplicationHandler initialize
INFO: Initiating Jersey application, version Jersey: 2.6 2014-02-18
21:52:53…AppFeature
AppBinder
Nov 15, 2016 12:22:21 PM
org.apache.catalina.startup.HostConfig deployDirectory
每次,我们发送一个请求,在控制台中得到关注
Service instance created
Controller created
我的问题
>服务,每当我们发送一个
http请求;它在每个请求中创建实例还是只是
调用构造函数?
>为什么AppConfig中的System.out被调用两次?
>是否有更好的方法来设置我的小型项目,该项目没有任何数据库访问权限并且只有三个发布端点?
编辑:
根据@Harikrishnan提供的链接,为Controller类添加了@Singleton.现在,构造函数仅调用一次(在第一个请求时-为什么在服务器启动期间不!).
但是,为什么Service类构造函数会在每个请求上调用(在将@Singleton添加到Controller之前),即使它是单例的呢?另外,其他问题仍然存在.
编辑2:
谢谢@peeskillet.所以这些对我来说是结果.
>这在第一次请求时仅调用一次构造函数
bind(ReflectionService.class).to(ReflectionService.class).in(Singleton.class);
bind(Controller.class).to(Controller.class).in(Singleton.class);
>这给http请求错误
bind(ReflectionService.class).to(ReflectionService.class).in(Immediate.class);
java.lang.IllegalStateException: Could not find an active context for org.glassfish.hk2.api.Immediate
没关系,因为
>这在服务器启动时称为构造函数,仅一次
bind(new ReflectionService()).to(ReflectionService.class);
bind(new Controller()).to(Controller.class);
>这样,启动时就完成了注入,但是http请求上却出现404错误. (在AppBinder中配置了控制器,然后在AppConfig中配置了)
@ApplicationPath("/")
public class AppConfig extends ResourceConfig {
public AppConfig() {
register(new AppBinder());
}
}
>就像您所说的那样,它可以运行!
@ApplicationPath("/")
public class AppConfig extends ResourceConfig {
public AppConfig() {
register(new AppBinder());
register(Controller.class);
}
}
最后,这些都是我所需要的
public class AppBinder extends AbstractBinder {
@Override
protected void configure() {
bind(new ReflectionService()).to(ReflectionService.class);
bind(new Controller()).to(Controller.class);
}
}
@ApplicationPath("/")
public class AppConfig extends ResourceConfig {
public AppConfig() {
register(new AppBinder());
register(Controller.class);
}
}
最佳答案
Service,Controller constructors is being called whenever we send an http request; does it create instances in each request or just calling constructor?
不幸的是,@ Singleton在使用AbstractBinder绑定时没有任何作用.我们需要明确地说应该是单身
bind(ReflectionService.class).to(ReflectionService.class).in(Singleton.class);
默认行为是“每次查询”范围,这意味着每次请求服务时都会创建一个新实例
(at the very first request – Why not during server startup!!)
这就是它的工作方式.还有一个InstantScope,它将使它在启动时创建
bind(ReflectionService.class).to(ReflectionService.class).in(ImmediateScope.class)
或者,您可以使用实例代替类,它将自动成为单例
bind(new ReflectionService()).to(ReflectionService.class)
Service,Controller constructors is being called whenever we send an http request; does it create instances in each request or just calling constructor?
这是默认行为.每个请求的资源类的新实例.如前所述,如果只需要一次实例,则将其标记为@Singleton
Why System.out in AppConfig is called twice?
不确定,可能只是引导程序上的Jersey内部处理所需的
Is there a better way for setting up my small project, which does not have any db access and only three post endpoints?
设置很好,但是如果使用Jersey,则应使用ResourceConfig(应用程序扩展)类而不是Application
@ApplicationPath("/")
public class AppConfig extends ResourceConfig {
public AppConfig() {
register(new AppBinder());
register(Controller.class);
}
}
这样,您无需将AppBinder包装在AppFeature中.泽西岛已经知道如何处理AppBinder