@Inject 通过 URL 将参数传递给 CDI @Named bean

2023-12-29

如果我无法将 @ManagedProperty 注释与 @Named 一起使用,因为 @ManagedProperty 在 CDI 中不起作用(?),那么如何将 URL 中的参数传递给 Facelets 客户端?在我的代码中,我想通过“后退”和“前进”按钮将 javax.mail.getMessageNumber() 传递给details.xhtml。

我知道应该使用@Inject,但是注入什么以及如何注入?

从 glassfish 日志来看,id 始终为 0,这很奇怪。即使单击“前进”,无论单击该按钮多少次,id 也永远不会超过 1。当然,这只是问题的表象。当然,期望的输出是前进到下一条消息。

也许将 Message(或者至少是 int)放入会话中?

客户端是这样的:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                template="./template.xhtml"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:c="http://java.sun.com/jsp/jstl/core"
                xmlns:f="http://java.sun.com/jsf/core">
    <ui:define name="top">
        <h:form>
            <h:form>
                <h:outputLink id="link1" value="detail.xhtml">
                    <f:param name="id" value="#{detail.back()}" />
                    <h:outputText value="back" />
                </h:outputLink>
            </h:form>
        </h:form>
        <h:form>
            <h:outputLink id="link1" value="detail.xhtml">
                <f:param name="id" value="#{detail.forward()}" />
                <h:outputText value="forward" />
            </h:outputLink>
        </h:form>
    </ui:define>
    <ui:define name="content">
        <h:outputText value="#{detail.content}"></h:outputText>
    </ui:define>
</ui:composition>

和豆子一样:

package net.bounceme.dur.nntp;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.RequestScoped;
import javax.faces.bean.ManagedProperty;
import javax.inject.Named;
import javax.mail.Message;

@Named
@RequestScoped
public class Detail {

    private static final Logger logger = Logger.getLogger(Detail.class.getName());
    private static final Level level = Level.INFO;
    @ManagedProperty(value = "#{param.id}")
    private Integer id = 0;
    private Message message = null;
    private SingletonNNTP nntp = SingletonNNTP.INSTANCE;

    public Detail() {
        message = nntp.getMessage(id);
    }

    public int forward() {
        logger.log(level, "Detail.forward.." + id);
        id = id + 1;
        logger.log(level, "..Detail.forward " + id);
        return id;
    }

    public int back() {
        logger.log(level, "Detail.back.." + id);
        id = id - 1;
        logger.log(level, "..Detail.back " + id);
        return id;
    }

    public Message getMessage() {
        return message;
    }

    public String getContent() throws Exception {
        return message.getContent().toString();
    }
}

这仅适用于 JSF 2.3 中引入的javax.faces.annotation.ManagedProperty https://jakarta.ee/specifications/platform/8/apidocs/javax/faces/annotation/ManagedProperty.html.

@Inject @ManagedProperty("#{param.id}")
private String id;

现在已弃用javax.faces.bean.ManagedProperty https://jakarta.ee/specifications/platform/8/apidocs/javax/faces/bean/ManagedProperty.html注释仅适用于 JSF@ManagedBean类。 IE。在由 JSF 管理的实例中。它不适用于由 CDI 管理的实例@Named。此外,你还犯了另一个错误:你试图准备Message基于构造函数中的托管属性。如果这是一个真实的@ManagedBean,那也是行不通的。托管属性在构造期间不可用,只是因为在调用构造函数之前不可能调用 setter 方法。你应该使用过@PostConstruct方法用于此。

如果您无法升级到 JSF 2.3,则需要创建自定义 CDI 注释。具体的例子发布在这个博客 http://www.glxn.net/?p=141。以下是相关性的摘录:

习俗@HttpParam注解:

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface HttpParam {
    @NonBinding
    public String value() default "";
}

注释值生产者:

public class HttpParamProducer {

    @Inject
    FacesContext facesContext;

