Scala語言中的Scala Servlet
為了讓一門語言適用于 “現實”,并且使其 “輝煌起來”,該語言必須能夠服務于現實環境和應用程序。在這一期的 面向 Java 開發人員的 Scala 指南 系列中,Ted Neward 將介紹 Scala 在現實環境中的使用,即解釋 Scala 如何與核心 Servlet API 交互,甚至可能會對其進行一些改正。
Scala 顯然是一門有趣的語言,很適合體現語言理論和創新方面的新思想,但最終它要用在 “現實” 環境中,它必須能滿足開發人員的某些需求并在 “現實” 環境中有一定的實用性。
了解 Scala語言的一些核心功能之后,就能認識到 Scala語言的一些靈活性,并能放心使用 Scala 創建 DSL.現在我們進入實際應用程序使用的環境,看看 Scala 如何適應環境。在本系列的新階段中,我們將首先討論大部分 Java? 應用程序的核心:Servlet API.
Servlet 回顧
回憶一下 Servlet 101 課程和教程,servlet 環境的核心實際上就是通過一個套接字(通常是端口 80)使用 HTTP 協議的客戶機-服務器交換。客戶機可以是任何 “用戶-代理”(由 HTTP 規范定義),服務器是一個 servlet 容器。servlet 容器在我編寫的一個類上查找、加載和執行方法,該類最終必須實現 javax.servlet.Servlet 接口。
通常,實際的 Java 開發人員不會編寫直接實現接口的類。因為最初的 servlet 規范是用于為 HTTP 之外的其他協議提供一個通用 API,所以 servlet 命名空間被分為了兩部分:
一個 “通用” 包(javax.servlet)
一個特定于 HTTP 的包(javax.servlet.http)
這樣,將在一個稱為 javax.servlet.GenericServlet 的抽象基類的通用包中實現一些基本的功能;然后在派生類 javax.servlet.http.HttpServlet 中實現其他特定于 HTTP 的功能,該類通常用作 servlet 實際 “內容” 的基類。HttpServlet 提供了一個 Servlet 的完整實現,將 GET 請求委托給一個將要被覆蓋的 doGet 方法,將 POST 請求委托給一個將要被覆蓋的 doPut 方法,依此類推。
Hello, Scala 與 Hello, Servlet
顯然,任何人編寫的第一個 servlet 都是普遍的 “Hello, World” servlet;Scala 的第一個 servlet 示例也是如此。回憶一下許多年之前介紹的 servlet 教程,當時基本的 Java “Hello, World” servlet 只是輸出清單 1 所示的 HTML 響應:
清單 1. 預期的 HTML 響應
- <HTML>
- <HEAD><TITLE>Hello, Scala!</TITLE></HEAD>
- <BODY>Hello, Scala! This is a servlet.</BODY>
- </HTML>
用 Scala 編寫一個簡單的 servlet 來實現這個操作非常簡單,而且這個 servlet 與其相應的 Java 形式幾乎一樣,如清單 2 所示:
清單 2. Scala Servlet!
- import javax.servlet.http.{HttpServlet,
- HttpServletRequest => HSReq, HttpServletResponse => HSResp}
- class HelloScalaServlet extends HttpServlet
- {
- override def doGet(req : HSReq, resp : HSResp) =
- resp.getWriter().print("<HTML>" +
- "<HEAD><TITLE>Hello, Scala!</TITLE></HEAD>" +
- "<BODY>Hello, Scala! This is a servlet.</BODY>" +
- "</HTML>")
- }
注意,我使用了一些適當的導入別名來縮短請求的類型名稱和相應類型;除此之外,這個 servlet 幾乎與其 Java servlet 形式一樣。編譯時請記得在 servlet-api.jar(通常隨 servlet 容器一起發布;在 Tomcat 6.0 發行版中,它隱藏在 lib 子目錄中)中包含一個引用,否則將找不到 servlet API 類型。
這還準備得不夠充分;根據 servlet 規范,它必須使用一個 web.xml 部署描述符部署到 Web 應用程序目錄中(或一個 .war 文件中),該描述符描述 servlet 應該與哪個 URL 結合。對于這樣一個簡單的例子,使用一個相當簡單的 URL 來配合它最容易,如清單 3 所示:
清單 3. 部署描述符 web.xml
- <!DOCTYPE web-app
- PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd">
- <web-app>
- <servlet>
- <servlet-name>helloWorld</servlet-name>
- <servlet-class>HelloScalaServlet</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>helloWorld</servlet-name>
- <url-pattern>/sayHello</url-pattern>
- </servlet-mapping>
- </web-app>
從這里開始,我假設讀者會在必要時調整/修改部署描述符,因為這跟 Scala 沒有關系。
當然,格式良好的 HTML 與格式良好的 XML 非常相似;鑒于這一點,Scala 對 XML 字面值的支持使編寫這個 servlet 簡單得多(參閱 參考資料 中的 “Scala 和 XML” 一文)。Scala 不是在傳遞給 HttpServletResponse 的 String 中直接嵌入消息,它可以分離邏輯和表示形式(非常簡單),方法是利用此支持將消息放在 XML 實例中,然后再傳遞回去:
清單 4. Hello, Scala Servlet!
- import javax.servlet.http.{HttpServlet,
- HttpServletRequest => HSReq, HttpServletResponse => HSResp}
- class HelloScalaServlet extends HttpServlet
- {
- def message =
- <HTML>
- <HEAD><TITLE>Hello, Scala!</TITLE></HEAD>
- <BODY>Hello, Scala! This is a servlet.</BODY>
- </HTML>
- override def doGet(req : HSReq, resp : HSResp) =
- resp.getWriter().print(message)
- }
Scala 的內聯表達式求值工具使用 XML 字面值,這意味著能夠輕松地使 servlet 更有趣。例如,將當前日期添加到消息中與將 Calendar 表達式添加到 XML 中一樣簡單,不過增加了幾行 { Text(java.util.Calendar.getInstance()。getTime()。toString() ) }.這似乎顯得有點冗長,如清單 5 所示:
清單 5. Hello, timed Scala Servlet!
- import javax.servlet.http.{HttpServlet,
- HttpServletRequest => HSReq, HttpServletResponse => HSResp}
- class HelloScalaServlet extends HttpServlet
- {
- def message =
- <HTML>
- <HEAD><TITLE>Hello, Scala!</TITLE></HEAD>
- <BODY>Hello, Scala! It's now { currentDate }</BODY>
- </HTML>
- def currentDate = java.util.Calendar.getInstance().getTime()
- override def doGet(req : HSReq, resp : HSResp) =
- resp.getWriter().print(message)
- }
實際上,Scala 編譯器與 XML 對象消息一起整合到一個 scala.xml.Node 中,然后在將它傳遞給響應的 Writer 的 print 方法時將其轉換為一個 String.
不要小看這一點 — 表達形式從邏輯中分離出來完全在一個類內部進行。這條 XML 消息將進行編譯時檢查,以確保語法正確和格式良好,并獲得一些標準 servlet(或 JSP)不具備的好處。由于 Scala 可以進行類型推斷,因此可以省略有關 message 和 currentDate 的實際類型消息,使得這就像動態語言 Groovy/Grails 一樣。初次使用效果不錯。以上是Scala語言中的Scala Servlet一個小小的介紹,希望對大家有用。
【編輯推薦】