本文介绍了jersey 2:如何创建自定义HTTP参数绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为我的restful服务创建一个自定义的http param绑定。请参阅下面的示例。

I am trying to create a custom http param binding for my restful service. Please see the example below.

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

}

您可以看到函数签名中有UserAuthHeaderParam注释。我想做的是有一个自定义的http param绑定,而不是标准的javax.ws.rs。* Param。

You can see that there is a UserAuthHeaderParam annotation in the function signature. What I want to do is have a custom http param binding other than the standard javax.ws.rs.*Param .

我试图实现org.glassfish.hk2 .api.InjectionResolver基本上从http标头中提取值:

I have try to implement org.glassfish.hk2.api.InjectionResolver which basically extract the value from http header:

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

    return "Hello World";
}
...

}

当我调用restful服务时,服务器会获得异常。它表明框架无法解析函数签名中的参数:

When I call the restful service, the server get below exceptions. It indicates that the framework fails to resolve the param in the function signature:

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

请帮忙。任何建议表示赞赏。我在谷歌上做了很多搜索,但没能使它工作。 的InjectableProvider和AbstractHttpContextInjectable可能是类似的问题。

Please help. Any advise is appreciated. I do make a lot of search on google but fails to make it work. Jersey 2.*. How to replace InjectableProvider and AbstractHttpContextInjectable of Jersey 1.* might be the similar question.

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

-- UPDATES:I use AbstractBinder to bind my resolver to 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");

}

}

谢谢!

推荐答案

如果您只想将值直接从标头传递给方法,则无需创建自定义注释。假设您有一个标题授权,那么您可以通过声明这样的方法轻松访问它:

If all you want is to pass value directly from the header to the method you don't need to create custom annotations. Let's say you have a header Authorization, then you can easily access it by declaring your method like this:

@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

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

Given that the answer to your question, how to create custom binding is as follows.

首先,您必须声明这样的注释:

First you have to declare your annotation like this:

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

宣布注释后,您必须定义如何解析注释。声明Value Factory Provider(这是您可以访问标头参数的位置 - 请参阅我的评论):

Having your annotation declared you have to define how it will be resolved. Declare the Value Factory Provider (this is where you'll have access to the header parameters - see my comment):

@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";
            }
        };
    }
}

现在声明注射旋转变压器

Now declare an injection resolver

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

以及配置的Binder

and a Binder for your configuration

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()),像这样

now the last thing, in your ResourceConfig add register(new HeaderParamResolverBinder()), like this

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

鉴于此,您现在应该可以使用值如你所愿:

Given that, you should be now able to use the value as you wanted:

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

我希望这有帮助。

这篇关于jersey 2:如何创建自定义HTTP参数绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 19:33
查看更多