通过 postValidate 进行 JSF 跨字段验证,无需在支持 bean 中按名称查找组件

2023-12-01

我正在构建一个登录表单复合组件。使用它的页面将传递一个事件处理程序来验证用户名和密码。通常(不使用复合组件)当我们通过以下方式执行跨字段验证时postValidate,事件处理程序必须按名称查找字段的组件。验证器最好不要这样做,因为这些是应该抽象的组件的内部细节。

知道如何获取用户名和密码字段的转换值吗?postValidate处理程序不知道复合组件的内部细节?

Update:这样做的目的并不是完全避免按名称查找组件,而是能够以不需要使用页面和/或 bean 来了解其内部细节的方式跨字段验证复合组件的字段。组件。


这是可以做到的。在下面的代码中,特别注意postValidate复合组件中的事件和postValidate支持组件中的方法。注意它是如何解决的MethodExpression属性并调用传入的方法。

这是复合组件:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:cc="http://java.sun.com/jsf/composite"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui">

    <!-- Login form. -->
    <cc:interface componentType="com.example.LoginForm">
        <cc:attribute name="emailAddress" type="java.lang.String" required="true"/>
        <cc:attribute name="rememberMe" type="java.lang.Boolean" required="true"/>
        <cc:attribute name="checkCredentials"
                      method-signature="void checkCredentials(java.lang.String,java.lang.String,java.lang.String)"
                      shortDescription="Parameters are clientId, username and password. If credentials are invalid, attach a FacesMessage to the component specified by clientId."
                      required="true"/>
        <cc:attribute name="actionListener" method-signature="void actionListener()" required="true"/>
        <cc:attribute name="registerOutcome" type="java.lang.String" required="true"/>
        <cc:attribute name="recoverPasswordOutcome" type="java.lang.String" required="true"/>
        <cc:attribute name="headerTitle" type="java.lang.String" default="Sign In"/>
        <cc:attribute name="emailAddressLabel" type="java.lang.String" default="Email address:"/>
        <cc:attribute name="passwordLabel" type="java.lang.String" default="Password:"/>
        <cc:attribute name="rememberMeLabel" type="java.lang.String" default="Stay signed in on this machine"/>
        <cc:attribute name="loginLabel" type="java.lang.String" default="Sign In"/>
        <cc:attribute name="recoverPasswordLabel" type="java.lang.String" default="Forgot password?"/>
        <cc:attribute name="emailAddressRequiredMessage" type="java.lang.String" default="Email address required"/>
        <cc:attribute name="passwordRequiredMessage" type="java.lang.String" default="Password required"/>
        <cc:attribute name="registerLabel" type="java.lang.String" default="Register"/>
    </cc:interface>

    <cc:implementation>
        <h:outputStylesheet library="components/example/login-form" name="style.css"/>

        <div id="#{cc.clientId}">
            <h:form id="form">

                <f:event type="postValidate" listener="#{cc.postValidate}"/>

                <div style="margin-top:10px;">
                    <p:panel header="#{cc.attrs.headerTitle}" styleClass="loginPanel">
                        <div class="login-form_errorContainer">
                            <p:messages rendered="#{facesContext.maximumSeverity.ordinal ge 2}"/>
                        </div>
                        <h:panelGrid columns="3">
                            <h:outputText styleClass="login-form_label" value="#{cc.attrs.emailAddressLabel}"/>
                            <h:panelGroup styleClass="login-form_cell">
                                <h:inputText id="emailAddress"
                                             value="#{cc.attrs.emailAddress}"
                                             required="true"
                                             requiredMessage="#{cc.attrs.emailAddressRequiredMessage}"
                                             styleClass="login-form_field"
                                             immediate="true"/>
                            </h:panelGroup>
                            <h:panelGroup/>

                            <h:outputText styleClass="login-form_label" value="#{cc.attrs.passwordLabel}"/>
                            <h:panelGroup styleClass="login-form_cell">
                                <h:inputSecret id="password"
                                               value="#{cc.attrs.password}"
                                               required="true"
                                               requiredMessage="#{cc.attrs.passwordRequiredMessage}"
                                               styleClass="login-form_field"
                                               immediate="true"/>
                            </h:panelGroup>
                            <h:link styleClass="login-form_link" value="#{cc.attrs.recoverPasswordLabel}" outcome="#{cc.attrs.recoverPasswordOutcome}"/>

                            <h:panelGroup/>
                            <p:selectBooleanCheckbox value="#{cc.attrs.rememberMe}" itemLabel="#{cc.attrs.rememberMeLabel}" immediate="true"/>
                            <h:panelGroup/>

                            <h:panelGroup/>
                            <h:panelGroup>
                                <p:commandButton id="submitForm" value="#{cc.attrs.loginLabel}" actionListener="#{cc.attrs.actionListener}" update="form"/>
                                <span class="login-form_or">or</span>
                                <h:link styleClass="login-form_link" value="#{cc.attrs.registerLabel}" outcome="#{cc.attrs.registerOutcome}"/>
                            </h:panelGroup>
                            <h:panelGroup/>
                        </h:panelGrid>
                    </p:panel>
                </div>
            </h:form>
        </div>
    </cc:implementation>
</html>

支撑成分:

@FacesComponent("com.example.LoginForm")
public class LoginFormComponent extends UIInput implements NamingContainer
{
    @Override
    protected Object getConvertedValue(FacesContext context, Object newSubmittedValue) throws ConverterException
    {
        UIInput emailAddressComponent = (UIInput) findComponent(EMAIL_ADDRESS_ID);
        UIInput passwordComponent = (UIInput) findComponent(PASSWORD_ID);
        String emailAddress = (String) emailAddressComponent.getValue();
        String password = (String) passwordComponent.getValue();
        return new LoginFormValue(emailAddress, password);
    }

    public void postValidate(ComponentSystemEvent e) {
        FacesContext ctx = getFacesContext();

        // Don't validate credentials if the username and/or password fields are invalid.
        if (!ctx.getMessageList(EMAIL_ADDRESS_ID).isEmpty() || !ctx.getMessageList(PASSWORD_ID).isEmpty())
        {
            return;
        }

        LoginFormValue value = (LoginFormValue) getConvertedValue(null, null);
        MethodExpression checkCredentials = (MethodExpression) getAttributes().get(CHECK_CREDENTIALS_ATTRIBUTE_NAME);
        checkCredentials.invoke(ctx.getELContext(), new Object[]{getClientId(), value.getEmailAddress(), value.getPassword()});
    }

    @Override
    public String getFamily()
    {
        return "javax.faces.NamingContainer";
    }

    public static final String CHECK_CREDENTIALS_ATTRIBUTE_NAME = "checkCredentials";
    public static final String EMAIL_ADDRESS_ID = "form:emailAddress";
    public static final String PASSWORD_ID = "form:password";
}

The LoginFormValue完整性类:

public class LoginFormValue
{
    public LoginFormValue(String emailAddress, String password)
    {
        this.emailAddress = emailAddress;
        this.password = password;
    }

    public String getEmailAddress()
    {
        return emailAddress;
    }

    public String getPassword()
    {
        return password;
    }

    private String emailAddress;
    private String password;
}

使用登录表单的页面:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ex="http://java.sun.com/jsf/composite/components/example">
    <h:head>
        <title></title>
    </h:head>
    <h:body>
        <ui:composition template="/WEB-INF/templates/myLayout.xhtml">
            <ui:define name="windowTitle">Sign In</ui:define>
            <ui:define name="body">

                <ex:login-form emailAddress="#{loginBean.emailAddress}"
                               rememberMe="#{loginBean.rememberMe}"
                               checkCredentials="#{loginBean.checkCredentials}"
                               actionListener="#{loginBean.submit()}"
                               recoverPasswordOutcome="recover-password"
                               registerOutcome="signup"/>

            </ui:define>
        </ui:composition>
    </h:body>
</html>

最后,页面的支持 bean:

@Named
@RequestScoped
public class LoginBean implements Serializable
{
    public String getEmailAddress()
    {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress)
    {
        this.emailAddress = emailAddress;
    }

    public boolean isRememberMe()
    {
        return rememberMe;
    }

    public void setRememberMe(boolean rememberMe)
    {
        this.rememberMe = rememberMe;
    }

