2010-11-12 78 views
10

以下是可能使用Python:自舉一個Web服務器在斯卡拉

$ apt-get install python 
$ easy_install Flask 
$ cat > hello.py 
from flask import Flask 
app = Flask(__name__) 

@app.route("/") 
def hello(): 
    return "Hello World!" 

if __name__ == "__main__": 
    app.run() 
$ python hello.py 

4命令和7號線的代碼來獲得一個Web服務器上運行是非常可觀的確實。

什麼是Scala等價物?

+3

你的意思是在那裏apt-get的存在系統上的4個命令,easy_install的捆綁Python和使用sh的外殼。你是否也假設有root權限? – huynhjl 2010-11-12 16:25:31

+8

是的,我還假設系統有CPU,RAM,存儲器,已安裝的操作系統,鍵盤和顯示器;) – Matthew 2010-11-12 17:10:04

+3

這是一個嚴重的問題,或者只是試圖展示Python + Flask有多酷?在需要輸入15個命令而不是4個命令之前,需要多少次設置Web服務器纔是工作中的限速步驟?我承認這是非常酷的,但是我唯一可以從需要的地方開始思考的應用程序,而不是僅僅有趣的是將漏洞嵌入到一個小緩衝區中,該緩衝區將目標機器轉換爲Web服務器。 – 2010-11-12 21:45:24

回答

4

那麼,有Scalatra,其目的是在功能和易用性方面類似於Ruby的Sinatra。

10

您可能會發現Unfiltered值得一看。

+0

鏈接已損壞。 – Meglio 2012-02-22 03:41:26

+0

我更新了鏈接。 – 2012-02-23 00:53:45

+0

鏈接被再次破壞... – 2017-08-24 13:11:36

10

我知道Max alread mentioned,但我忍不住指出Scalatra's 6行的Hello World:

import org.scalatra._ 

class ScalatraExample extends ScalatraServlet { 
    get("/") { 
    <h1>Hello, world!</h1> 
    } 
} 

不管怎樣,看看可用Scala web frameworks

編輯

還有的是如何輕鬆搞定工裝準備,特別是關於提起一些討論。所以,這是Ubuntu上的一個會話。我大部分時間都在試圖弄清楚Sun的Java在包管理器中的用途。無論如何,一旦被安裝的Java,這是它如何去,與所有的消息省略的,所以可以看到我其實是有鍵入:

[email protected]:~$ wget -q -O bin/sbt-launch.jar http://simple-build-tool.googlecode.com/files/sbt-launch-0.7.4.jar 
[email protected]:~$ echo 'java -Xmx512M -jar `dirname $0`/sbt-launch.jar "[email protected]"' > bin/sbt 
[email protected]:~$ chmod u+x bin/sbt 
[email protected]:~$ mkdir app 
[email protected]:~$ cd app 
[email protected]:~/app$ sbt 
Project does not exist, create new project? (y/N/s) s 
> *lifty is org.lifty lifty 1.4 
> lifty create project-blank sample 2.1 
> reload 
> update 
> jetty-run 

還有,Web服務器正在運行。當然,你必須事先了解SBT和Lifty,甚至知道你會用它們來運行Scala Lift程序,但另一方面,我從來沒有聽說過Flask,所以我肯定會花錢有更多的時間試圖弄清楚如何獲得一個使用Python的Web服務器應用程序,而不是我獲得一個電梯服務器應用程序。

我也沒有得到它的第一次嘗試正確的 - 我試過爲斯卡拉2.8.1(上面使用默認的2.7.7版本,但2.8.0也可以),只是爲了找出目前還沒有可用於該版本Scala的Lift版本。另一方面,我已經安裝了lifty,並且爲了顯示安裝它的命令而卸載它。

我的確希望有一個用於SBT的Debian/Ubuntu軟件包 - 它只是一個小小的shell腳本和一個jar文件,畢竟它需要下載Scala,Lift等等,並且無論您需要什麼版本。

這是一個與Python和Ruby不同的模型,其中語言帶有一個處理大多數事情的包管理器。

