簡體   English   中英

如何從我的 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因為類加載器是不一樣的。 不過, srv_req的類是org.eclipse.jetty.server.Request 但是在 servlet 中,我不能這樣對待它,也不能投射它。

我已經閱讀了https://www.eclipse.org/jetty/documentation/current/jetty-classloading.html但我仍然不清楚如何將srv_req作為org.eclipse.jetty.server.Request實例訪問.

我懷疑我不應該能夠從 servlet 中做到這一點,但是提出這個問題並沒有什么壞處。

我可以訪問從我的HttpServletRequestWrapper對象返回的javax.servlet.ServletRequest ,它看起來是一個org.eclispe.jetty.server.Request實例嗎?

或者,我可以從我可以在 servlet 中訪問的內容創建一個全雙工 NIO 通道嗎?

首先,要從javax.servlet.HttpServletRequest獲取org.eclipse.jetty.server.Request只需使用 ...

Request baseRequest = Request.getBaseRequest(httpServletRequest);

但這不會讓你走得很遠。

org.eclipse.jetty.server.HttpChannelorg.eclipse.jetty.io.EndPoint不會將 NIO 接口或行為暴露給應用程序。

它們是通過單個接口實現 HTTP 規范行為的內部類,以處理諸如...

  • 傳輸編碼
  • 分塊
  • 內容編碼
  • 壓縮包
  • 多部分編碼
  • 等等 ..

這正是 HTTP/1.1 帶來的好處,如果您開始使用 HTTP/2,事情會變得更加復雜(通過物理連接控制許多虛擬流)。

但是,如果您不想使用或不關心 HTTP,該怎么辦?

您可以使用自己的Connection對象升級連接並從 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 對話中使用適當的標頭(例如: Connection: upgrade )這么說。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM