有没有办法从POJO中检索会话?或者最终从POJO中检索bean。
澄清:
基本上我是从servlet创建一个bean,我需要从Web容器外部(从POJO)访问该bean的属性。我无法将请求传递给pojo;并且需要请求来检索会话。
更具体地说,我有一个Web应用程序,它使用Cactus框架从Web界面运行JUnit测试。但是,调用JUnit测试运行器的servlet是在jar中编译的;我添加了额外的下拉菜单来更改JUnit测试将从中读取的设置以在不同环境(WLI集群)之间切换,因此,如果已经编译了运行器servlet,我无法修改它以处理来自多个环境的额外参数。我已经尝试过写入.dat文件的持久化方法,JUnit测试将通过Reader类读取该文件;我也尝试过最终无法通过JUnit测试访问的bean方法。
答案 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类。
如果遵循这些约定,POJO就是一个bean。
答案 3 :(得分:2)
假设您指的是Servlet编程....
没有直接的方式从POJO到会话。您需要从HttpServletRequest对象获取Session。
我见过有两种流行的解决方案可以解决这个问题。
第一个选项是创建包含Session的某种上下文对象。然后将此上下文传递到您的业务层,以便您的POJO可以在需要时获取此信息。
第二个选项是利用ThreadLocal存储。通常,会话由过滤器或拦截器放置在ThreadLocal存储上。然后系统中的任何对象都可以从线程中获取它。这种模式出现在许多Web框架中,如Spring和Struts。