    @Produces
    @HttpParam
    String getHttpParameter(InjectionPoint ip) {
        String name = ip.getAnnotated().getAnnotation(HttpParam.class).value();
        if ("".equals(name)) name = ip.getMember().getName();
        return facesContext.getExternalContext()
                .getRequestParameterMap()
                .get(name);
    }
}

使用示例:

@Inject @HttpParam
private String id;

JSF 实用程序库OmniFaces http://omnifaces.org has a @Param http://showcase.omnifaces.org/cdi/Param正是为了这个目的,内置了对 JSF 转换和验证的支持。


或者,您也可以手动从外部上下文中获取请求参数Detail托管 bean。推荐的托管 bean 初始化方法是使用@PostConstruct方法,而不是构造函数,作为构造函数could与托管 bean 创建的用途完全不同:

@PostConstruct
public void init() {
    String id = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id");
    // ...
}

另一种方法,IMO也更适合这种特殊情况,是使用<f:viewParam>它还允许您将 ID 转换为Message直接通过自定义转换器。

<f:metadata>
    <f:viewParam name="id" value="#{detail.message}" converter="messageConverter" />
</f:metadata>

只用

@Named
public class Detail {

    private Message message;

    // Getter+setter
}

and a

@FacesConverter("messageConverter")
public class MessageConverter implements Converter {

    // Convert string id to Message object in getAsObject().
    // Convert Message object to string id in getAsString().

}

See also

  • ViewParam 与 @ManagedProperty(value = "#{param.id}") https://stackoverflow.com/questions/4888942/viewparam-vs-managedpropertyvalue-param-id
  • JSF 2.0 中的通信 - 处理 GET 请求参数 http://balusc.blogspot.com/2011/09/communication-in-jsf-20.html#ProcessingGETRequestParameters
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

@Inject 通过 URL 将参数传递给 CDI @Named bean 的相关文章

