java - 我在资源中注入(inject)了服务接口(interface),但无法弄清楚如何配置资源方法调用

标签 java guice dropwizard inject

enter image description here这是我为启动资源而编写的代码。无法注册资源类。使用过Mongo数据库和@Injected基础知识

@JsonIgnoreProperties(ignoreUnknown = true)
public class Student extends BaseModel {

    private String firstName;
    private String lastName;
    private String marks;
    private long dob;
    @Email
    private String email;


    public Student() {
    }

    public Student(String firstName, String lastName, String marks, long dob, @Email String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.marks = marks;
        this.dob = dob;
        this.email = email;
    }
//Getter Setter method 
}

//Base Repository Interface
public interface BaseRepository<T extends BaseModel> extends GenericRepository<T> {

    T save (T model);
    List<T> getAll();
    T getById(String Id);
    void deleteById(String Id);
    T updateById(String Id, T model);
}

Abstract Repository Method 执行CRUD操作的Basics方法

 public BaseRepositoryImpl(MongoDb mongoManager, Class<T> clazz) throws Exception{
        this.mongoManager = mongoManager;
        collectionName = clazz.getAnnotation(CollectionName.class);
        collection = mongoManager.getMongoCollection(collectionName.name());
        entityClass = clazz;
    }

    @Override
    public T save(T model) {
        if(model == null){
            throw new RuntimeException("No data Found");
        }
        Object id = collection.save(model).getUpsertedId();
        if(id != null && id instanceof ObjectId){
            model.setId(((ObjectId) id).toStringMongod());
        }
        return model;
    }
}

//service
public interface StudentService {
    Student save(Student student);
}


//Resource 
WebService
@Path("/student")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@HK2Managed
@Timed
public class StudentResource {


    @Inject
    StudentService studentService;

   /* @Inject
    public StudentResource(StudentService studentService) {
        this.studentService = studentService;
    }*/

    @Path("/getName")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String getName(){
        return "Puru";
    }
}

应用配置注册主类的Uri和端口

    private String template;
    // private StudentService studentService;

    private String defaultName = "Stranger";

    public MongoConfiguration getMongoConfiguration() {
        return mongoConfiguration;
    }

    public void setMongoConfiguration(MongoConfiguration mongoConfiguration) {
        this.mongoConfiguration = mongoConfiguration;
    }


    @Valid
    @JsonProperty("mongoserver")
    public MongoConfiguration mongoConfiguration;
}

//Application Connector  to bind the Class in interface of the Respected Class 

public class ApplicationConnector extends AbstractModule /*AbstractBinder*/ {

    private final ConfigurationContext context;

    public ApplicationConnector(ConfigurationContext context) {
        this.context = context;
    }

    @PostConstruct
    @Override
    protected void configure() {
        bind(StudentService.class).to(StudentServiceImpl.class);
        bind(StudentRepository.class).to(StudentRepositoryImpl.class);
    }

// applicaytion Connector Class 

public class App extends Application<AppConfiguration> {

    GuiceBundle<AppConfiguration> guiceBundle = null;
    private JAXWSBundle jaxwsBundle = new JAXWSBundle();
    public static void main(final String[] args) throws Exception {
        new App().run(args);
    }
    private JAXWSBundle<Object> jaxWsBundle = new JAXWSBundle<>("/api");
    @Override
    public String getName() {
        return "student-DropWizard-demo";
    }

    @Override
    public void initialize(final Bootstrap<AppConfiguration> bootstrap) {
        // TODO: application initializatio
//        bootstrap.getObjectMapper().enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
//        bootstrap.addBundle(GuiceBundle.<AppConfiguration>builder()
//                .enableAutoConfig("package.to.scan")
//                .searchCommands(true)
//                .build()
//        );
             /*  GuiceBundle.Builder builder = GuiceBundle.builder() .noDefaultInstallers()
                .enableAutoConfig("com.dzone");
               guiceBundle = builder.build();*/
//        bootstrap.addBundle(GuiceBundle.builder().enableAutoConfig("com.dzone")
//                .build());

      //  Module[] modules = autoDiscoverModules();


        bootstrap.getObjectMapper().registerSubtypes(DefaultServerFactory.class);
//bootstrap.getObjectMapper().registerModule(new FCSerializerModule());
        bootstrap.getObjectMapper().enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
        bootstrap.addBundle(jaxwsBundle);
        GuiceBundle.Builder builder = GuiceBundle.builder()
//                .modules(modules)
                .noDefaultInstallers()
                .installers(new Class[]{LifeCycleInstaller.class,
                        ManagedInstaller.class,
                        JerseyFeatureInstaller.class, ResourceInstaller.class,
                        JerseyProviderInstaller.class,
                        EagerSingletonInstaller.class,
                        HealthCheckInstaller.class,
                        TaskInstaller.class,
                        PluginInstaller.class
                })
                .enableAutoConfig(ApplicationConnector.class.getPackage().getName());
        postInitialize(bootstrap, builder);
        guiceBundle = builder.build();
        bootstrap.addBundle(guiceBundle);
    }

