使用Jersey 1.17.1,我实现了一个基本的RESTful API,并将其作为servlet部署在Google App Engine 1.7.5中。我正在使用在HTTP请求标头参数中传输的令牌对用户进行身份验证。我成功使用@HeaderParam
提取令牌并使用令牌对用户进行身份验证,但我想创建一个自定义注释来为我处理身份验证。但是,泽西岛似乎没有提供提供者。
我定义了一个注释:
package com.kwogger.api.web.rs.ext;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthUser {
boolean required() default true;
}
和提供者:
package com.kwogger.api.web.rs.ext;
import com.googlecode.objectify.Key;
import com.sun.jersey.api.core.HttpContext;
import com.sun.jersey.core.spi.component.ComponentContext;
import com.sun.jersey.server.impl.inject.AbstractHttpContextInjectable;
import com.sun.jersey.spi.inject.Injectable;
import com.sun.jersey.spi.inject.PerRequestTypeInjectableProvider;
import com.kwogger.om.User;
@Provider
public class AuthUserProvider extends PerRequestTypeInjectableProvider<AuthUser, Key<User>> {
public AuthUserProvider() {
super(Key.class);
}
@Override
public Injectable<Key<User>> getInjectable(ComponentContext ic, final AuthUser a) {
return new AbstractHttpContextInjectable<Key<User>>() {
@Override
public Key<User> getValue(HttpContext ctxt) {
// ... authenticate user here ...
}
};
}
}
在我的资源中,我从这里修改了端点:
@GET
public JsonNode getVault() {
Key<User> user = authUser();
}
private String userToken;
@HeaderParam(Constants.HEADER_USER_TOKEN)
public void setUserToken(String token) {
if (token != null) {
userToken = token;
}
}
@CookieParam(Constants.COOKIE_USER_TOKEN)
public void setUserTokenCookie(String cookie) {
if (cookie != null) {
userToken = cookie;
}
}
private Key<User> authUser() {
// ... authenticate user here ...
}
到此:
@GET
public JsonNode getItem(@AuthUser Key<User> user) {
// do stuff...
}
但是,当我尝试访问端点时,我在日志中收到HTTP 415并显示以下错误消息:
com.sun.jersey.spi.container.ContainerRequest getEntity: A message body reader for Java class com.googlecode.objectify.Key, and Java type com.googlecode.objectify.Key<com.kwogger.om.User>, and MIME media type application/octet-stream was not found.
The registered message body readers compatible with the MIME media type are:
application/octet-stream ->
com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
com.sun.jersey.core.impl.provider.entity.FileProvider
com.sun.jersey.core.impl.provider.entity.InputStreamProvider
com.sun.jersey.core.impl.provider.entity.DataSourceProvider
com.sun.jersey.core.impl.provider.entity.RenderedImageProvider
*/* ->
com.sun.jersey.core.impl.provider.entity.FormProvider
com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider
com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONArrayProvider$General
com.sun.jersey.json.impl.provider.entity.JSONObjectProvider$General
com.sun.jersey.core.impl.provider.entity.StringProvider
com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
com.sun.jersey.core.impl.provider.entity.FileProvider
com.sun.jersey.core.impl.provider.entity.InputStreamProvider
com.sun.jersey.core.impl.provider.entity.DataSourceProvider
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
com.sun.jersey.core.impl.provider.entity.ReaderProvider
com.sun.jersey.core.impl.provider.entity.DocumentProvider
com.sun.jersey.core.impl.provider.entity.SourceProvider$StreamSourceReader
com.sun.jersey.core.impl.provider.entity.SourceProvider$SAXSourceReader
com.sun.jersey.core.impl.provider.entity.SourceProvider$DOMSourceReader
com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$General
com.sun.jersey.json.impl.provider.entity.JacksonProviderProxy
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$General
com.sun.jersey.core.impl.provider.entity.EntityHolderReader
同一资源文件中的每个其他端点都可以正常工作。我在servlet定义中的com.sun.jersey.config.property.packages
init-param中指定了包,并且ExceptionMapper
位于与自定义提供程序相同的包中。我不使用Spring或Guice。
我错过了什么?看起来泽西岛正试图从身体上读取Key<User> user
,这让我觉得提供者根本没有被接受,但我似乎无法弄清楚如何让它发挥作用。
答案 0 :(得分:2)
您的Key<User>
类未被截获,因为在Jersey运行时注册的提供程序期望原始类型(Key
),如您的提供者构造函数中所指定的那样:
public AuthUserProvider() {
super(Key.class);
}
但是您尝试注入参数化类型,因此需要适当地调用超类构造函数。获得所需实际类型的最简单(也可能是唯一)方法是通过超类型令牌。以下是使用Jackson TypeReference
类作为帮助者的示例:
public AuthUserProvider() {
super(new TypeReference<Key<User>>() {
}.getType());
}
这一行:
new TypeReference<Key<User>>() {}.getType()
基本上允许您创建一个保留其通用信息的类型(在这种情况下,它代表Key<User>
。
除了Jackson TypeReference类,您可以使用Jersey客户端GenericType或Gson TypeToken来完成同样的事情。