    /** Action listener for login-form. Called after validation passes. */
    public void submit()
    {
        User user = userDao.findByEmailAddress(emailAddress);
        userRequestBean.login(user.getUserId());

        // Remember me
        if (!rememberMe)
        {
            return;
        }

        // Handle rememberMe here (create a cookie, etc.)
    }

    /** Called by the backing component's postValidate event handler */
    public void checkCredentials(String clientId, String emailAddress, String password)
    {
        if (!securityEjb.checkCredentials(emailAddress, password))
        {
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Incorrect email address/password", null);
            FacesContext ctx = FacesContext.getCurrentInstance();
            ctx.addMessage(clientId, message);
            ctx.renderResponse();
        }
    }

    private String emailAddress = "";

    private boolean rememberMe = true;

    @Inject
    private UserRequestBean userRequestBean;

    @EJB
    private SecurityEjb securityEjb;

    @EJB
    private UserDao userDao;

    @EJB
    private LoginCookieDao loginCookieDao;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过 postValidate 进行 JSF 跨字段验证,无需在支持 bean 中按名称查找组件 的相关文章

  • 检查发送到网页的请求数

    我正在编写一个 Java 多线程应用程序 它可以访问不同 Web 服务器的数百万个 有时甚至数十亿个 URL 这个想法是检查这些 URL 是否给出有效的 200OK 响应或 404 其他代码 我如何知道我的程序是否不会在他们的服务器上造成高
  • jpa2 CriteriaBuilder order by “ORDER BY 表达式必须出现在选择列表中”

    我正在写一个查询标准生成器 但无法添加order by子句 因为它随消息一起抛出错误ORDER BY 表达式必须出现在选择列表中这是我的实体 public class A Integer aId ManyToOne JoinColumn n
  • 初始堆大小无效。无法创建Java虚拟机

    我遇到了下一个问题 我尝试通过startup bat手动启动Tomcat 但似乎没有显示任何结果 然后我尝试运行shutdown bat 控制台显示如下 D apache tomcat 7 0 35 bin gt startup bat U
  • EL 通过 Scriptlet

    在 JSP 中使用 EL 相对于 scriptlet 的优势是什么 EL 被认为是无脚本语言 EL 使 JSP 免受容易出错原始 Java 代码并强制您根据 MVC 思想编写 JSP EL 或像 JSTL 这样的标签库 不可能实现的任何事情
  • 全静态方法和应用单例模式有什么区别?

    我正在创建一个数据库来存储有关我的网站用户的信息 我正在使用 stuts2 因此使用 Java EE 技术 对于数据库 我将创建一个 DBManager 我应该在这里应用单例模式还是将其所有方法设为静态 我将使用这个 DBManager 进
  • AffineTransform.rotate() - 如何同时缩放、旋转和缩放?

    我有以下代码 它可以完成我想要绘制一个上面有一些棋子的棋盘的 第一部分 Image pieceImage getImage currentPiece int pieceHeight pieceImage getHeight null dou
  • Android 游戏偶尔出现延迟

    我正在用 Java 制作一个简单的 Android 游戏 我注意到每 20 40 秒就会出现一些烦人的延迟 首先 我认为它们是由垃圾收集器引起的 但当我检查 LogCat 时 我发现游戏滞后时没有垃圾收集 每当游戏开始滞后时 我都会标记日志
  • 在 Java 中创建带注释的对象时收到通知

    Intent 我有一个自定义 Java 注释 DynamicField public class RESTEndpointInvoker DynamicField key httpTimeout private long httpTimeo
  • 反应式 Spring Webflux REST 控制器内部重定向

    我正在为 spring 反应项目创建简单的控制器服务器 在设置重定向到另一个位置时 我在调用时发现错误http localhost 8080 There was an unexpected error type Internal Serve
  • selenium webdriver 中的多个程序执行不起作用

    Selenium WebDriver 中的多个程序执行不起作用 我编写了 1 个 testNG xml 文件和 2 个 java 类 我尝试从 xml 文件运行这两个 java 类 但这不起作用 XML代码
  • 使用 JNI 从 Java 代码中检索 String 值的内存泄漏