    @Override
    public void run(final AppConfiguration configuration,
                    final Environment environment) throws Exception {
        // TODO: implement application
      //  FilterRegistration.Dynamic dFilter = environment.servlets().addFilter("student", CrossOriginFilter.class);
//   AbstractServerFactory sf = (AbstractServerFactory) configuration.getServerFactory();

//        Endpoint e =  jaxWsBundle.publishEndpoint(
//                new EndpointBuilder("student", new StudentResource()));
       // environment.jersey().register(new StudentResource());
        //environment.jersey().register(new StudentServiceImpl());
        //environment.jersey().packages("service");
      //  environment.jersey().disable();
       // environment.servlets().addServlet(StudentResource.class).addMapping("/student");
        environment.getJerseyServletContainer().getServletInfo();
        //environment.servlets().setBaseResource("");
        ///environment.servlets().addServlet("StudentResource",StudentResource.class);
       //environment.jersey().register(new ResourceInstaller());

        postRun(configuration,environment);
    }

    protected void postRun(final AppConfiguration configuration, final Environment environment) throws Exception {
        // Sub-classes should
    }

    protected void postInitialize(Bootstrap<AppConfiguration> bootstrapm, GuiceBundle.Builder guiceBuilder) {
        // Sub-classes should
    }
 /*public Module[] autoDiscoverModules() {
        Reflections reflections =
                new Reflections(
                        new ConfigurationBuilder()
                                .forPackages(
                                       "com.dzone"));

        Set<Class<? extends AbstractModule>> classes = reflections.getSubTypesOf(AbstractModule.class);

        List<Module> discoveredModules = new ArrayList<>();
        for (Class clazz : classes) {
            try {
                AbstractModule module = (AbstractModule) clazz.newInstance();
                discoveredModules.add(module);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return discoveredModules.toArray(new Module[]{});
    }
}

这是代码的输出。无法注册应用程序的资源

WARN  [2019-09-09 05:32:31,707] io.dropwizard.setup.AdminEnvironment: 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!    THIS APPLICATION HAS NO HEALTHCHECKS. THIS MEANS YOU WILL NEVER KNOW      !
!     IF IT DIES IN PRODUCTION, WHICH MEANS YOU WILL NEVER KNOW IF YOU'RE      !
!    LETTING YOUR USERS DOWN. YOU SHOULD ADD A HEALTHCHECK FOR EACH OF YOUR    !
!         APPLICATION'S DEPENDENCIES WHICH FULLY (BUT LIGHTLY) TESTS IT.       !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
INFO  [2019-09-09 05:32:31,711] org.eclipse.jetty.server.handler.ContextHandler: Started i.d.j.MutableServletContextHandler@615db358{/,null,AVAILABLE}
INFO  [2019-09-09 05:32:31,718] org.eclipse.jetty.server.AbstractConnector: Started application@f9cab00{HTTP/1.1,[http/1.1]}{0.0.0.0:8099}
INFO  [2019-09-09 05:32:31,719] org.eclipse.jetty.server.AbstractConnector: Started admin@10272bbb{HTTP/1.1,[http/1.1]}{0.0.0.0:8091}
INFO  [2019-09-09 05:32:31,719] org.eclipse.jetty.server.Server: Started @5573ms
INFO  [2019-09-09 05:32:31,719] com.roskart.dropwizard.jaxws.JAXWSEnvironment: No JAX-WS service endpoints were registered.

enter image description here

最佳答案

在上面的示例中,您将 Resource 声明为 HK managed:

@HK2Managed
@Timed
public class StudentResource {

这意味着 HK2( Jersey 的 DI)将实例化对象而不是 guice。

但是你的服务是在guice模块中声明的:

public class ApplicationConnector extends AbstractModule /*AbstractBinder*/ {

    private final ConfigurationContext context;

    public ApplicationConnector(ConfigurationContext context) {
        this.context = context;
    }

    @PostConstruct
    @Override
    protected void configure() {
        bind(StudentService.class).to(StudentServiceImpl.class);
        bind(StudentRepository.class).to(StudentRepositoryImpl.class);
    }

因此您的服务无法注入(inject) StudentService 是正常的,因为 HK2 不知道 guice 依赖项。

这可以通过 activating HK2-guice bridge 修复所以 HK 可以使用 guice 绑定(bind):

  • 添加依赖:org.glassfish.hk2:guice-bridge:2.5.0-b32(版本必须匹配HK2版本,dropwizard使用)
  • 启用选项:.option(GuiceyOptions.UseHkBridge, true)

在您的 github 项目 ( student-gradle ) 中,您有相反的情况:

资源由 guice 管理(guice 创建资源实例)

@Path("/student")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Timed
public class StudentResource {

并且服务是在香港申报的:

public class ApplicationConnector extends /*AbstractModule*/ AbstractBinder {
    @PostConstruct
    @Override
    protected void configure() {
        bind(StudentService.class).to(StudentServiceImpl.class);
        bind(StudentRepository.class).to(StudentRepositoryImpl.class);
    }
}

(但这个模块实际上从未注册过)

我的建议是“活”在 guice 上下文中:不要使用 @HKManaged(它只是为边缘情况添加的)并使用 guice 模块进行服务声明。这样 guice 将负责与您的代码相关的所有 DI。

关于java - 我在资源中注入(inject)了服务接口(interface),但无法弄清楚如何配置资源方法调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57848594/

相关文章:

java - JPQL 查询返回没有字段名称的对象

java - 基于条件的 lombok 对象构建

java - [JavaFx]这个绑定(bind)有什么问题?

java - 如何限制 Java Web 应用程序中的 Web 服务调用

aop - Guice 执行后方法拦截

java - JSR-330 中的 Inject 和 Provider 有什么区别

java - 了解下游减少实现

java - 库依赖不适用于模块

java - 如何将依赖项注入(inject) Jackson 自定义反序列化器

java - 使用 validatorUrl 为 null 后 Swagger UI 仍然显示错误