java 如何使用 AJAX 数据验证创建 JSF 表单

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10454692/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 01:06:20  来源:igfitidea点击:

How to create JSF form with AJAX data validation

javajsfjsf-2

提问by Peter Penzov

I'm working on a JSF form prototype for inserting data into database table using AJAX data validation This is the JSF page:

我正在研究一个 JSF 表单原型,用于使用 AJAX 数据验证将数据插入数据库表 这是 JSF 页面:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"    
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    <h:head>
        <ui:insert name="header">           
            <ui:include src="header.xhtml"/>         
        </ui:insert>
    </h:head>
    <h:body>

        <h1><img src="resources/css/images/icon.png" alt="NVIDIA.com" /> History Center</h1>
        <!-- layer for black background of the buttons -->
        <div id="toolbar" style="margin: 0 auto; width:1180px; height:30px; position:relative;  background-color:black">
            <!-- Include page Navigation -->
            <ui:insert name="Navigation">           
                <ui:include src="Navigation.xhtml"/>         
            </ui:insert>

        </div>  

        <div id="logodiv" style="position:relative; top:35px; left:0px;"> 
            <h:graphicImage alt="Demo Insert Form"  style="position:relative; top:-20px; left:9px;"  value="resources/images/logo_databasez.png" />
        </div>
        <div id="main" style="margin: 0 auto; width:1190px; height:700px; position:absolute;  background-color:transparent; top:105px">

            <div id="mainpage" style="margin: 0 auto; width:1190px; height:500px; position:absolute;  background-color:transparent; top:80px">

                <div id="settingsHashMap" style="width:350px; height:400px; position:absolute;  background-color:r; top:20px; left:1px">
                    <h:form>
                        <div id="settingsdiv" style="width:750px; height:400px; position:absolute;  background-color:r; top:20px; left:1px">

                            <h:panelGrid columns="2">
                                <h:panelGroup>Session ID</h:panelGroup>
                                <h:panelGroup>
                                    <h:inputText id="sessionid" value="#{DatabaseController.formMap['sessionid']}" >
                                        <f:validateLength minimum="0" maximum="15"/>
                                        <f:ajax render="sessionidvalidate" event="blur"/>                                          
                                    </h:inputText>
                                    <h:outputText id="sessionidvalidate" rendered="#{DatabaseController.validateSessionid}" value="session is already registered" />
                                </h:panelGroup>

                                <h:panelGroup>User ID</h:panelGroup>
                                <h:panelGroup>
                                    <h:inputText id="userid" value="#{DatabaseController.formMap['userid']}" >
                                        <f:validateLength minimum="0" maximum="15"/>
                                    </h:inputText>
                                </h:panelGroup>

                                <h:panelGroup>Login Time</h:panelGroup>
                                <h:panelGroup>
                                    <h:inputText id="logintime" value="#{DatabaseController.formMap['logintime']}" >
                                        <f:validateLength minimum="0" maximum="35"/>
                                    </h:inputText>
                                </h:panelGroup>

                                <h:panelGroup>Last Refresh Time</h:panelGroup>
                                <h:panelGroup>
                                    <h:inputText id="lastrefreshtime" value="#{DatabaseController.formMap['lastrefreshtime']}" >
                                        <f:validateLength minimum="0" maximum="35"/>
                                    </h:inputText>
                                </h:panelGroup>

                                <h:panelGroup>User IP</h:panelGroup>
                                <h:panelGroup>
                                    <h:inputText id="userip" value="#{DatabaseController.formMap['userip']}" >
                                        <f:validateLength minimum="0" maximum="15"/>
                                    </h:inputText>
                                </h:panelGroup>

                            </h:panelGrid>          

                        </div>   

                        <div id="settingstwodiv" style="width:150px; height:60px; position:absolute;  background-color:transparent; top:380px; left:800px">

                            <h:commandButton value="Create User" action="#{DatabaseController.saveData}"/>

                        </div> 
                    </h:form> 

                </div>   

            </div>  
        </div>

    </h:body>
</html>

This is the managed bean:

这是托管 bean:

import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
// or import javax.faces.bean.SessionScoped;
import javax.inject.Named;
/* include SQL Packages */
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import javax.annotation.Resource;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
// or import javax.faces.bean.ManagedBean;   

import org.glassfish.osgicdi.OSGiService;

// Demo Insert Form
@Named("DatabaseController")
@SessionScoped
public class Database implements Serializable {

    private HashMap<String, String> formMap = new HashMap<>();

    public Database() {
    }
    /* Call the Oracle JDBC Connection driver */
    @Resource(name = "jdbc/Oracle")
    private DataSource ds;

    public HashMap<String, String> getformMap() {
        return formMap;
    }

    /*

    CREATE TABLE ACTIVESESSIONS(
    SESSIONID VARCHAR2(30 ) NOT NULL,
    USERID VARCHAR2(30 ) NOT NULL,
    LOGINTIME TIMESTAMP(6),
    LASTREFRESHTIME TIMESTAMP(6),
    USERIP VARCHAR2(30 )
    )
    /
     */
    @PostConstruct
    public void hashMapGenerate() {
        /* Initialize the hashmap */
        formMap.put("sessionid", null);
        formMap.put("userid", null);
        formMap.put("logintime", null);
        formMap.put("lastrefreshtime", null);
        formMap.put("userip", null);
    }

