将JSF视图中的初始化参数传递给后台的托管bean



我是JSF的新手,正在努力将数据传递给我的支持bean。我有一个bean,它应该读取数据并将数据保存到一个特定的表中。该表有两列"Property"one_answers"Val"。这个类的简化版本如下:

@ManagedBean
@SessionScoped
 public class GlobalProperties implements Serializable {
    // private void setKey(param);
    // private String getKey();      
    // some more attributes and getters / setters
    private String property; // + getter/setter    
    private void saveProperty() throws SQLException {
        try {
            dbHandler = dbConnection.connect();
            ps = dbHandler.prepareStatement("UPDATE TABLEXXX SET VAL = '" + getValue() + "' WHERE PROPERTYKEY = '" + getProperty() + "'");
            ps.executeQuery();
            } catch (SQLException ex) {
            Logger.getLogger(GlobalProperties.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
            if (dbHandler != null) {
                dbHandler.close();
            }
        }        
    }
    private void readProperty() throws SQLException {
        try {
            dbHandler = dbConnection.connect();
            ps = dbHandler.prepareStatement("SELECT VAL FROM TABLEXXX WHERE PROPERTYKEY = '" + getProperty() + "'");
            rs = ps.executeQuery();
            while (rs.next()) {
                setValue("VAL");
            }
        } catch (SQLException ex) {
            Logger.getLogger(GlobalProperties.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            if (dbHandler != null) {
                dbHandler.close();
            }
        }    
    }        
}

此类正在多个页面上使用。在使用它的每一页上,都需要为属性属性填充不同的值,因为我必须从表中读取不同的键。在JSF端有一个文本输入,它显示值,并在用户单击保存按钮时进行设置。

每当创建这个类的实例时,我都需要向该类传递一个信息,说明它必须读取什么键。但是,我在JSF方面找不到合适的机制来实现这一点,因为用户不能更改该值非常重要。

我最后一次尝试是使用"preRenderView"-事件如下:

  <f:metadata>
        <f:event type="preRenderView" listener="#{globalProperties.setKey('SYSTEM_NAME')}" />
    </f:metadata>

这是正确的方式吗?

在不需要任何用户操作的情况下,以安全的方式在后台的ManagedBean中设置属性,使其不受用户操作的最佳做法是什么?

谢谢大家。

<f:event type="preRenderView">在每个请求中都被调用。这对于请求范围的bean来说可能是可以的,但对于视图/会话范围的bean则没有必要。另请参阅What can<f: 元数据>lt;f: viewParam>并且<f: viewAction>用于?

另一方面,虽然preRenderView方法可以工作,但是JSF视图应该是声明性的。模型(这个特定透视图中的backingbean)实际上应该基于视图执行初始化,而不是相反。所以当你对此产生怀疑时,你的直觉是正确的。

JSF对此没有专门的方法。最接近的声明性方法是在<f:metadata>中使用<f:attribute>("在视图上定义元数据属性")。

<f:metadata>
    <f:attribute name="key" value="SYSTEM_NAME" />
</f:metadata>

这可由UIViewRoot#getAttributes()在a.o @PostConstruct:中获得

String key = (String) context.getViewRoot().getAttributes().get("key");

或者当你碰巧使用OmniFaces:时

String key = Faces.getMetadataAttribute("key");

OmniFaces showcase应用程序还使用这种方法来声明文档和源代码的路径(例如,请参阅<o:socket> showcase的/push/socket.xhtml源代码)。

另一种方法是通过视图ID对键进行应用程序范围的映射,并依赖于视图ID。

Map<String, String> keysByViewId = new HashMap<>();
keysByViewId.put("/foo.xhtml", "SYSTEM_NAME");

String key = keysByViewId.get(context.getViewRoot().getViewId());

最新更新