【问题标题】:How to return status messages in JSF?如何在 JSF 中返回状态消息?
【发布时间】:2012-04-02 11:55:57
【问题描述】:

我会让自己很客观:

一个用户注册自己,在这个操作之后register我想显示一些消息说恭喜!欢迎!,如果在我的数据库中有类似duplicated key 的问题,类似的内容或消息。

我已经知道如何使用 RichFaces 显示一些消息,但我想保持简单,RichFaces 与 CSS 有点混淆,所以我现在想避免它。

所以这里是我的页面和我的托管 bean:

    <h:form id="form_user">
        <h:panelGrid columns="3">
            <h:outputLabel for="name" value="Name:" />
            <h:inputText id="name" value="#{personc.personb.person.name}">
                <f:ajax event="blur" listener="#{personValidate.name}" render="m_name" />
            </h:inputText>
            <h:message id="m_name" for="name" />

            <!--other fields...-->

            <h:commandButton value="Register" action="#{personc.register}">
                <f:ajax execute="@form" render="@form" />
            </h:commandButton>

        </h:panelGrid>
    </h:form>

Person Controller(遵循 MVC 结构):

@ManagedBean(name="personc")
@SessionScoped
public class PersonController implements Serializable {
    private static final long serialVersionUID = 2000186666864113813L;

    // attributes
    @EJB PersonEAO personEAO;
    private PersonBean personb;

    public PersonController() {
        personb = new PersonBean();
    }

    // methods
    public String register(){
        if (personEAO.register(personb.getUser(), personb.getPerson())){
            status = "welcome!";
            return "success";
        }else{
            status = "an error occurs";
            return "failure";
        }
    }
        // others methods..

还有 PersonEAO 实体:

@Stateless
@LocalBean
public class PersonEAO {
    @PersistenceContext
    EntityManager em;

    public PersonEAO() {}

    public boolean register(User user, Person person){
        try{
            em.persist(user);

            person.setUser(user);
            em.persist(person);
        }catch(Exception e){
                    // would like to treat better the exceptions here 
                    // should I keep returning boolean here ? or a string would be better ? 
            return false;
        }
        return true;
    }

我有一些问题:

如果我应该继续从 JPA 操作中返回 boolean,我想给用户一个更好的消息,说明发生了什么,例如 duplicate key

【问题讨论】:

  • 小备注:@LocalBeanPersoneEAO bean 上是不必要的。

标签: jsf jsf-2


【解决方案1】:

不要使用布尔标志(或枚举)来指示异常结果。为此使用例外。您只需要添加一些逻辑 PersistenceException 正在包装哪种 JPA 实现特定的异常,然后将其重新抛出为您的特定业务异常,例如自定义public class DuplicateKeyException extends PersistenceException

例如,在您的业务服务实现中

public void register(User user, Person person) throws PersistenceException, DuplicateKeyException {
    try {
        em.persist(user);
        person.setUser(user);
        em.persist(person);
    }
    catch (PersistenceException e) {
        if (Exceptions.is(e, ConstraintViolationException.class)) {
            throw new DuplicateKeyException(e);
        }
        else {
            throw e;
        }
    }
}

Exceptions 实用程序类中使用此方法:

public static <T extends Throwable> boolean is(Throwable exception, Class<T> type) {
    for (;exception != null; exception = exception.getCause()) {
        if (type.isInstance(exception)) {
            return true;
        }
    }

    return false;
}

然后在控制器端处理:

public String register() {
    try {
        personEAO.register(personb.getUser(), personb.getPerson());
        Messages.addGlobalInfo("user.register.success");
        return "success";
    }
    catch (DuplicateKeyException e) {
        logger.log(e); // If necessary.
        Messages.addGlobalError("user.register.error.duplicate");
        return "failure";
    }
}

Messages.addGlobalXxx() 可以将全局FacesMessage 添加到上下文中,如下所示

FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
    FacesMessage.SEVERITY_INFO, someBundle.getString(key), null));

OmniFaces 有一个similar class 可以帮助您。

这样的全局消息将显示在一个

<h:messages globalOnly="true" />

【讨论】:

    【解决方案2】:

    如何创建一个具有预定义值的枚举,而不是 catch(Exception e) 做几个更具体的 catch,并在每个中设置具有该特定枚举值的方法的返回参数

    枚举示例

    public enum REGISTERCODE{
        SUCCESS , DUPLICATE, GENERAL_ERROR, SESSION_EXPIRED, MORE, MORE2; 
    }
    

    把签名改成类似

    public REGISTERCODE register(User user, Person person){...return REGISTERCODE.SUCCESS...
    

    也..您可以在语言文件中创建带有前缀 ResgisterCode_ 的密钥,然后根据此向您的用户返回消息,例如

    localizationClass.getMessageFromBundle("ResgisterCode_"+REGISTERCODE_variable.name())
    

    REGISTERCODE_variable 是注册方法的返回值

    然后在您的personc bean 中的调用方方法中根据枚举值返回详细消息...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多