java 使用ResteasyContext和ContainerRequestFilter从RestEasy迁移到RestEasyReactive

brgchamk  于 2023-06-04  发布在  Java
关注(0)|答案(1)|浏览(146)

我正在将旧的Quarkus项目从RestEasy迁移到ResteasyReactive,由于在REST Easy中没有真实的的1:1替代方案,因此在迁移ResteasyContext.pushContext时遇到了一些困难。
我使用ContainerRequestFilter中的ResteasyContext.pushContext将一些自定义对象推送到Context,然后使用@Context检索它。
就像我提供的这个最小的例子。
过滤器:

package org.acme.filter;

import org.acme.pojo.CustomHttpRequest;
import org.jboss.resteasy.core.ResteasyContext;

import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.ext.Provider;
import java.time.LocalDateTime;
import java.util.Random;

@Provider
@ApplicationScoped
public class HttpRequestFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) {
        CustomHttpRequest request = CustomHttpRequest.builder()
                .headers(requestContext.getHeaders())
                .dateTime(LocalDateTime.now())
                .text("Some random text for example " + new Random().nextInt(100))
                .build();
        ResteasyContext.pushContext(CustomHttpRequest.class, request);
    }
}

要推送到上下文的自定义对象:

package org.acme.pojo;

import lombok.Builder;
import lombok.Getter;
import lombok.ToString;

import javax.ws.rs.core.MultivaluedMap;
import java.time.LocalDateTime;

@Getter
@Builder
@ToString
public class CustomHttpRequest {

    private String text;
    private LocalDateTime dateTime;
    private MultivaluedMap<String, String> headers;
    private boolean secured;
}

后者从我的rest endpoint中的上下文读取它:

package org.acme;

import org.acme.pojo.CustomHttpRequest;
import org.acme.pojo.ResponseData;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class GreetingResource {

    @GET
    @Path("{pathText}")
    @Produces(MediaType.APPLICATION_JSON)
    public ResponseData testContext(@Context CustomHttpRequest httpRequest,
                                    @PathParam("pathText") String querryText) {

       return ResponseData.builder()
                .querryText(querryText)
                .httpRequestText(httpRequest.getText())
                .secured(httpRequest.isSecured())
                .build();
    }
}

以下是GitHub上的完整示例:https://github.com/pkristja/resteasy_context/tree/main
我发现了一些与RestEasyReactive一起工作的替代方案,比如使用ContainerRequestContext和使用setProperty设置数据。
生成文件更改:从implementation("io.quarkus:quarkus-resteasy-jackson")变更为implementation("io.quarkus:quarkus-resteasy-reactive-jackson")
用于将对象设置为上下文的过滤器:

package org.acme.filter;

import org.acme.pojo.CustomHttpRequest;

import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import java.time.LocalDateTime;
import java.util.Random;

@Provider
@ApplicationScoped
public class HttpRequestFilter implements ContainerRequestFilter {

    @Context
    ContainerRequestContext crContext;

    @Override
    public void filter(ContainerRequestContext requestContext) {
        CustomHttpRequest request = CustomHttpRequest.builder()
                .headers(requestContext.getHeaders())
                .dateTime(LocalDateTime.now())
                .text("Some random text for example " + new Random().nextInt(100))
                .build();

        crContext.setProperty("customHttpRequest", request);
    }
}

正在从上下文检索对象:

package org.acme;

import org.acme.pojo.CustomHttpRequest;
import org.acme.pojo.ResponseData;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class GreetingResource {

    @GET
    @Path("{pathText}")
    @Produces(MediaType.APPLICATION_JSON)
    public ResponseData testContext(@Context ContainerRequestContext crContext,
                                    @PathParam("pathText") String querryText) {

        CustomHttpRequest httpRequest = (CustomHttpRequest) crContext.getProperty("customHttpRequest");

       return ResponseData.builder()
                .querryText(querryText)
                .httpRequestText(httpRequest.getText())
                .secured(httpRequest.isSecured())
                .build();
    }
}

有没有办法在RestEasyReactive中使用ResteasyContext.pushContext获得与RestEasy相同的功能,因为从上下文中检索每个对象并将其转换是非常冗长和低效的,因为在我的真实示例中,我有多个自定义对象被推送到ResteasyContext.pushContext的上下文。
谢谢你!

vsdwdz23

vsdwdz231#

当使用RESTEasy Reactive时,有一种更简单的方法来做这样的事情:只需使用CDI请求作用域bean。
下面这样的东西应该就可以了:

@Singleton
public class CustomHttpRequestProducer {

    @RequestScoped
    @Unremovable
    public CustomHttpRequest produce(HttpHeaders headers) {
        return new CustomHttpRequest(headers.getRequestHeaders(), LocalDateTime.now(), "dummy");
    }
}

然后,您可以在JAX-RS资源中轻松地使用它:

@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello(@Context CustomHttpRequest customHttpRequest) {
    return customHttpRequest.getText();
}

请注意,只有在使用CustomHttpRequest作为方法参数时才需要@Unremovable。但是,如果您将其作为字段注入,则@Unremovable是不必要的。

更新

https://github.com/quarkusio/quarkus/pull/33793成为Quarkus的一部分后(可能在3.2中),即使对于方法参数,@Unremovable也不再是必需的

相关问题