在POJO外部容器中检索servlet上下文,会话和请求

时间:2011-01-21 22:04:51

标签: java jsp session servlets javabeans

有没有办法从POJO中检索会话?或者最终从POJO中检索bean。

澄清:

基本上我是从servlet创建一个bean,我需要从Web容器外部(从POJO)访问该bean的属性。我无法将请求传递给pojo;并且需要请求来检索会话。

更具体地说,我有一个Web应用程序,它使用Cactus框架从Web界面运行JUnit测试。但是,调用JUnit测试运行器的servlet是在jar中编译的;我添加了额外的下拉菜单来更改JUnit测试将从中读取的设置以在不同环境(WLI集群)之间切换,因此,如果已经编译了运行器servlet,我无法修改它以处理来自多个环境的额外参数。我已经尝试过写入.dat文件的持久化方法,JUnit测试将通过Reader类读取该文件;我也尝试过最终无法通过JUnit测试访问的bean方法。

4 个答案:

答案 0 :(得分:11)

仅当您的POJO正在运行HttpServletRequest相同主题中运行时,您才能在ThreadLocal<T>的帮助下实现这一目标

创建以下类:

public final class YourContext implements AutoCloseable {

    private static ThreadLocal<YourContext> instance = new ThreadLocal<>();

    private HttpServletRequest request;
    private HttpServletResponse response;

    private YourContext(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }

    public static YourContext create(HttpServletRequest request, HttpServletResponse response) {
        YourContext context = new YourContext(request, response);
        instance.set(context);
        return context;
    }

    public static YourContext getCurrentInstance() {
        return instance.get();
    }

    @Override    
    public void close() {
        instance.remove();
    }

    public HttpServletRequest getRequest() {
        return request;
    }

    public HttpSession getSession() {
        return request.getSession();
    }

    public ServletContext getServletContext() {
        return request.getServletContext();
    }

    // ... (add if necessary more methods here which return/delegate the request/response).    
}

实施javax.servlet.Filter,其在doFilter()方法中执行以下操作,并映射到感兴趣的url-pattern,例如/*或前控制器servlet的servlet-name

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    try (YourContext context = YourContext.create(request, response)) {
        chain.doFilter(request, response);
    }
}

请注意try-with-resources语句的重要性。它保证在过滤器完成其工作后将调用YourContext#close()并清除ThreadLocal资源。否则,线程在为另一个HTTP请求回收时仍会包含它。

以下是您在POJO中使用它的方法:

YourContext context = YourContext.getCurrentInstance();
HttpSession session = context.getSession();

这一切基本上也是普通MVC框架的Context对象如何工作,如JSF的FacesContext和Wicket中的那个。

说,你看过CDI了吗?也许更容易制作CDI管理的工件,这样你就可以相互@Inject

答案 1 :(得分:3)

是的,有。

如果您使用的是Web框架,例如Wicket,通常有办法获取当前的HttpSession。从那里,你可以获得Spring ApplicationContext,如果你有,你可以从中获得Spring Beans。这适用于任何位置,因为我们只使用静态实用程序方法。

示例代码:

import org.apache.wicket.protocol.http.WebApplication;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.context.WebApplicationContext;

ServletContext sc = WebApplication.getServletContext();
WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(sc);

Object bean = wac.getBean("myBeanId");

但请注意,Spring Filter和Wicket Filter必须就位并处理当前请求,否则实用程序方法将无效。

如果你不是指Spring Beans,那么你必须自己将它们存储在HTTP Session中。如果您没有Web框架,您可能希望执行 rfeak 建议并实现您自己的ThreadLocal。

答案 2 :(得分:2)

Pojo是一个普通的旧Java对象。 POJOS与会话无关。

https会话在请求对象上可用。

看看这个

http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.6/api/index.html

具体是HttpServletRequest接口和getSession()方法。

对于问题的'bean'部分。 bean是一个符合3个标准的java类。

  1. 没有arg构造函数
  2. 用于访问私有字段的setter和getter
  3. 实现可序列化。
  4. 如果遵循这些约定,POJO就是一个bean。

答案 3 :(得分:2)

假设您指的是Servlet编程....

没有直接的方式从POJO到会话。您需要从HttpServletRequest对象获取Session。

我见过有两种流行的解决方案可以解决这个问题。

第一个选项是创建包含Session的某种上下文对象。然后将此上下文传递到您的业务层,以便您的POJO可以在需要时获取此信息。

第二个选项是利用ThreadLocal存储。通常,会话由过滤器或拦截器放置在ThreadLocal存储上。然后系统中的任何对象都可以从线程中获取它。这种模式出现在许多Web框架中,如Spring和Struts。