随机推荐

  • 如何在 Android 应用程序中设置 Holo 深色主题?

    如何在我的应用程序中设置黑暗全息主题 这时我得到了这个 但是当我将其更改为 我收到一个错误error Error retrieving parent for item No resource found that matches the g
  • 表示数字的最小位数

    找出表示某个随机 int 数需要多少位的最有效方法是什么 例如数字 30 000 用二进制表示 111010100110000 所以需要15位 您可以尝试 Math Floor Math Log 30000 2 1 or int Math
  • SpringDoc - 如何以编程方式添加模式

    我正在使用 SpringDoc 并尝试以编程方式向 OpenApi 添加架构 但没有成功 Bean public OpenAPI customOpenAPI Schema mySchema new Schema mySchema type
  • EXCEL:仅当 B 列 = X 时才从 A 列复制单元格 -> C,但仅使用 1 列

    我有两列数据 COL A COL B AAAA PM BBBB PM CCCC P DDDD M EEEE PM 我想通过过滤列 A 来创建第三列 前提是列 B PM 但我想通过仅添加一列来实现这一点 即 没有逐步 多列方法 结果如下 CO
  • 理解 scikit-learn 中数据的格式

    我正在尝试使用 Python 3 x 中的 scikit learn 进行多标签文本分类 我有 libsvm 格式的数据 我正在使用它加载load svmlight file模块 数据格式是这样的 314523 165538 76255 1
  • 如何在SceneKit / ARKit中使用SCNTechnique创建“蒙面”传送门效果?

    我正在尝试了解如何将 SCNTechnique 与 Scenekit 结合使用 我试图创建的效果可以在 Unity 中轻松实现 方法是向两种材质添加自定义着色器 使具有 过滤 着色器的对象仅在通过其他着色器 门户 看到时才可见 我按照本教程
  • CMake:如何在 Linux 中将一个目标/文件打包到多个包中?

    我正在开发一个生成相当多可执行文件 库的项目 和配置 需要打包到不同的包中进行部署 问题是 这些目标 文件的包含不是相互的 独家的 一个目标 文件可以属于多个包 我正在使用 CMake 2 8 9 并尝试 CPack 我知道这是可行的 安装
  • 是否可以使用 Convert-sass 转换整个文件夹? (scss 到 sass)

    我在一堆 SCSS 格式的文件夹中有一堆文件 我需要将其全部转换为 SASS 格式 并且我知道 sass 有一个特定的命令来转换 sass 但是我不确定是否可以转换整个文件夹 其中包含文件夹 如果可能的话 那么如何convert sass
  • yii2 时区格式化程序中的问题

    php ini 中的时区是 UTC 系统时区为UTC yii 默认时区是 UTC 但在保存到数据库之前 我的日期时间属性会转换为我的时区 亚洲 加尔各答 例如 UTC 时间 12 00 小时 我的输入 17 30hrs 我在 db 中期望的
  • 如何以编程方式关闭 Android 手机?

    是否可以通过编程方式关闭移动设备 那是不使用 su 命令 这是可能的 但你需要一个RootedAndroid 设备Superuser使用权 除非您的应用程序已使用 Root 签名 否则您无法在没有 Root 的情况下执行此操作System
  • 模板专业化是否扩展或覆盖通用模板?

    template
  • 让 Android 应用程序监听共享链接

    当用户共享来自其他应用程序 如浏览器 的 URL 时 我希望我的 Android 应用程序显示为选项 我如何注册我的应用程序来做到这一点 我该如何对链接共享做出反应 多谢 Edit 我尝试过像这样使用 IntentFilter 但没有成功
  • 如何使用audio_service和just_audio在Flutter中查找当前歌曲时长

    当您设置MediaItem in 音频服务 https pub dev packages audio service你还不知道歌曲时长 因为只是音频 https pub dev packages just audio目前还没有任何更改可以告
  • jQuery 与 ExtJS 兼容吗?

    我相信 Ext js 使用了 jQuery 但我不确定 有谁知道是否与 jQuery 和 Ext js 完全兼容 Ext js 完全独立于 jQuery 因此不以任何方式依赖 jQuery 不知道 完全兼容性 是什么意思 但您可以在同一页面
  • Xcode UI 测试允许系统警报系列

    我有问题 如果我尝试允许系列系统警报 只工作一次 而下一个警报不 允许 我在谷歌上搜索了更多时间 并且知道了那个帖子 Xcode 7 UI 测试 如何在代码中消除一系列系统警报 https stackoverflow com questio
  • 我们可以在同一个 EAR 中跨 Web 应用程序共享 CDI @ApplicationScoped bean 实例吗?

    我有一个 JavaEE 应用程序 它有 2 个 Web 应用程序 我还有另一个库 Web 模块 其中包含 common bean 注释为 ApplicationScoped 我的问题是 我可以在两个 Web 应用程序之间共享 common
  • 浏览器如何判断是下载还是显示

    我有一个 Web 资源 它返回 json 内容Content Type application json 通常内容会直接显示在浏览器中 但有时不会 而是显示下载提示 我知道有一个标题Content Disposition inline at
  • jQuery:如何在单击缩略图时显示图像弹出窗口?

    在我的 aspx 页面中 我有一个缩略图 img 当用户单击该图像时 我希望显示一个弹出窗口 用较大 完整 版本的图像遮挡 UI 的其余部分 有没有任何插件可以做到这一点 有很多 jQuery 插件可用于此 Thickbox http co
  • Google Play 商店是否支持华为 HMS?

    我有一个带有常见谷歌广告和应用内支付功能的应用程序 它已被 Play 商店接受 现在我想让它同时支持GMS和HMS 根据适当服务的可用性 应用程序可以决定使用哪个平台 该应用程序内置了华为功能 在我自己的设备上测试时运行良好 然而 一旦华为
  • @Inject 通过 URL 将参数传递给 CDI @Named bean

    如果我无法将 ManagedProperty 注释与 Named 一起使用 因为 ManagedProperty 在 CDI 中不起作用 那么如何将 URL 中的参数传递给 Facelets 客户端 在我的代码中 我想通过 后退 和 前进