    我使用 GetStringUTFChars 从使用 JNI 的 java 代码中检索字符串的值 并使用 ReleaseStringUTFChars 释放该字符串 当代码在 JRE 1 4 上运行时 不会出现内存泄漏 但如果相同的代码在 JR
  • java中日期转换dd-MMM-yyyy到dd-MM-yyyy

    在Java中将23 Mar 2011转换为23 03 2011的最简单方法是什么 感谢大家 这似乎解决了这个问题 try Calendar cal Calendar getInstance cal setTime new SimpleDat
  • JFrame Glasspane 也优于 JDialog,但不应该

    我有一个带有 Glasspane 的 JFrame 未装饰 该框架打开一个 JDialog 也未装饰 也有一个 glassPane 并隐藏自身 setVisible false Glasspanes 通过 setGlassPane 设置 对
  • 在 REST Web 服务中接受逗号分隔值

    我正在尝试接收 REST URI 中以逗号分隔值形式的字符串列表 示例 http localhost 8080 com vogella jersey first rest todo test 1 abc test 其中 abc 和 test
  • 更新分页。是否可以?

    他们是否存在一些方法来处理更新分页 例如我有 100 行类型 Id private Integer id Column private boolean flag Column private Date last 一开始它们看起来像 id f
  • 如何列出Resources文件夹中的所有文件(java/scala)

    我正在编写一个函数 需要访问资源中的文件夹 并循环遍历所有文件名 如果这些文件符合条件 则加载这些文件 new File getClass getResource images sprites getPath listFiles 返回空指针
  • 使用正则表达式匹配阿拉伯文文本

    我试图使用正则表达式仅匹配阿拉伯语文本 但出现异常 这是我的代码 txt matches P Arabic 这是例外情况 线程 main 中的异常 java util regex PatternSyntaxException 索引 9 附近
  • 如何创建具有同等时间元素的 JavaFX 转换?

    我正在尝试 JavaFX 和动画 尤其是PathTransition 我正在创建一个简单的程序 使球 弹跳 而不使用QuadCurveTo班级 到目前为止 这是我的代码 Ellipse ball new Ellipse 375 250 10
  • CSS3 背景渐变未验证,有人可以告诉我为什么吗?里面的代码示例

    有人能告诉我为什么下面的 css 没有验证吗 我一直在尝试自己研究这个问题 但没有运气 我读过的所有文档都说这是在 css3 中进行渐变的正确原因 header color white font size 12px font family
  • Java 可变 BigInteger 类

    我正在使用 BigIntegers 进行计算 该计算使用一个调用 multiply 大约 1000 亿次的循环 并且从 BigInteger 创建新对象使其非常慢 我希望有人编写或找到了 MutableBigInteger 类 我在 jav

随机推荐

  • Azure AD登录后如何重定向到特定页面?

    我正在将 Azure AD 登录集成到我的应用程序中 我想在成功登录天蓝色广告后重定向到特定操作 我的 Startup Auth cs 文件中有以下代码 但它没有重定向到redirecturi 任何人都可以建议我如何在成功登录后重定向到自定
  • Python Tkinter Treeview 添加图像作为列值

    我试图将图像添加到树视图上每一行的第一列 但无论我做什么 最终总是显示对象 pyimage1 的名称而不是实际图像 正如这张图片所示 我正在使用的代码是这样的 from tkinter import PhotoImage self img
  • 如何使用 jQuery 在 30 分钟内使 cookie 过期?

    如何让 Cookie 在 30 分钟内过期 我正在使用 jQuery cookie 我能够做这样的事情 cookie example foo expires 1 这是 1 天的时间 但是我们如何将到期时间设置为 30 分钟 30分钟是30
  • 在 SQL SERVER 2008 中从字符串转换日期和/或时间时转换失败

    我有以下 SQL UPDATE student queues SET Deleted 0 last accessed by raja last accessed on CONVERT VARCHAR 24 23 07 2014 09 37
  • 是否有 C# 中的 JSON Web Token (JWT) 示例?

    我觉得我在这里服用了疯狂的药 通常 对于任何给定的任务 网络上总会有一百万个库和示例 我正在尝试使用 JSON Web Tokens JWT 来实现 Google 服务帐户 的身份验证 如下所述here 但是 只有 PHP Python 和
  • 使用 C#/.NET 将图像上传到服务器并将文件名存储在数据库中

