【问题标题】:Passing value from Servlet to JSF Action method in WebLogic将值从 Servlet 传递到 WebLogic 中的 JSF Action 方法
【发布时间】:2012-12-25 21:24:01
【问题描述】:

我正在尝试将 ObjectServletdoPost() 传递给 JSF 的 Managed bean 的操作方法。但我做不到。

我尝试将Servlet 的值设置为:

request.getSession().setAttribute(key, "JYM");

并尝试从Managed bean 中检索它:

FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(key)

它正在返回null

这也是从Managed bean返回null

((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getSession().getAttribute(key);

同样来自Managed bean,这是返回null

((HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false)).getAttribute(key)

我将密钥传递为:

'${pageContext.request.contextPath}/uploadservlet;jsessionid=${pageContext.session.id}?key=<h:outputText value="#{uploadBean.key}" />'

uploadBeanManaged bean 的名称,key 生成为:

key = UUID.randomUUID().toString();

key 在 Servlet 和托管 bean 中都保持不变。我打印的是检查。

如何将ObjectServlet 传递到Action?任何指针都会很有帮助。

更新

Managed bean 在会话范围内。

更新

通过使用ServletContext 我可以传递值:

这是我所做的: 在 Servlet 中:

String key = request.getParameter("key");

if (getServletContext().getAttribute(key) == null) {
    List<FileItem> fileFields = new ArrayList<FileItem>();
    fileFields.add(fileField);
    getServletContext().setAttribute(key, fileFields);
} else {
    List<FileItem> fileFields = (List<FileItem>)getServletContext().getAttribute(key);
    fileFields.add(fileField);
}

并且来自会话范围的 bean:

ServletContext servletContext = ((ServletContext)FacesContext.getCurrentInstance().getExternalContext().getContext());
List<FileItem> fileFields = (List<FileItem>)servletContext.getAttribute(key);
servletContext.setAttribute(key, null);

现在fileFields 不再为空。我的理解是 ServletContext 的行为类似于 Application Scoped 变量。

更新

HttpSessionListener的实现:

这是我写的课程:

public class UploadListener implements HttpSessionListener {
    private HttpSession session = null;

    public void sessionCreated(HttpSessionEvent event) {
        session  = event.getSession();
        session.setMaxInactiveInterval(10);
    }

    public void sessionDestroyed(HttpSessionEvent event) {
        session  = event.getSession();
        Set<String> keys = (Set<String>) session.getAttribute("key");
        Map<String, Object> data = (Map<String, Object>) session.getServletContext().getAttribute("key");
        data.keySet().removeAll(keys);
    }
}

我将ServletContext 中的值设置为:

String key = request.getParameter("key");

List<FileItem> fileFields = (List<FileItem>)getServletContext().getAttribute(key);

if (fileFields == null) {
    fileFields = new ArrayList<FileItem>();
    getServletContext().setAttribute(key, fileFields);
}

fileFields.add(fileField);

这就是我调用 Servlet 的方式:'${pageContext.request.contextPath}/uploadservlet?key=&lt;h:outputText value="#{uploadBean.key}" /&gt;'

【问题讨论】:

  • 看看this post。您需要将 bean 放在 JSF 期望的范围内
  • @VikasV 你的意思是来自 servlet 我需要做request.getSession().setAttribute("key", "value");
  • 是的,我是想说。您的 bean 在会话范围内。所以你上面输入的代码应该没问题。
  • @VikasV 我在问题中提到,在第一个代码 sn-p 中,我在 servlet 中做了完全相同的事情。
  • 您设置的是 key 而不是 managed bean。如果您重新查看我提到的帖子,您会看到 managed bean 已放入所需的范围

标签: java jsf servlets weblogic jsf-1.2


【解决方案1】:

如果 servletcontainer 不支持通过jsessionid URL 片段识别 HTTP 会话,则此构造将失败。这是默认支持的,但可以通过特定于 servletcontainer 的配置来关闭它。到目前为止,不幸的是,您的 Weblogic 服务器似乎是这样配置的。

您最好的选择是在应用程序范围内交换数据。 UUID 的随机性足够强,不会引起冲突。您只需要确保在销毁会话时清除与会话相关的数据。否则内存会泄漏。为此,您可以使用HttpSessionListener。如果您将密钥存储在应用程序范围(引用共享数据)和会话范围(引用到目前为止使用的所有密钥的集合)中,那么sessionDestroyed() 实现可以如下所示:

public void sessionDestroyed(HttpSessionEvent event) {
    Set<String> keys = (Set<String>) event.getSession().getAttribute("keys");
    Map<String, Object> data = (Map<String, Object>) event.getSession().getServletContext().getAttribute("data");
    data.keySet().removeAll(keys);
}

更新根据您的更新,获取/设置它们的更优雅的方式是:

String key = request.getParameter("key");
List<FileItem> fileFields = (List<FileItem>) getServletContext().getAttribute(key);

if (fileFields == null) {
    fileFields = new ArrayList<FileItem>();
    getServletContext().setAttribute(key, fileFields);
}

fileFields.add(fileField);

List<FileItem> fileFields = (List<FileItem>) FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().remove(key);
// ...

【讨论】:

  • 谨向您表示诚挚的感谢。我有一点不明白,你想让我在 Application Scope 中有一个托管 bean 吗?或者您是说将密钥存储在 ApplicationMap 中?您能否解释一下如何在 Servlet 中获取应用程序范围?通过使用 ServletContext 进行值传递,我取得了成功。我已经更新了我的问题,向您展示我做了什么。就我所知,单例类的使用方法是错误的还是有风险的?
  • 只需将密钥存储在应用程序范围内。它在 JSF 中确实由 ExternalContext#getApplicationMap() 表示。它甚至可以只是应用程序范围的托管 bean 的一个属性。应用范围由ServletContext 的属性表示。 JSF 还在其中存储应用程序范围的托管 bean,由托管 bean 名称作为关键字。另见例如stackoverflow.com/questions/2633112/… 这种方法没有错误,但是对于密钥冲突的情况有风险。但是,我会再看一下让 Weblogic 接受 jsessionid URL 片段
  • 只是为了确认,我可以在这种情况下使用ServletContext,正如我在我的问题的第二次更新中所展示的那样?
  • 在 JSF 方面,你的意思是?这是可行的,但只是不必要的。 ExternalContext#getApplicationMap() 已经委托给 ServletContext 属性。您知道,JSF 是对“原始”Servlet API 的抽象。另请参阅javadoc
  • 谢谢,它正在工作。所以我不再需要HttpSessionListener,因为我明确删除了密钥,所以没有内存泄漏的机会?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-25
  • 2012-05-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多