+0

謝謝,6行Scala很棒!有沒有辦法讓Scala和Scalatra安裝,只用幾條命令啓動服務器? – Matthew 2010-11-12 17:11:24

+0

請參閱「快速入門Scalatra」:http://blog.everythings-beta.com/?p=430。這掩蓋了安裝sbt的步驟,但這並不困難。當然,爲它提供一個debian/ubuntu包會是一個優勢。 – 2010-11-13 16:43:01

+0

@Matthew當然。在Scalatra的網頁上快速入門非常簡短。你只需要安裝git和sbt。我希望他們能夠實現像Lifty這樣的處理器(https://github.com/Lifty/Lifty),這樣sbt就足夠了。 – 2010-11-13 16:44:13

1

你可以使用一個嵌入式Jetty服務器:

/* 
* Required Libs: Jetty, Servlet API 
* 
* Compile: 
* scalac -cp jetty-6.1.14.jar:jetty-util-6.1.14.jar:servlet-api-2.5-6.1.14.jar WebServer.scala 
* 
* Run: 
* scala -cp .:jetty-6.1.14.jar:jetty-util-6.1.14.jar:servlet-api-2.5-6.1.14.jar WebServer 
*/ 
import org.mortbay.jetty.Server 
import org.mortbay.jetty.servlet.Context 
import javax.servlet.http.{HttpServlet, 
         HttpServletRequest, 
         HttpServletResponse} 

class HelloServlet extends HttpServlet { 
    override def doGet(req : HttpServletRequest, resp : HttpServletResponse) = 
    resp.getWriter().print("Hello There!") 
} 

object WebServer { 
    def main(args: Array[String]) { 
    val server = new Server(8080) 
    val root = new Context(server, "/", Context.SESSIONS) 
    root.addServlet(classOf[HelloServlet], "/*") 
    server.start() 

    println("Point your browser to http://localhost:8080/") 
    println("Type [CTRL]+[C] to quit!") 

    Thread.sleep(Long.MaxValue) 
    } 
} 

如果你的LOC比較對象,您可以使用嵌入太陽JDK的HTTP服務器。另一種解決方案可以是使用javax.xml.ws.Endpoint和Provider API。

2

該解決方案採用了JAX-WS端點:

import java.io._ 
import javax.xml.ws._ 
import javax.xml.ws.http._ 
import javax.xml.transform._ 
import javax.xml.transform.stream._ 

@WebServiceProvider 
@ServiceMode(value=Service.Mode.PAYLOAD) 
class P extends Provider[Source] { 
    def invoke(source: Source) = new StreamSource(new StringReader("<p>Hello There!</p>")); 
} 

val address = "http://127.0.0.1:8080/" 
Endpoint.create(HTTPBinding.HTTP_BINDING, new P()).publish(address) 

println("Service running at "+address) 
println("Type [CTRL]+[C] to quit!") 

Thread.sleep(Long.MaxValue) 

你可以把它複製到文件網絡服務器。斯卡拉並通過鍵入簡單地運行它:

scala WebServer.scala 
11

它使用的是內置在JDK6的HttpServer類。隨意提出改進建議,我是斯卡拉新手。

package org.test.simplehttpserver 

import java.net.InetSocketAddress 
import com.sun.net.httpserver.{HttpExchange, HttpHandler, HttpServer} 
import collection.mutable.HashMap 

abstract class SimpleHttpServerBase(val socketAddress: String = "127.0.0.1", 
            val port: Int = 8080, 
            val backlog: Int = 0) extends HttpHandler { 
    private val address = new InetSocketAddress(socketAddress, port) 
    private val server = HttpServer.create(address, backlog) 
    server.createContext("/", this) 

    def redirect(url: String) = 
    <html> 
     <head> 
      <meta http-equiv="Refresh" content={"0," + url}/> 
     </head> 
     <body> 
     You are being redirected to: 
     <a href={url}> 
      {url} 
     </a> 
     </body> 
    </html> 

    def respond(exchange: HttpExchange, code: Int = 200, body: String = "") { 
    val bytes = body.getBytes 
    exchange.sendResponseHeaders(code, bytes.size) 
    exchange.getResponseBody.write(bytes) 
    exchange.getResponseBody.write("\r\n\r\n".getBytes) 
    exchange.getResponseBody.close() 
    exchange.close() 
    } 

    def start() = server.start() 

    def stop(delay: Int = 1) = server.stop(delay) 
} 

abstract class SimpleHttpServer extends SimpleHttpServerBase { 
    private val mappings = new HashMap[String,() => Any] 

    def get(path: String)(action: => Any) = mappings += path -> (() => action) 

    def handle(exchange: HttpExchange) = mappings.get(exchange.getRequestURI.getPath) match { 
    case None => respond(exchange, 404) 
    case Some(action) => try { 
     respond(exchange, 200, action().toString) 
    } catch { 
     case ex: Exception => respond(exchange, 500, ex.toString) 
    } 
    } 
} 

class HelloApp extends SimpleHttpServer { 
    var count = 0 

    get("/") { 
    "There's nothing here" 
    } 

    get("/hello") { 
    "Hello, world!" 
    } 

    get("/markup") { 
    <html> 
     <head> 
     <title>Test Title</title> 
     </head> 
     <body> 
     Test Body 
     </body> 
    </html> 
    } 

    def countPage = <html> 
    <head> 
     <title>Test Title</title> 
    </head> 
    <body> 
     Count: 
     {count}<a href="/increaseCount">++</a> 
     <a href="/decreaseCount">--</a> 
     <a href="/resetCount">Reset</a> 
    </body> 
    </html> 

    get("/count") { 
    countPage 
    } 

    get("/resetCount") { 
    count = 0 
    redirect("/count") 
    } 

    get("/increaseCount") { 
    count = count + 1 
    redirect("/count") 
    } 

    get("/decreaseCount") { 
    count = count - 1 
    redirect("/count") 
    } 

    get("/error") { 
    throw new RuntimeException("Bad bad error occurred") 
    } 
} 

object Main { 

    def main(args: Array[String]) { 
    val server = new HelloApp() 
    server.start() 
    } 
} 
+0

有沒有什麼辦法指定內容類型來響應,例如,用圖像? – Tutankhamen 2014-08-29 21:17:38

+1

使用對exchange.sendResponseHeaders()的調用來設置內容類型。 – Tommy 2014-09-06 12:23:25

+0

謝謝,已經做成:) – Tutankhamen 2014-09-08 06:19:01