    public int saveData() throws SQLException, java.text.ParseException {
//        formMap = new HashMap<String, String>();

        String SqlStatement = null;

        if (ds == null) {
            throw new SQLException();
        }

        Connection conn = ds.getConnection();
        if (conn == null) {
            throw new SQLException();
        }

        PreparedStatement ps = null;

        /*

        CREATE TABLE ACTIVESESSIONS(
        SESSIONID VARCHAR2(30 ) NOT NULL,
        USERID VARCHAR2(30 ) NOT NULL,
        LOGINTIME TIMESTAMP(6),
        LASTREFRESHTIME TIMESTAMP(6),
        USERIP VARCHAR2(30 )
        )
        /
         */

        try {
            conn.setAutoCommit(false);
            boolean committed = false;
            try {           /* insert into Oracle the default system(Linux) time */
                SqlStatement = "INSERT INTO ACTIVESESSIONS"
                        + " (SESSIONID, USERID, LOGINTIME, LASTREFRESHTIME, USERIP)"
                        + " VALUES (?, ?, ?, ?, ?)";

                ps = conn.prepareStatement(SqlStatement);

                ps.setString(1, formMap.get("sessionid"));
                ps.setString(2, formMap.get("userid"));
                ps.setTimestamp(3, toTimeStamp(formMap.get("logintime")));
                ps.setTimestamp(4, toTimeStamp(formMap.get("lastrefreshtime")));
                ps.setString(5, formMap.get("userip"));

                ps.executeUpdate();

                conn.commit();
                committed = true;
            }
            finally 
            {
                if (!committed) {
                    conn.rollback();
                }
            }
        } finally {
            /* Release the resources */
            ps.close();
            conn.close();
        }

        return 0;

    }
    private Timestamp toTimeStamp(String s) throws java.text.ParseException
    {
        Timestamp ts = null;
        java.util.Date date = null;
        if (s == null || s.trim().isEmpty()) return ts;

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.S");
        date = (java.util.Date) sdf.parse(s);
        ts = new Timestamp(date.getTime());

        return ts;

    }

    /* Validators section */
    public boolean getvalidateSessionid(){

        //do SQL query

        return true;
    }

}

I'm having difficulties in implementing the form validation. I want to pass the String entered by the used and check it into database is this value already into the database table. Here I'm calling the Java method to check the value:

我在实施表单验证时遇到困难。我想通过使用输入的字符串并将其检入数据库,这个值是否已经进入数据库表。这里我调用 Java 方法来检查值:

                            <h:panelGroup>
                                <h:inputText id="sessionid" value="#{DatabaseController.formMap['sessionid']}" >
                                    <f:validateLength minimum="0" maximum="15"/>
                                    <f:ajax render="sessionidvalidate" event="blur"/>                                          
                                </h:inputText>
                                <h:outputText id="sessionidvalidate" rendered="#{DatabaseController.validateSessionid}" value="session is already registered" />
                            </h:panelGroup>

How I can send the inserted value to the Java method?

如何将插入的值发送到 Java 方法?

Best Wishes

最好的祝愿

回答by BalusC

You need to create a Validator.

您需要创建一个Validator.

Kickoff example:

开场示例:

@FacesValidator("sessionIdValidator")
public class SessionIdValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        // ...

        if (yourDataService.existSessionId(value)) {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
                "Session ID is already in use, please choose another.", null));
        }
    }

}

Use it as follows:

使用方法如下:

<h:inputText id="sessionid" value="#{DatabaseController.formMap['sessionid']}">
    <f:validateLength minimum="0" maximum="15" />
    <f:validator validatorId="sessionIdValidator" />
    <f:ajax event="blur" render="sessionidMessage" />                                          
</h:inputText>
<h:message id="sessionidMessage" for="sessionid" />

Note that you should use a <h:message>to show validation messages. You haven't any one in your view. Apply the same for all your other fields:

请注意,您应该使用 a<h:message>来显示验证消息。你眼中没有任何人。对所有其他字段应用相同的方法:

<h:inputText id="userid" value="#{DatabaseController.formMap['userid']}">
    <f:validateLength minimum="0" maximum="15" />
    <f:ajax event="blur" render="useridMessage" />                                          
</h:inputText>
<h:message id="useridMessage" for="userid" />


If you want to use @Resourceor @EJBor @Injectin the validator, then replace the @FacesValidatorannotation by @ManagedBeanor (as you seem to use CDI for some reason) @Named:

如果您想在验证器中使用@Resourceor 或@EJBor @Inject,请用or替换@FacesValidator注释@ManagedBean(因为您似乎出于某种原因使用了 CDI)@Named

@Named
public class SessionIdValidator implements Validator {

    @Resource
    private DataSource dataSource;

    @Inject
    private YourDataService yourDataService;

    // ...
}

and use it as follows instead

并按如下方式使用它

    <f:validator binding="#{sessionIdValidator}" />

回答by Kapelchik

Just add listener in your tag h:inputText:

只需在您的标签中添加侦听器h:inputText

<h:inputText id="sessionid" value="#{DatabaseController.formMap['sessionid']}" 
         valueChangeListener="#{DatabaseController.validateSessionid}">

So you can check the entered value on the server side. When a user tabs out of the input field, JSF makes an ajax-call to the server and runs the name input component through the execute portion of the life cycle. This means that JSF will invoke the name input's value-change listener specified in attribute valueChangeListenerduring the validations process phase of the life cycle.

所以你可以在服务器端检查输入的值。当用户退出输入字段时,JSF 对服务器进行 ajax 调用,并在生命周期的执行部分运行名称输入组件。这意味着 JSF 将valueChangeListener在生命周期的验证过程阶段调用属性中指定的名称输入的值更改侦听器。

And I would suggest to implement this method:

我建议实施这种方法:

public void validateSessionid(ValueChangeEvent e) {
    UIInput nameInput = e.getComponent()
    String sessionid = nameInput.getValue()

    //do SQL query
}

After the ajax-call returns JSF renders the h:outputText id="sessionidvalidate".

在 ajax 调用返回后,JSF 呈现h:outputText id="sessionidvalidate".