如何通过 JAX-RS 2.0 (Resteasy) 将 @Inject 和 CDI 用于企业 bean

How to use @Inject and CDI for enterprise beans with JAX-RS 2.0 (Resteasy)

我在寻找如何让 JAX-RS 2.0 在 wildfly 10 上与 CDI 一起工作时遇到了一些问题。我在另一个 post 上得到了一些答案,它是 JAX-RS 1.0/2.0 的混合体,他们使用除了 Wildfly 中包含的库之外的其他依赖项。

我的 objective 是注入一个单例企业 bean,将驻留在同一个 jar 中的业务逻辑封装到我的 REST 资源中。 REST 资源 class 应该是请求范围的并且只处理 REST 功能(请求和响应)。我的 POJO classes 是 JAXB 标记的。

如何在 Wildfly 10 中使用 JAX-RS 2.0 和包含的 CDI 库?

bean 接口

@Local
public interface DateBean {
    Date getLocalFormatDate();
}

豆子

@Singleton
public class DateBeanImpl implements DateBeanLocal {

    private static final Logger LOG = Logger.getLogger("org.test.logger");

    public DateBean() {
        LOG.fine("DateBean");
    }

    @Override
    public Date getLocalFormatDate() {
        Calendar cal = Calendar.getInstance();
        TimeZone localZone = TimeZone.getDefault();
        cal.setTimeZone(localZone);
        Date localTime = cal.getTime();
        return localTime;
    }
}

REST 资源

@Path("classroom")
@Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class ClassRoomResource {

    private static final Logger LOG = Logger.getLogger("org.clearbyte.logger");
    @Inject private DateBean dateBean;

    public ClassRoomResource() {
        LOG.fine("ClassRoomResource");
    }

    @GET
    @Path("{id}/getDummy")
    public ClassRoom getDummy(@PathParam("id") long id) {
        ClassRoom room = new ClassRoom();
        room.setRoomName("Dummy");
        room.setRoomNr(id);
        return room;
    }

    @GET
    @Path("localDate")
    @Produces({MediaType.TEXT_HTML})
    public Response getLocalformatDate() {
        LOG.fine("DateBean variable: " +dateBean);
        Date localDate = dateBean.getLocalDate();
        LOG.fine("Local date: " +localDate);
        return Response.status(Response.Status.OK)
                .entity(localDate.toString())
                .build();
    }        
}

Wildlfy 10 中包含 JAX-RS 2.0 的 Resteasy 实现,因此无需添加更多依赖项。

接口不需要 @Local当它位于同一个 jar/war 中时,CDI 就可以找到它。要使 CDI 中的企业 bean 单例使用 @ApplicationScope,如果不需要具有 read/write 同步的托管 bean,则可以省略 @Singleton 符号。

@ApplicationScoped
public class DateBeanImpl implements DateBean {

    private static final Logger LOG = Logger.getLogger("org.test.logger");

    public DateBean() {
        LOG.fine("DateBean");
    }

    @Override
    public Date getLocalFormatDate() {
        //DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Calendar cal = Calendar.getInstance();
        TimeZone localZone = TimeZone.getDefault();
        cal.setTimeZone(localZone);
        Date localTime = cal.getTime();
        return localTime;
    }
}

使用 @RequestScoped 表示法使 REST 资源请求有范围。请注意 @Inject 注入接口而不是 bean 的实现。

@RequestScoped
@Path("classroom")
@Consumes({MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class ClassRoomResource {

    private static final Logger LOG = Logger.getLogger("org.clearbyte.logger");
    @Inject private DateBean dateBean;
    ...

如果扩展 jax-rs 应用程序 class,则无需配置 web.xml

@ApplicationPath("rest")
public class ClassRoomApp extends Application {

private final Set<Class<?>> resources = new HashSet<>();

    public ClassRoomApp() {
        resources.add(ClassRoomResource.class);
    }

    @Override
    public Set<Class<?>> getClasses() {
        return resources;
    }
}