java - Jersey 2 : How to create custom HTTP param binding

标签 java jersey-2.0 grizzly

我正在尝试为我的 Restful 服务创建一个自定义的 http 参数绑定(bind)。请参阅下面的示例。

@POST
@Path("/user/{userId}/orders")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public MyResult foo(@PathParam("userId") String someString, @UserAuthHeaderParam String authString){

}

可以看到函数签名中有一个UserAuthHeaderParam注解。我想要做的是拥有一个不同于标准 javax.ws.rs.*Param 的自定义 http 参数绑定(bind)。

我尝试实现 org.glassfish.hk2.api.InjectionResolver,它基本上从 http header 中提取值:

public class ProtoInjectionResolver implements InjectionResolver<UserAuthHeaderParam>{
...
@Override
public Object resolve(Injectee injectee, ServiceHandle< ? > root)
{

    return "Hello World";
}
...

}

当我调用 restful 服务时,服务器出现以下异常。说明框架解析函数签名中的param失败:

org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=String,parent=MyResource,qualifiers={}),position=0,optional=false,self=false,unqualified=null,2136594195), 

java.lang.IllegalArgumentException: While attempting to resolve the dependencies of rs.server.MyResource errors were found

请帮忙。任何建议表示赞赏。我确实在谷歌上做了很多搜索,但没能成功。 Jersey 2.*. How to replace InjectableProvider and AbstractHttpContextInjectable of Jersey 1.*可能是类似的问题。

-- 更新: 我使用 AbstractBinder 将我的解析器绑定(bind)到 UserAuthHeaderParam:

public class MyApplication extends ResourceConfig
{

public MyApplication()
{
    register(new AbstractBinder()
    {
        @Override
        protected void configure()
        {
            // bindFactory(UrlStringFactory.class).to(String.class);
            bind(UrlStringInjectResolver.class).to(new TypeLiteral<InjectionResolver<UrlInject>>()
            {
            }).in(Singleton.class);
        }
    });
    packages("rs");

}

}

谢谢!

最佳答案

如果您只想将值直接从 header 传递到您不需要创建自定义注释的方法。假设您有一个 header Authorization,那么您可以通过像这样声明您的方法来轻松访问它:

@GET
public String authFromHeader(@HeaderParam("Authorization") String authorization) {
    return "Header Value: " + authorization + "\n";
}

你可以通过调用curl来测试它,例如

$ curl --header "Authorization: 1234" http://localhost:8080/rest/resource
Header Value: 1234

鉴于您的问题的答案,如何创建自定义绑定(bind)如下。

首先你必须像这样声明你的注解:

@java.lang.annotation.Target(PARAMETER)
@java.lang.annotation.Retention(RUNTIME)
@java.lang.annotation.Documented
public @interface UserAuthHeaderParam {
}

声明注释后,您必须定义如何解析它。声明 Value Factory Provider(这是您可以访问 header 参数的地方 - 请参阅我的评论):

@Singleton
public class UserAuthHeaderParamValueFactoryProvider extends AbstractValueFactoryProvider {

    @Inject
    protected UserAuthHeaderParamValueFactoryProvider(MultivaluedParameterExtractorProvider mpep, ServiceLocator locator) {
        super(mpep, locator, Parameter.Source.UNKNOWN);
    }

    @Override
    protected Factory<?> createValueFactory(Parameter parameter) {
        Class<?> classType = parameter.getRawType();

        if (classType == null || (!classType.equals(String.class))) {
            return null;
        }

        return new AbstractHttpContextValueFactory<String>() {
            @Override
            protected String get(HttpContext httpContext) {
                // you can get the header value here
                return "testString";
            }
        };
    }
}

现在声明一个注入(inject)解析器

public class UserAuthHeaderParamResolver extends ParamInjectionResolver<UserAuthHeaderParam> {
    public UserAuthHeaderParamResolver() {
        super(UserAuthHeaderParamValueFactoryProvider.class);
    }
}

和一个 Binder 用于您的配置

public class HeaderParamResolverBinder extends AbstractBinder {

    @Override
    protected void configure() {
        bind(UserAuthHeaderParamValueFactoryProvider.class)
                .to(ValueFactoryProvider.class)
                .in(Singleton.class);

        bind(UserAuthHeaderParamResolver.class)
                .to(new TypeLiteral<InjectionResolver<UserAuthHeaderParam>>() {})
                .in(Singleton.class);
    }
}

现在是最后一件事,在你的 ResourceConfig 中添加 register(new HeaderParamResolverBinder()),像这样

@ApplicationPath("rest")
public class MyApplication extends ResourceConfig {
    public MyApplication() {
        register(new HeaderParamResolverBinder());
        packages("your.packages");
    }
}

鉴于此,您现在应该可以根据需要使用该值:

@GET
public String getResult(@UserAuthHeaderParam String param) {
    return "RESULT: " + param;
}

希望对您有所帮助。

关于java - Jersey 2 : How to create custom HTTP param binding,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23231511/

相关文章:

java - 如何使用 Grizzly 在相同的基本 url 上提供静态内容和资源

Eclipse 无法找到 JRE

java - ' boolean android.support.v7.widget.RecyclerView$LayoutManager.canScrollVertically()'

java - 防止 Tomcat 在 HTTP 错误状态 4xx 或 5xx 上干扰 Jersey/JAX-RS 2 响应主体

java - Jersey 客户端、内存泄漏、静态和并发

jackson - 在 Jax-RS 应用程序中注册 JodaModule

java - 在java中构建rest api时使用servlet有什么优点

java - 尝试用随机数创建 for 循环?

java - 空白 "Location" header ,但在 IE 中发生重定向

java - 如何在 Grizzly 中设置默认索引页