1

Scala的當量是在6個命令:

$ curl https://raw.github.com/n8han/conscript/master/setup.sh | sh 
$ ~/bin/cs n8han/giter8 
$ ~/bin/g8 scalatra/scalatra-sbt --name=scalatra-example 
$ cd scalatra-example 
$ wget http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-tools.sbt/sbt-launch/0.11.0/sbt-launch.jar 
$ java -Xmx512M -jar sbt-launch.jar ~jetty-run 

使用播放,

step #1 download Play, then 
$ play install scala 
$ play new myproject --with scala 
$ play run myproject 
0

David Winslow提到的,Unfiltered用法代碼段

INFO:用於Apache Spark簡單API功能用斯卡拉書寫的字數統計範例唱未過濾。

object SimplePlan extends Plan { 
    def intent = { 
    case req @ GET(Path("/get")) => { 
    Ok ~> ResponseString(WordCount.count("Test #1: Test the Default word count program").mkString("\n")); 
    } 

    case req @ POST(Path("/get_custom")) => { 
    val custom_string = Body.string(req) 
    Ok ~> ResponseString(WordCount.count(custom_string).mkString("\n")) 
    } 
} 
} 

object SimpleServer extends App { 
    val bindingIP = SocketPortBinding(host = "localhost", port = 8080) 
    unfiltered.jetty.Server.portBinding(bindingIP).plan(SimplePlan).run() 
} 

完整的例子是here