我是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());