背景
我有一个java.lang.Thread,它可以在特定时间在Web服务器(JBoss或WebSphere)上的应用程序内部运行,而无需人工干预,而它所做的只是发送一封电子邮件。电子邮件的内容类似于我们用作Web视图显示的JSP(/jsp/Report.jsp)的内容。
我不想复制相同的工作或将JSP更改为两者都可以访问的静态类,我想从线程内部抓取JSP运行的内容并将其放置在电子邮件中以进行发送。
我从“ web.xml”中使用侦听器获得了当前的ServletContext。我当前在线程中的JSP调用类似于:
servletContext.getRequestDispatcher("/jsp/Report.jsp").include(dummyRequest, dummyResponse);
请求/响应类基本上是这样创建的:
final HttpServletRequest dummyRequest = new HttpServletRequest() { .... }
final HttpServletResponse dummyResponse = new HttpServletResponse() { .... }
我打算通过dummyRequest将附加属性(类)设置为JSP,例如“ dummyRequest.setAttribute(name,value)”。
每当我进行调用时,都会得到异常,因为虚拟请求/响应是HttpServletResponse / HttpServletRequest的匿名类。
WebSphere Application Server 7.0.0.17:
java.lang.RuntimeException: SRV.8.2: RequestWrapper objects must extend ServletRequestWrapper or HttpServletRequestWrapper
JBoss AS 7.1.1:
java.lang.ClassCastException: my.test.thread$1$2 incompatible with javax.servlet.ServletRequestWrapper
如果没有原始请求/响应,就无法创建HttpServletResponseWrapper / HttpServletRequestWrapper。
题
所以...。是否可以使用上下文从Web应用程序上的线程内部获取JSP的内容?
如果是这样,我该怎么做呢?
更新资料
这是我用于测试的代码:link
研究
现在,我开始研究服务器的源代码,以尝试了解发生了什么。
老板
在ApplicationDispatcher中,“ forward”不执行任何操作,因为在请求中未设置“ DISPATCHER_TYPE”属性(在processRequest方法中可见)。 “包含”不是必需的。
我遇到的有关不兼容类型的“问题”是在“ ApplicationFilterFactory.createFilterChain”内部。 Request对象不是要查找的正确类,在JBoss的情况下,它是“ org.apache.catalina.connector.Request”或“ org.apache.catalina.connector.RequestFacade”。除非请求与这些类型之一匹配,否则它将根本不会继续。
因此,当我使用以下请求时:
final HttpServletRequest dummyRequest = new org.apache.catalina.connector.RequestFacade(new org.apache.catalina.connector.Request() { ... });
它成功运行并从线程内部返回JSP的结果。
网络圈
我无法在Websphere上产生相同的结果。
Websphere需要一个“ com.ibm.ws.webcontainer.srt.SRTConnectionContextImpl”实例,然后将ServletContext操纵为其原始类“ com.ibm.wsspi.webcontainer.facade.ServletContextFacade”,但是随后我陷入了“访问” $ 200“ com.ibm.ws.webcontainer.srt.SRTServletRequest $ SRTServletRequestHelper”中的空指针异常,这似乎使我以某种方式破坏了Java。
java.lang.NullPointerException at com.ibm.ws.webcontainer.srt.SRTServletRequest$SRTServletRequestHelper.access$200(SRTServletRequest.java:2629)
这是我当前的代码:
SRTConnectionContext n = new SRTConnectionContextImpl();
(((SRTServletRequest) (n.getRequest())).getRequestContext())
.setCurrWebAppBoundary((WebApp) ((ServletContextFacade) context)
.getIServletContext());
servletContext.getRequestDispatcher("/jsp/Report.jsp").include(n.getRequest(), n.getResponse());
结束
希望有人可以找到在Websphere上完成此任务的方法。
从源代码的角度来看,除非缺少我的辅助方法,否则如果没有服务器自己的特定类文件来执行请求,就无法运行包含/转发。甚至请求包装器都被包装到其基类中,这就是为什么我总是在有包装器和无包装器的情况下都得到Class Cast Exception的原因。
如果没有更干净的服务器,而不是特定于服务器类的服务器,这种方法是从线程内部获取JSP结果的,那么这可能是我最初的问题的答案,无论它看起来有多混乱。
最佳答案
因为虚拟请求/响应是的匿名类
HttpServletResponse / HttpServletRequest。
不,您会收到classcast异常b / c,它们是不同的容器,需要包装器。您的代码正在提供请求/响应。
对我们来说还不是很清楚,您实际上在哪里调用以创建虚拟HttpServletRequest / Response ..看起来就像从您调用的位置...您实际上需要实例化ServletRequestWrapper / responseWapper对象,如果您有一个对象,请对其设置请求处理并使用它。
也许这可以帮助
http://hc.apache.org/从jsp / response中读取html并从中创建电子邮件。