Quarkus中的会话范围

Quarkus中的会话范围,quarkus,Quarkus,我正在将一个应用程序从Thorntail迁移到Quarkus。它在bean中使用会话范围注释,该注释在所有RESTAPI请求期间向感兴趣的任何服务提供令牌信息。但在Quarkus文档中,它表示对话范围未实现。我可以使用类似的功能吗 以下是我想做的: @Path @ApplicationScoped public class FruitsResource { @Inject FruitsService fruitsService; @POST public int po

我正在将一个应用程序从Thorntail迁移到Quarkus。它在bean中使用会话范围注释,该注释在所有RESTAPI请求期间向感兴趣的任何服务提供令牌信息。但在Quarkus文档中,它表示对话范围未实现。我可以使用类似的功能吗

以下是我想做的:

@Path
@ApplicationScoped
public class FruitsResource {

    @Inject FruitsService fruitsService;

    @POST
    public int post (Fruit fruit) {
         return fruitsService.post(fruit);
    }
}

@Provider
@ApplicationScoped
private class AuthorizationFilter implements ContainerRequestFilter {

    @Inject AuthorizationHolder authorizationHolder;

    @Override
    public void filter (ContainerRequestContext request) {
        String token = request.getHeaderString(HttpHeaders.AUTHORIZATION);
        Authorization authorization = createAuthorizationFromToken(token);
        authorizationHolder.setAuthorization(authorization);
    }
}

@ConversationScoped
private class AuthorizationHolder {

    private Authorization authorization;

    @Produces
    public Authorization getAuthorization () {
        return authorization;
    }

    public void setAuthorization (Authorization authorization) {
        this.authorization = authorization;
    }
}

@ApplicationScoped
private class FruitsService {

    @Inject Authorization authorization;
    @Inject EntityManager entityManager;

    @Transactional
    public void post (Fruit fruit) {
         // do some complex validation with the authorization object
         ...

         // persist object
         entityManager.persist(fruit);
         entityManager.flush();
         return fruit.getId();
    }
}

每个请求中是否存在
授权
标题?我想它是(或者应该是),在这种情况下,只使用
@RequestScoped
而不是
@ConversationScoped
应该可以工作。无论如何,这可能是最好的办法

如果头仅出现在“第一个”请求中,并且同一会话中的后续请求可以重用令牌,那么您可以将
@ConversationScoped
替换为
@SessionScoped
。不过,我认为强制在所有请求中都显示标头会更好

最后,如果您真的想模拟对话,您可以这样做(未经测试,甚至未在IDE中编写,仅从我的头顶):

@SessionScoped
私有类授权持有人{
私有ConcurrentMap授权=新ConcurrentHashMap();
公共授权getAuthorization(ContainerRequestContext请求){
返回authorizations.get(getConversationId(request));
}
public void setAuthorization(ContainerRequestContext请求,授权){
this.authorizations.put(getConversationId(请求),authorization);
}
私有字符串getConversationId(ContainerRequestContext请求){
多值映射查询=request.getUriInfo().getQueryParameters();
返回query.getFirst(“cid”);
}
}

但是,正如我上面所说的,我真的认为您应该将bean
@requestscope
设置为限定的,并强制客户端在每个请求中发送
授权
头。

您能更详细地描述您的用例吗?因为从您编写的内容来看,似乎requestscope对您来说已经足够了。在任何情况下,SessionScoped都应该在Quarkus中可用,并且您可以在此基础上实现对话。这正是Thorntail中的代码。如何使用SessionScoped在Quarkus中实现同样的效果@ladicek每次请求都会发送授权。即使如此,用RequestScope替换ConversationScope也不起作用。我在这里创建了一个显示此行为的测试:只需在quarkus:dev中运行,在swagger ui中添加任何令牌,并为您建议的SessionScoped解决方案执行端点,每个端点调用都必须通知一个名为cid的查询参数@LadicekConversation作用域就是这样工作的,如果我没记错的话。事实上,仅仅用RequestScope替换ConversationScope是不起作用的,因为用Products注释的方法。当这个方法被注释为requestScope时,它就工作了。啊,好的,我没有想到这一点。我还是CDI新手:-)
@SessionScoped
private class AuthorizationHolder {
    private ConcurrentMap<String, Authorization> authorizations = new ConcurrentHashMap<>();

    public Authorization getAuthorization(ContainerRequestContext request) {
        return authorizations.get(getConversationId(request));
    }

    public void setAuthorization(ContainerRequestContext request, Authorization authorization) {
        this.authorizations.put(getConversationId(request), authorization);
    }

    private String getConversationId(ContainerRequestContext request) {
        MultivaluedMap<String, String> query = request.getUriInfo().getQueryParameters();
        return query.getFirst("cid");
    }
}