java – 泽西:InjectableProvider没有拿起 – 春天
|
我目前正试图用泽西创造一个可注射的提供者,但是我不能让泽西拿起来. 我找不到任何真实的使用示例,甚至除了在实现上使用@Provider注释之外,还可以找到它.在泽西岛看似写的人在一些帖子中暗示,这足以让它拾起. 我需要指定一些SPI服务文件,还是将其添加到某个工厂? 注意:我正在Glassfish 3.1中运行,并使用Spring 3.1.似乎合理的是,Spring可能会以某种方式接管供应商的自动加载.但是,我只是不知道.我没有使用Spring来管理下面的建议的InjectableProvider,也没有尝试以其他方式添加它,这可能是我的问题. import com.sun.jersey.core.spi.component.ComponentContext;
import com.sun.jersey.spi.inject.Injectable;
import com.sun.jersey.spi.inject.PerRequestTypeInjectableProvider;
public abstract class AbstractAttributeInjectableProvider<T>
extends PerRequestTypeInjectableProvider<AttributeParam,T>
{
protected final Class<T> type;
public AbstractAttributeInjectableProvider(Class<T> type)
{
super(type);
this.type = type;
}
@Override
public Injectable<T> getInjectable(ComponentContext componentContext,AttributeParam attributeParam)
{
return new AttributeInjectable<T>(type,attributeParam.value());
}
}
基本实施: import javax.ws.rs.ext.Provider;
@Component // <- Spring Annotation
@Provider // <- Jersey Annotation
public class MyTypeAttributeInjectableProvider
extends AbstractAttributeInjectableProvider<MyType>
{
public MyTypeAttributeInjectableProvider()
{
super(MyType.class);
}
}
参考文献注释: @Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AttributeParam
{
/**
* The value is the name to request as an attribute from an {@link
* HttpContext}'s {@link HttpServletRequest}.
* @return Never {@code null}. Should never be blank.
*/
String value();
}
参考link from Jersey developer. 更新:calvinkrishy指出了我的想法的两个缺陷. 首先,我假设泽西岛将在传统的Jersey-Spring servlet被启动之后开始扫描@Providers:com.sun.jersey.spi.spring.container.servlet.SpringServlet.这大概是错误的它确实开始扫描,但它查找具有注释的Spring bean. 其次,我假设PerRequestTypeInjectableProvider将被询问每个传入的请求,一个可注入来处理它控制的注释.这也是错的. PerRequestTypeInjectableProvider在启动时按预期进行实例化,但Jersey立即要求Injectable处理给定类型的给定注释,该给定的注释通过扫描Restful Services来确定它在此时决定管理(也就是说,他们都是这样). PerRequestTypeInjectableProvider和SingletonTypeInjectableProvider之间的区别似乎是所产生的Injectable或者包含值,而不是为它工作(单例),或者每次查找该值(每个请求),从而使该值可以根据请求更改. 通过强制我在我的AttributeInjectable(下面的代码)中做一些额外的工作,而不是按照我计划的方式传递一些对象,以避免给予AttributeInjectable额外的知识,从而将一个较小的扳手投入到我的计划中. public class AttributeInjectable<T> implements Injectable<T>
{
/**
* The type of data that is being requested.
*/
private final Class<T> type;
/**
* The name to extract from the {@link HttpServletRequest} attributes.
*/
private final String name;
/**
* Converts the attribute with the given {@code name} into the {@code type}.
* @param type The type of data being retrieved
* @param name The name being retrieved.
* @throws IllegalArgumentException if any parameter is {@code null}.
*/
public AttributeInjectable(Class<T> type,String name)
{
// check for null
// required
this.type = type;
this.name = name;
}
/**
* Look up the requested value.
* @return {@code null} if the attribute does not exist or if it is not the
* appropriate {@link Class type}.
* <p />
* Note: Jersey most likely will fail if the value is {@code null}.
* @throws NullPointerException if {@link HttpServletRequest} is unset.
* @see #getRequest()
*/
@Override
public T getValue()
{
T value = null;
Object object = getRequest().getAttribute(name);
if (type.isInstance(object))
{
value = type.cast(object);
}
return value;
}
/**
* Get the current {@link HttpServletRequest} [hopefully] being made
* containing the {@link HttpServletRequest#getAttribute(String) attribute}.
* @throws NullPointerException if the Servlet Filter for the {@link
* RequestContextHolder} is not setup
* appropriately.
* @see org.springframework.web.filter.RequestContextFilter
*/
protected HttpServletRequest getRequest()
{
// get the request from the Spring Context Holder (this is done for
// every request by a filter)
ServletRequestAttributes attributes =
(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
return attributes.getRequest();
}
}
我希望能够从提供者传递HttpServletRequest,但是AttributeInjectable只能按照唯一的注释/类型进行实例化.由于我无法做到这一点,我使用了Spring的RequestContextFilter单例,它提供了一个ThreadLocal机制,用于安全地检索HttpServletRequest(与当前请求相关的其他内容). <filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>
org.springframework.web.filter.RequestContextFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/path/that/i/wanted/*</url-pattern>
</filter-mapping>
结果确实有效,并且它使得代码更加可读,而不会强制各种服务扩展一个基类,只是为了隐藏@Context HttpServletRequest请求的使用,然后用于通过某些帮助方法完成上述的访问属性. 那么你可以做一些这样的事情: @Path("my/path/to")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public interface MyService
{
@Path("service1")
@POST
Response postData(@AttributeParam("some.name") MyType data);
@Path("service2")
@POST
Response postOtherData(@AttributeParam("other.name") MyOtherType data);
}
@Component // Spring
public class MyServiceBean implements MyService
{
@Override
public Response postData(MyType data)
{
// interact with data
}
@Override
public Response postOtherData(MyOtherType data)
{
// interact with data
}
}
这变得非常方便,因为我使用Servlet过滤器来确保用户在传递数据之前具有访问服务的适当权限,然后我可以解析传入的数据(或加载它或任何)并将其转储到属性中要加载 如果您不想要上述Provider方法,并且您希望基类访问属性,则可以在此处: public class RequestContextBean
{
/**
* The current request from the user.
*/
@Context
protected HttpServletRequest request;
/**
* Get the attribute associated with the current {@link HttpServletRequest}.
* @param name The attribute name.
* @param type The expected type of the attribute.
* @return {@code null} if the attribute does not exist,or if it does not
* match the {@code type}. Otherwise the appropriately casted
* attribute.
* @throws NullPointerException if {@code type} is {@code null}.
*/
public <T> T getAttribute(String name,Class<T> type)
{
T value = null;
Object attribute = request.getAttribute(name);
if (type.isInstance(attribute))
{
value = type.cast(attribute);
}
return value;
}
}
@Path("my/path/to")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public interface MyService
{
@Path("service1")
@POST
Response postData();
@Path("service2")
@POST
Response postOtherData();
}
@Component
public class MyServiceBean extends RequestContextBean implements MyService
{
@Override
public Response postData()
{
MyType data = getAttribute("some.name",MyType.class);
// interact with data
}
@Override
Response postOtherData()
{
MyOtherType data = getAttribute("other.name",MyOtherType.class);
// interact with data
}
}
(编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
