我在JSF 2.0中创建了一个自定义组件。其目的是在输入文本框中显示会话属性值。我希望在HttpSessionListener sessionCreated
方法中创建会话属性。问题是encodeAll
方法在sessionCreated
方法之前被调用。如何在sessionCreated
之前调用encodeAll
?
的web.xml
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/components.taglib.xml</param-value>
</context-param>
<listener>
<listener-class>mycomp.jsf.listener.MyListener</listener-class>
</listener>
components.taglib.xml
<facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
version="2.0">
<namespace>http://mycomp/jsf/components</namespace>
<tag>
<tag-name>mycomp</tag-name>
<component>
<component-type>MyComp</component-type>
</component>
</tag>
</facelet-taglib>
MyListener.java
public class MyListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent event) {
HttpSession session = event.getSession();
session.setAttribute("sessionid", session.getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
}
}
MyComp.java
@FacesComponent(value = "MyComp")
public class MyComp extends UIComponentBase {
public MyComp() {
setRendererType(null);
}
protected Class getComponentClass() {
return this.getClass();
}
@Override
public void decode(FacesContext context) {
//some logic
}
@Override
public void encodeAll(FacesContext context) throws IOException {
String clientId = getClientId(context) + ":token";
HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
String sessionId = (String) session.getAttribute("sessionid");
if (sessionId == null || "".equals(sessionId)) {
throw new RuntimeException("sessionid is missing!");
}
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", this);
writer.writeAttribute("type", "text", "type");
writer.writeAttribute("name", clientId, "name");
writer.writeAttribute("value", sessionId, "value");
writer.endElement("input");
}
@Override
public String getFamily() {
return null;
}
}
的index.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:t="http://mycomp/jsf/components">
<h:head>
</h:head>
<h:body>
<h:form>
<t:mycomp />
</h:form>
</h:body>
</html>
答案 0 :(得分:0)
将getSession(false)
替换为getSession(true)
。
HttpSession session = (HttpSession) context.getExternalContext().getSession(true);
布尔值表示在尚未创建会话时是否应创建会话。使用getSession(false)
时,如果在此时尚未创建null
,那么当您调用任何方法时,NullPointerException
就会产生ExternalContext#getSessionMap()
。另请参阅javadoc。
无关,更清洁的是使用javax.servlet
代替。在JSF代码中导入“原始”HttpSession session = (HttpSession) context.getExternalContext().getSession(true);
String sessionId = (String) session.getAttribute("sessionid");
if (sessionId == null || "".equals(sessionId)) {
throw new RuntimeException("sessionid is missing!");
}
通常表示JSF代码中有气味。即有些东西不必要地过于复杂。然后,您应该使用纯JSF API寻找更简单的方法。
替换
String sessionId = (String) context.getExternalContext().getSessionMap().get("sessionid");
if (sessionId == null || "".equals(sessionId)) {
throw new RuntimeException("sessionid is missing!");
}
通过
{{1}}