0

我在 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;
}
}

索引.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>
4

1 回答 1

0

替换getSession(false)getSession(true)

HttpSession session = (HttpSession) context.getExternalContext().getSession(true);

布尔值告诉在会话尚未创建时是否应该创建会话。因此,您有可能在那时还没有创建它,因此每当您在其上调用任何方法时都会getSession(false)冒着风险。另请参阅javadocnullNullPointerException


与具体问题无关,改用清洁剂ExternalContext#getSessionMap()。在您的 JSF 代码中有“原始”javax.servlet导入通常表示 JSF 代码中有异味。即做某事不必要地过于复杂。然后,您应该使用纯 JSF API 寻找更简单的方法。

代替

HttpSession session = (HttpSession) context.getExternalContext().getSession(true);
String sessionId = (String) session.getAttribute("sessionid");
if (sessionId == null || "".equals(sessionId)) {
    throw new RuntimeException("sessionid is missing!");
}

经过

String sessionId = (String) context.getExternalContext().getSessionMap().get("sessionid");
if (sessionId == null || "".equals(sessionId)) {
    throw new RuntimeException("sessionid is missing!");
}
于 2012-04-13T13:56:29.597 回答