- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我目前正在尝试创建一个 InjectableProvider
与 Jersey ,但我无法让 Jersey 拿起它。
除了使用 @Provider
之外,我找不到任何有关其用法的真实示例,甚至找不到如何使用它的方法。关于实现的注释。似乎在 Jersey 写它的人在一些帖子中暗示这足以让它被接受。
我是否需要指定一些 SPI 服务文件,或者将其添加到某个工厂的某个地方?
注意:我在 Glassfish 3.1 中运行,并使用 Spring 3.1。 Spring 可能会以某种方式接管 Provider
的自动加载,这似乎是合理的。 s。不过,我就是不知道。我没有使用 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);
}
}
Annotation
:
@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();
}
@Provider
s 被传统的 Jersey-Spring servlet 启动后:
com.sun.jersey.spi.spring.container.servlet.SpringServlet
.这主要是不正确的。它确实开始扫描,但它会查找具有注释的 Spring bean。
PerRequestTypeInjectableProvider
将在每次传入请求时询问
Injectable
处理它控制的注释。这也是错误的。
PerRequestTypeInjectableProvider
正如预期的那样在启动时实例化,但 Jersey 然后立即要求
Injectable
使用给定的
type
处理给定的注释,它通过扫描它所拥有的 Restful 服务来确定——此时——决定它管理(也就是说,所有这些)。
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
来自
Provider
,但
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 request
的用法。 ,然后用于通过一些辅助方法访问上述属性。
@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
}
}
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
}
}
AbstractAttributeInjectableProvider
的实现,它本身是一个泛型类,只存在提供
AttributeInjectable
用于给定类型,
Class<T>
和提供的
AttributeParam
.提供非
abstract
更容易被告知其类型(
Class<T>
)和每个请求的实现
AttributeParam
,从而避免了一堆为您提供类型的仅构造函数实现。这也避免了必须为要与
AttributeParam
一起使用的每种类型编写代码。注解。
@Component
@Provider
public class AttributeParamInjectableProvider
implements InjectableProvider<AttributeParam, Type>
{
/**
* {@inheritDoc}
* @return Always {@link ComponentScope#PerRequest}.
*/
@Override
public ComponentScope getScope()
{
return ComponentScope.PerRequest;
}
/**
* Get an {@link AttributeInjectable} to inject the {@code parameter} for
* the given {@code type}.
* @param context Unused.
* @param parameter The requested parameter
* @param type The type of data to be returned.
* @return {@code null} if {@code type} is not a {@link Class}. Otherwise
* an {@link AttributeInjectable}.
*/
@Override
public AttributeInjectable<?> getInjectable(ComponentContext context,
AttributeParam parameter,
Type type)
{
AttributeInjectable<?> injectable = null;
// as long as it's something that we can work with...
if (type instanceof Class)
{
injectable = getInjectable((Class<?>)type, parameter);
}
return injectable;
}
/**
* Create a new {@link AttributeInjectable} for the given {@code type} and
* {@code parameter}.
* <p />
* This is provided to avoid the support for generics without the need for
* {@code SuppressWarnings} (avoided via indirection).
* @param type The type of data to be returned.
* @param parameter The requested parameter
* @param <T> The type of data being accessed by the {@code param}.
* @return Never {@code null}.
*/
protected <T> AttributeInjectable<T> getInjectable(Class<T> type,
AttributeParam parameter)
{
return new AttributeInjectable<T>(type, parameter.value());
}
}
Injectable
在启动时实例化一次而不是每个请求,但是在每个传入请求时都会调用它们。
最佳答案
你是如何初始化 Jersey 的?
我将假设您使用 Jersey 使用 jersey-spring servlet。在这种情况下, Jersey 将默认使用 Spring bean 进行初始化,因此您的 Provider
必须是一个Spring bean。尝试添加 @Named
(或者如果您不使用 atinject @Component
或 Spring 注释之一)到您的 Provider
.
An example of using Injectable Providers .
更新 :注入(inject)范围更清晰:Provider
必须是一个单例,因为对于所有实际目的来说,它是一个与范围相关的工厂,并且不需要为每个请求构建一个工厂。注入(inject)本身会根据请求发生。换句话说,getInjectable
每个请求都会调用方法。你有机会尝试吗?
OTOH,如果您扩展 SingletonTypeInjectableProvider
每次都会将相同的对象注入(inject)到您的资源中。
我不确定我是否完全理解您的 Provider
执行。我相信像下面这样的东西应该有效。
public class UserProvider extends PerRequestTypeInjectableProvider<AttributeParam, Users>{
public UserProvider(){
super(Users.class);
}
@Context
HttpServletRequest request;
@Override
public Injectable<Users> getInjectable(ComponentContext cc, AttributeParam a) {
String attributeValue = AnnotationUtils.getValue(a);
return new Injectable<Users>(){
public Users getValue() {
System.out.println("Called"); //This should be called for each request
return request.getAttribute(attributeValue);
}
};
}
}
HttpServletRequest
然后直接将其注入(inject)您的
Resource
或
Provider
使用
@Context
注释会让你知道。
AssistedProvider
或使用与您类似的方法。但是,如果您内联您的
Injectable
,您可以再次缓解这种情况。在 Provider 中定义并注入(inject)
HttpServletRequest
进
Provider
类(class)。在这种情况下,
Injectable
将能够访问
HttpServletRequest
实例(因为它在范围内)。我刚刚更新了我的例子来展示这种方法。
PerRequestTypeInjectableProvider
和
SingletonTypeInjectableProvider
不是您必须向资源中注入(inject)值(value)的唯一两个选项。您也可以使用
*Param
注入(inject)值使用
StringReaderProvider
.显然,这种注入(inject)是请求范围的。
@Provider
@Named("userProviderParamInjector")
public class UserProviderParam implements StringReaderProvider<Users> {
@Context
HttpServletRequest request;
public StringReader<Users> getStringReader(Class<?> type, Type type1, Annotation[] antns) {
if(type.equals(Users.class) {
return null;
}
String attributeValue = null;
for(Annotation a : antns) {
if((a.getClass().getSimpleName()).equals("AttributeParam")){
attributeValue = (String)AnnotationUtils.getValue(a);
}
}
return new StringReader<Users>(){
public Users fromString(String string) {
// Use the value of the *Param or ignore it and use the attributeValue of our custom annotation.
return request.getAttribute(attributeValue);
}
};
}
}
Provider
将为任何
*Param
调用您的资源中所拥有的。所以有了
Provider
就像上面注册的一个和下面一个一样的资源,
Users
value 将被注入(inject)到您的资源方法中。
@Path("/user/")
@Named
public class UserResource {
@Path("{id}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Result<Users> get(@AttributeParam("foo") @PathParam("id") Users user) {
...
}
}
Injectable
感觉更干净。
关于java - Jersey :InjectableProvider 没有被选中 - Spring,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11944434/
我尝试阅读有关 Spring BOM、Spring Boot 和 Spring IO 的文档。 但是没有说明,我们应该如何一起使用它们? 在我的项目中,我们已经有了自己的 Parent POM ,所以
我正在开发的很酷的企业应用程序正在转向 Spring。这对所有团队来说都是非常酷和令人兴奋的练习,但也是一个巨大的压力源。我们所做的是逐渐将遗留组件移至 Spring 上下文。现在我们有一个 huuu
我正在尝试使用 @Scheduled 运行 Spring 批处理作业注释如下: @Scheduled(cron = "* * * * * ?") public void launchMessageDi
我对这两个概念有点困惑。阅读 Spring 文档,我发现,例如。 bean 工厂是 Spring 容器。我还读到“ApplicationContext 是 BeanFactory 的完整超集”。但两者
我们有一个使用 Spring BlazeDS 集成的应用程序。到目前为止,我们一直在使用 Spring 和 Flex,它运行良好。我们现在还需要添加一些 Spring MVC Controller 。
假设我有一个类(class) Person带属性name和 age ,它可以像这样用 Spring 配置: 我想要一个自定义的 Spring 模式元素,这很容易做到,允许我在我的 Sp
如何在 Java 中以编程方式使用 Spring Data 创建 MongoDB 复合索引? 使用 MongoTemplate 我可以创建一个这样的索引:mongoTemplate.indexOps(
我想使用 spring-complex-task 执行我的应用程序,并且我已经构建了复杂的 spring-batch Flow Jobs,它执行得非常好。 你能解释一下spring批处理流作业与spr
我实现了 spring-boot 应用程序,现在我想将它用作非 spring 应用程序的库。 如何初始化 lib 类,以便 Autowiring 的依赖项按预期工作?显然,如果我使用“new”创建类实
我刚开始学习 spring cloud security,我有一个基本问题。它与 Spring Security 有何不同?我们是否需要在 spring boot 上构建我们的应用程序才能使用 spr
有很多人建议我使用 Spring Boot 而不是 Spring 来开发 REST Web 服务。我想知道这两者到底有什么区别? 最佳答案 总之 Spring Boot 减少了编写大量配置和样板代码的
您能向我解释一下如何使用 Spring 正确构建 Web 应用程序吗?我知道 Spring 框架的最新版本是 4.0.0.RELEASE,但是 Spring Security 的最新版本是 3.2.0
我如何才能知道作为 Spring Boot 应用程序的一部分加载的所有 bean 的名称?我想在 main 方法中有一些代码来打印服务器启动后加载的 bean 的详细信息。 最佳答案 如spring-
我有一个使用 Spring 3.1 构建的 RESTful API,也使用 Spring Security。我有一个 Web 应用程序,也是一个 Spring 3.1 MVC 应用程序。我计划让移动客
升级到 Spring 5 后,我在 Spring Rabbit 和 Spring AMQP 中遇到错误。 两者现在都设置为 1.5.6.RELEASE 有谁知道哪些版本应该与 Spring 5 兼容?
我现在已经使用 Spring Framework 3.0.5 和 Spring Security 3.0.5 多次了。我知道Spring框架使用DI和AOP。我还知道 Spring Security
我收到错误 Unable to Location NamespaceHandler when using context:annotation-config running (java -jar) 由
在 Spring 应用程序中嵌入唯一版本号的策略是什么? 我有一个使用 Spring Boot 和 Spring Web 的应用程序。 它已经足够成熟,我想对其进行版本控制并在运行时看到它显示在屏幕上
我正在使用 spring data jpa 进行持久化。如果存在多个具有相同名称的实体,是否有一种方法可以将一个实体标记为默认值。类似@Primary注解的东西用来解决多个bean的依赖问题 @Ent
我阅读了 Spring 框架的 DAOSupport 类。但是我无法理解这些 DAOSuport 类的优点。在 DAOSupport 类中,我们调用 getXXXTemplate() 方法来获取特定的
我是一名优秀的程序员,十分优秀!