SlingModels:从 Resource 适配时可以注入 SlingHttpServletRequest 吗?
SlingModels: Can I inject the SlingHttpServletRequest when adapting from Resource?
我是 SlingModels 的新手,注释还不是很清楚。我目前正在尝试将一些基本基础组件从 AEM 6.2 转换为使用 SlingModels。
对于图像组件,基金会JSP使用SlingHttpServletRequest 来设置ImageDoctype。所以我尝试了以下方法:
@Model(adaptables = {Resource.class})
public class ImageModel {
@SlingObject
private SlingHttpServletRequest request;
@SlingObject
private Resource resource;
}
但是有了这个 request
是空的。所以我改用:
@Model(adaptables = {SlingHttpServletRequest.class})
现在适用于 reuqest
和 resource
JSP代码:
<sling:adaptTo adaptable="${slingRequest}" adaptTo="models.ImageModel" var="m"/>
这是正确的方法吗?还是有办法适应 resource
并且仍然能够注入 request
?
您不能那样做,因为 SlingHttpServletRequest 无法识别资源。如果您的模型中需要 Request,请使其适应 Request。
有一些图书馆允许这样做。它使用 Filter 将当前 Request 存储在 ThreadLocal 中,然后从中读取它,但我不推荐这种方法。 ThreadLocal 只是另一个全局的。
@Model(adaptables = { SlingHttpServletRequest.class, Resource.class }, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class ImageModel {
@Self
private Resource resource;
@SlingObject
private ResourceResolver resourceResolver;
@SlingObject
SlingHttpServletRequest slingRequest;
}
采用 SlingHttpServletRequest 并不总是可行的。并考虑到您总是从一个 class 适应这一事实,即使您在适应字段中有多个 class (如果您根据请求进行适应,您可以通过 getResource 获得资源并在如果您从资源中采用 slingRequest 对象字段将为空)。
那是我的情况,我不得不从 Resource 中采用,并且我不得不向我的 Sling 模型中注入一些东西。为此,我使用了 ThreadLocal,看起来没有其他方法可以做到这一点。
以下是有关如何执行此操作的一些文章:
- https://github.com/Adobe-Consulting-Services/acs-aem-samples/blob/master/core/src/main/java/com/adobe/acs/samples/filters/impl/SampleThreadLocalFilter.java
- https://www.javacodegeeks.com/2012/05/threading-stories-threadlocal-in-web.html
- https://github.com/luontola/dimdwarf/blob/453f7aee9efc364ebad80531c05081e255323c07/dimdwarf-core/src/main/java/net/orfjackal/dimdwarf/context/ThreadContext.java
我创建了一个 util class 这样的:
public final class SomeThreadContext {
private static final ThreadLocal<Boolean> SOME_BOOLEAN_PROPERTY = new ThreadLocal<>();
private SomeThreadContext() {
}
public static void setSomeFlag(boolean someFlag) {
if (SOME_BOOLEAN_PROPERTY.get() != null) {
throw new IllegalStateException("Flag already set up.");
}
SOME_BOOLEAN_PROPERTY.set(someFlag);
}
public static boolean isSomeFlagEnabled() {
return SOME_BOOLEAN_PROPERTY.get() != null && SOME_BOOLEAN_PROPERTY.get();
}
public static void tearDown() {
if (SOME_BOOLEAN_PROPERTY.get() == null) {
throw new IllegalStateException("Flag already torn down.");
}
SOME_BOOLEAN_PROPERTY.remove();
}
}
你应该在创建模型之前使用setSomeFlag(它可以是过滤器或其他地方),isSomeFlagEnabled应该在模型内部使用并且在结束使用模型后,您总是必须使用 tearDown(您可以在最后一个块中执行此操作)。
您可以根据需要拥有任意数量的参数,最重要的是在完成工作后始终清理您的 ThreadLocal。如果您没有正确执行此操作,可能会导致内存泄漏。
我是 SlingModels 的新手,注释还不是很清楚。我目前正在尝试将一些基本基础组件从 AEM 6.2 转换为使用 SlingModels。
对于图像组件,基金会JSP使用SlingHttpServletRequest 来设置ImageDoctype。所以我尝试了以下方法:
@Model(adaptables = {Resource.class})
public class ImageModel {
@SlingObject
private SlingHttpServletRequest request;
@SlingObject
private Resource resource;
}
但是有了这个 request
是空的。所以我改用:
@Model(adaptables = {SlingHttpServletRequest.class})
现在适用于 reuqest
和 resource
JSP代码:
<sling:adaptTo adaptable="${slingRequest}" adaptTo="models.ImageModel" var="m"/>
这是正确的方法吗?还是有办法适应 resource
并且仍然能够注入 request
?
您不能那样做,因为 SlingHttpServletRequest 无法识别资源。如果您的模型中需要 Request,请使其适应 Request。
有一些图书馆允许这样做。它使用 Filter 将当前 Request 存储在 ThreadLocal 中,然后从中读取它,但我不推荐这种方法。 ThreadLocal 只是另一个全局的。
@Model(adaptables = { SlingHttpServletRequest.class, Resource.class }, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class ImageModel {
@Self
private Resource resource;
@SlingObject
private ResourceResolver resourceResolver;
@SlingObject
SlingHttpServletRequest slingRequest;
}
采用 SlingHttpServletRequest 并不总是可行的。并考虑到您总是从一个 class 适应这一事实,即使您在适应字段中有多个 class (如果您根据请求进行适应,您可以通过 getResource 获得资源并在如果您从资源中采用 slingRequest 对象字段将为空)。
那是我的情况,我不得不从 Resource 中采用,并且我不得不向我的 Sling 模型中注入一些东西。为此,我使用了 ThreadLocal,看起来没有其他方法可以做到这一点。
以下是有关如何执行此操作的一些文章:
- https://github.com/Adobe-Consulting-Services/acs-aem-samples/blob/master/core/src/main/java/com/adobe/acs/samples/filters/impl/SampleThreadLocalFilter.java
- https://www.javacodegeeks.com/2012/05/threading-stories-threadlocal-in-web.html
- https://github.com/luontola/dimdwarf/blob/453f7aee9efc364ebad80531c05081e255323c07/dimdwarf-core/src/main/java/net/orfjackal/dimdwarf/context/ThreadContext.java
我创建了一个 util class 这样的:
public final class SomeThreadContext {
private static final ThreadLocal<Boolean> SOME_BOOLEAN_PROPERTY = new ThreadLocal<>();
private SomeThreadContext() {
}
public static void setSomeFlag(boolean someFlag) {
if (SOME_BOOLEAN_PROPERTY.get() != null) {
throw new IllegalStateException("Flag already set up.");
}
SOME_BOOLEAN_PROPERTY.set(someFlag);
}
public static boolean isSomeFlagEnabled() {
return SOME_BOOLEAN_PROPERTY.get() != null && SOME_BOOLEAN_PROPERTY.get();
}
public static void tearDown() {
if (SOME_BOOLEAN_PROPERTY.get() == null) {
throw new IllegalStateException("Flag already torn down.");
}
SOME_BOOLEAN_PROPERTY.remove();
}
}
你应该在创建模型之前使用setSomeFlag(它可以是过滤器或其他地方),isSomeFlagEnabled应该在模型内部使用并且在结束使用模型后,您总是必须使用 tearDown(您可以在最后一个块中执行此操作)。
您可以根据需要拥有任意数量的参数,最重要的是在完成工作后始终清理您的 ThreadLocal。如果您没有正确执行此操作,可能会导致内存泄漏。