如何从我的 servlet 中获取 org.eclipse.jetty.server.Request
How do I get the org.eclipse.jetty.server.Request from within my servlet
考虑这段代码。这是一项正在进行的工作,但目标是
获得可用于创建全双工的 NIO 通道
RubyIO 实例 (org.jruby.RubyIO),可由 NIO 选择器选择。
但首先我想要一个 NIO 通道 ...
// This call returns a `javax.servlet.ServletRequest` but the underlying
// instance was created by Jetty - it seems to me - and is actually an
// `org.eclipse.jetty.server.Request`
ServletRequest srv_req = this.http_servlet_request_wrapper.getRequest();
Request req;
ClassLoader cl1 = Request.class.getClassLoader();
ClassLoader cl2 = srv_req.getClass().getClassLoader();
System.out.println("DBG: cl1: " + cl1.toString());
// => DBG: cl1: WebAppClassLoader{66233253}@3f2a3a5
System.out.println("DBG: cl2: " + cl2.toString());
// => DBG: cl2: java.net.URLClassLoader@63947c6b
if (srv_req instanceof Request) {
System.out.println("DBG: srv_req IS REQUEST");
req = (Request)srv_req;
System.out.println("DBG: req class: " + req.getClass().getName());
} else {
System.out.println("DBG: srv_req IS NOT REQUEST");
System.out.println("DBG: srv_req class: " + srv_req.getClass().getName());
throw new Exception("<expletive deleted>!");
}
HttpChannel http_channel = req.getHttpChannel();
EndPoint end_point = http_channel.getEndPoint();
控制台输出什么...
DBG: cl1: WebAppClassLoader{66233253}@3f2a3a5
DBG: cl2: java.net.URLClassLoader@63947c6b
DBG: srv_req IS NOT REQUEST
DBG: srv_req class: org.eclipse.jetty.server.Request
终于抛出了异常。
所以 instanceof
似乎是在说 srv_req
不是
Reuest
因为 classloader 不一样。 srv_req
的class
不过是 org.eclipse.jetty.server.Request
。但是在servlet中我不能
就这样对待它,我不能施放它。
我读过https://www.eclipse.org/jetty/documentation/current/jetty-classloading.html
但我仍然不清楚如何访问 srv_req
作为
org.eclipse.jetty.server.Request
个实例。
我怀疑我不应该能够从 servlet 执行此操作,但是它
可以问问。
我可以访问从我的返回的 javax.servlet.ServletRequest
HttpServletRequestWrapper
对象,就其外观而言,一个
org.eclispe.jetty.server.Request
实例?
或者,我可以从我可以访问的内容创建一个全双工 NIO 通道吗
在 servlet 中?
首先,要从 javax.servlet.HttpServletRequest
获取 org.eclipse.jetty.server.Request
,只需使用 ...
Request baseRequest = Request.getBaseRequest(httpServletRequest);
但这不会让你走得太远。
org.eclipse.jetty.server.HttpChannel
and org.eclipse.jetty.io.EndPoint
没有向应用程序公开 NIO 接口或行为。
它们是内部的 类,通过单个接口实现 HTTP 规范行为,以处理诸如...
- 传输编码
- 分块
- 内容编码
- Gzip
- 多部分编码
- 等..
而这正是 HTTP/1.1 给 table 带来的,如果你开始使用 HTTP/2 事情会变得更加复杂(物理连接控制许多虚拟流) .
但是,如果您不想使用或不关心 HTTP 怎么办?
您可以升级连接并使用您自己的 Connection
object.
从 HTTP 下退出
jettyEndPoint.setConnection(myConnection);
jettyEndPoint.upgrade(myConnection);
不要忘记实施 Connection.UpgradeTo
以从之前的连接中获取挥之不去的(未处理的)字节。
但这仍然不能让你得到 NIO,因为 EndPoint
并没有从 Jetty 中放弃,它仍在进行选择器管理和低级协议行为。 (例如来自 HTTP/2 的流)
好的,回到 HTTP,您还有哪些选择?
不会公开或让您管理 NIO 选择器。
您必须伪造 jruby 的选择器。
如果您想坚持使用 HTTP,请使用 servlet 规范 Async I/O 行为作为您的 Jetty 端 API 层。
如果您不想坚持使用 HTTP,请将连接从 HTTP 升级,请务必先在 HTTP 对话中使用适当的 headers(例如:Connection: upgrade
).
考虑这段代码。这是一项正在进行的工作,但目标是 获得可用于创建全双工的 NIO 通道 RubyIO 实例 (org.jruby.RubyIO),可由 NIO 选择器选择。
但首先我想要一个 NIO 通道 ...
// This call returns a `javax.servlet.ServletRequest` but the underlying
// instance was created by Jetty - it seems to me - and is actually an
// `org.eclipse.jetty.server.Request`
ServletRequest srv_req = this.http_servlet_request_wrapper.getRequest();
Request req;
ClassLoader cl1 = Request.class.getClassLoader();
ClassLoader cl2 = srv_req.getClass().getClassLoader();
System.out.println("DBG: cl1: " + cl1.toString());
// => DBG: cl1: WebAppClassLoader{66233253}@3f2a3a5
System.out.println("DBG: cl2: " + cl2.toString());
// => DBG: cl2: java.net.URLClassLoader@63947c6b
if (srv_req instanceof Request) {
System.out.println("DBG: srv_req IS REQUEST");
req = (Request)srv_req;
System.out.println("DBG: req class: " + req.getClass().getName());
} else {
System.out.println("DBG: srv_req IS NOT REQUEST");
System.out.println("DBG: srv_req class: " + srv_req.getClass().getName());
throw new Exception("<expletive deleted>!");
}
HttpChannel http_channel = req.getHttpChannel();
EndPoint end_point = http_channel.getEndPoint();
控制台输出什么...
DBG: cl1: WebAppClassLoader{66233253}@3f2a3a5
DBG: cl2: java.net.URLClassLoader@63947c6b
DBG: srv_req IS NOT REQUEST
DBG: srv_req class: org.eclipse.jetty.server.Request
终于抛出了异常。
所以 instanceof
似乎是在说 srv_req
不是
Reuest
因为 classloader 不一样。 srv_req
的class
不过是 org.eclipse.jetty.server.Request
。但是在servlet中我不能
就这样对待它,我不能施放它。
我读过https://www.eclipse.org/jetty/documentation/current/jetty-classloading.html
但我仍然不清楚如何访问 srv_req
作为
org.eclipse.jetty.server.Request
个实例。
我怀疑我不应该能够从 servlet 执行此操作,但是它 可以问问。
我可以访问从我的返回的 javax.servlet.ServletRequest
HttpServletRequestWrapper
对象,就其外观而言,一个
org.eclispe.jetty.server.Request
实例?
或者,我可以从我可以访问的内容创建一个全双工 NIO 通道吗 在 servlet 中?
首先,要从 javax.servlet.HttpServletRequest
获取 org.eclipse.jetty.server.Request
,只需使用 ...
Request baseRequest = Request.getBaseRequest(httpServletRequest);
但这不会让你走得太远。
org.eclipse.jetty.server.HttpChannel
and org.eclipse.jetty.io.EndPoint
没有向应用程序公开 NIO 接口或行为。
它们是内部的 类,通过单个接口实现 HTTP 规范行为,以处理诸如...
- 传输编码
- 分块
- 内容编码
- Gzip
- 多部分编码
- 等..
而这正是 HTTP/1.1 给 table 带来的,如果你开始使用 HTTP/2 事情会变得更加复杂(物理连接控制许多虚拟流) .
但是,如果您不想使用或不关心 HTTP 怎么办?
您可以升级连接并使用您自己的 Connection
object.
jettyEndPoint.setConnection(myConnection);
jettyEndPoint.upgrade(myConnection);
不要忘记实施 Connection.UpgradeTo
以从之前的连接中获取挥之不去的(未处理的)字节。
但这仍然不能让你得到 NIO,因为 EndPoint
并没有从 Jetty 中放弃,它仍在进行选择器管理和低级协议行为。 (例如来自 HTTP/2 的流)
好的,回到 HTTP,您还有哪些选择?
不会公开或让您管理 NIO 选择器。
您必须伪造 jruby 的选择器。
如果您想坚持使用 HTTP,请使用 servlet 规范 Async I/O 行为作为您的 Jetty 端 API 层。
如果您不想坚持使用 HTTP,请将连接从 HTTP 升级,请务必先在 HTTP 对话中使用适当的 headers(例如:Connection: upgrade
).