    我目前正在使用以下代码片段将数据插入数据库的表中 效果很好 但是 我想开始添加文件名数据 但不确定如何继续 我有以下内容 Create command comm new SqlCommand INSERT INTO Entries Titl
  • 基于主机的卡模拟,有什么指导吗?

    我是这个领域的新手 我有一个 Nexus S CyanogenMod11 Android Kitkat 4 4 2 我需要使用 HCE 基于主机的卡模拟 模式来模拟非接触式卡 为了实现这一目标 我需要遵循的步骤和技巧有什么指导吗 我需要对模
  • 如何从 hashCode 中获取字符串

    我正在开发一个项目 我得到了我的密码字段值hashCode出于安全目的 并将该 hashCode 存储在数据库中 现在我想从 hashCode 中恢复密码 我该怎么做 是否可以从 hashCode 中获取 String 值 如果不是 任何人
  • 为什么docker build后node_modules为空?

    为什么我的 docker 数据卷在主机系统上挂载为空 当 的时候docker compose up完成后我可以执行到 docker 容器并查看node modules目录中 我可以看到所有已成功安装的模块 但是当我检查我的node modu
  • 有没有办法在 ActionScript 中获取字形的实际边界框?

    我正在学习 ActionScript Flash 我喜欢玩弄文本 并且使用出色的 Java2D API 做了很多这样的事情 我想知道的一件事是 你到底在哪里画那个字形 TextField 类提供了方法getBounds and getCha
  • IE 中的 JQuery 复选框列表问题?保存为 on,on,on 的值应为 10,12,13 等

    我有一个使用 javascript 呈现的复选框列表
  • 开发和生产属性

    我有一个 GlassFish j2ee 应用程序 我在一个盒子上进行开发 生产是一个远程盒子 我有一个生成文件的函数 并且我需要根据我的开发盒或生产情况使文件的位置有所不同 有什么自动方法可以进行切换 这样我就不必根据部署位置来编辑源文件
  • 春季启动+休眠

    我的 Maven 依赖项出了什么问题 当我包含 JPA 时 我有例外列表 这是我的 Maven 依赖项
  • 如何将Hive连接到asp.net项目

    你好 我对 Hadoop 很陌生 我已将 Microsoft HDInsight 安装到本地系统 现在我想连接到 hive 和 HBase 但用于 HIVE 连接 我必须指定连接字符串 端口 用户名 密码 但我无法弄清楚如何获得这个值 我尝
  • Git:在提交/推送之前运行过滤器?

    有没有办法在提交之前通过过滤器运行更改的文件 我希望确保文件遵循项目的编码标准 我还想在提交 推送实际发生之前编译并运行一些测试 所以我知道存储库中的所有内容实际上都有效 预提交挂钩 继续阅读git钩子 Git 书籍有一个example例如
  • 将小计添加到 Pandas Groupby

    我正在寻找一种更干净的方法来将小计添加到 Pandas groupby 中 这是我的数据框 df pd DataFrame Category np random choice Group A Group B 50 Sub Category
  • 需要在 XNA 4.0 中使用实例的帮助

    我来询问有关 XNA 实例化的问题 我是一名初级 XNA 开发人员 最近才从 2D 游戏转向 3D 游戏 我正在尝试绘制大量仅由代码中的顶点组成的立方体 正如人们可能怀疑的那样 绘制大量这些立方体会给我的计算机带来相当大的压力 当我寻找一种
  • 在 where 子句中使用 php 变量时 MySQL 查询不起作用

    我是 PHP 和 MySQL 的新手 我正在尝试制作一个简单的搜索表单 我希望使用它根据表单中输入的输入文本显示数据库的结果 我的代码是这样的 Form php
  • Chrome 上字体大小渲染不一致的问题 [已关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 I am having an css issue on my site The font size is not consistent across all pages The di
  • 通过 postValidate 进行 JSF 跨字段验证,无需在支持 bean 中按名称查找组件

    我正在构建一个登录表单复合组件 使用它的页面将传递一个事件处理程序来验证用户名和密码 通常 不使用复合组件 当我们通过以下方式执行跨字段验证时postValidate 事件处理程序必须按名称查找字段的组件 验证器最好不要这样做 因为这些是应