有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用Jersey/Glassfish实现java正确的CDI注释

由于我正在努力编写关于CDI的文档,我希望这个问题能够成为在Jersey/Glassfish中使用正确CDI注释的有用资源

假设我们有一个应用程序BookStore

package my.bookstore;

import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;

@ApplicationPath("/bookstore")
public class BookStore extends ResourceConfig {
    public BookStore() {
        this.packages("my.bookstore.resource");
    }
}

我们希望通过RESTful服务访问Book实体:

package my.bookstore.entity;

public class Book {
    public String isbn;
    public String title;
    public String author;

    public Book(String isbn, String title, String author) {
        this.isbn = isbn;
        this.title = title;
        this.author = author;
    }
}

因此,我们需要一个DAO来访问数据存储:

package my.bookstore.dao;

import my.bookstore.entity.Book;
import java.util.List;

public interface BookDAO {
    public List<Book> getAllBooks();
}

及其实施:

package my.bookstore.dao;

import my.bookstore.entity.Book;
import java.util.List;
import java.util.ArrayList;

public class DefaultBookDAO implements BookDAO {
    public List<Book> getAllBooks() {
        List<Book> bookList = new ArrayList<>();
        list.add(new Book("1234", "Awesome Book", "Some Author"));
        return bookList;
     }
}

然后我想将DefaultBookDAO注入RESTful服务:

package my.bookstore.resource;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/books")
public class BookResource {

   @Inject
   BookDAO dao;

   @GET
   @Produces(MediaType.APPLICATION_JSON)
   public List<Book> getBooks() {
       return this.dao.getAllBooks();
   }
}

现在,在部署应用程序时,我得到:

Unsatisfied dependencies for type BookDAO with qualifiers @Default

因为我需要让CDI意识到这一点;但是怎么做呢?我尝试了各种组合@Named@Default@Model@Singleton@Stateless,许多资源(如问题和博客文章)都有自己的解释

在Jersey/Glassfish中,要使用什么正确、简单的CDI注释使此注入工作


共 (2) 个答案

  1. # 1 楼答案

    对我来说,似乎你没有放豆子。将xml文件导入到应用程序中。对于GlassFish4(通常是JavaEE7),不需要这个文件,但是,如果省略它,则只考虑使用范围注释注释的bean。因此,由于DefaultBookDAO没有被任何注释标记,所以CDI不认为它是注入的候选对象

    您有2个选项来修复它,并使CDI机制考虑Debug ToBooDa:

    • 在DeFultBooDAO类上放置^ {CD1}} -这不会改变其范围,因为^ {CD1}}是默认范围,但会使CDI考虑这个类
    • 创建bean。META-INF或WEB-INF(用于WEB应用程序)中的xml文件,值为bean-discovery-mode="all"

    在我看来,第一种选择是更干净的——您可以很容易地将可以注入的代码和不能注入的代码分开。但是,如果您想通过省略不必要的注释来提高生产率,请使用第二个选项。它更复杂,但每个模块只需执行一次

    请参阅this oracle blog post关于bean的内容。JavaEE7中的xml以及省略时的默认行为

  2. # 2 楼答案

    因为它是一个服务,所以您可以用@Stateless注释您的DefaultBookDAO

    然后需要一个额外的类来实现AbstractBinder

    您的案例应该是这样的:

    import org.glassfish.hk2.utilities.binding.AbstractBinder;
    
    public class MyApplicationBinder extends AbstractBinder {
        @Override
        protected void configure() {
            bind(DefaultBookDAO.class).to(BookDAO.class);
        }
    }
    

    您必须在扩展ResourceConfig的类中注册该类,如下所示:

    @ApplicationPath("/bookstore")
    public class BookStore extends ResourceConfig {
        public BookStore() {
            register(new MyApplicationBinder());
            this.packages("my.bookstore.resource");
        }
    }
    

    那么@Inject应该可以工作了

    另请参见: