2013年1月2日星期三
How Tomcat Works(Scala语言) 01 一个简单的Web服务器
1 简介
此文算是《How Tomcat Works》的Scala代码解析版。主要从代码角度来分析Tomcat的结构。使用Scala来进行说明。 采用简单说明+代码注释的方式来描述,代码也尽量简单化,做到以最少的文字来进行表述。
2 一个简单的Web服务器
一个静态服务器,根据请求,返回请求的静态文件内容
三个类HttpServer,Response,Request
Request类表示一个请求,根据HTTP协议的请求信息,获取到请求的文件
Response类表示一个响应,将找到的文件内容返回,或者返回404信息
HttpServer类为服务器类,不停的等待请求。当获得一个请求,就组装成Resquest来获取文件,并通过Response返回响应
import java.net.ServerSocket
import java.net.InetAddress
import java.io.File
/**
* Created with IntelliJ IDEA.
* User: Ivan
* Date: 12-11-24
* Time: 上午10:41
*/
//静态服务器类
class HttpServer {
var shutdown = false
//核心方法,接受请求,返回响应
def await() {
val port = 8080
val serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"))
while (!shutdown) {
try {
val socket = serverSocket.accept()
val input = socket.getInputStream()
val output = socket.getOutputStream()
//根据请求构造Request,获取资源文件
val request: Request = new Request(input)
request.parse()
//返回资源文件内容
val response: Response = new Response(output)
response.request = request
response.sendStaticResource()
socket.close()
shutdown = request.uri.equals(HttpServer.SHUTDOWN_COMMAND)
} catch {
case e: Exception => e.printStackTrace()
}
}
}
}
object HttpServer {
val WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot"
val SHUTDOWN_COMMAND = "/SHUTDOWN"
def main(args: Array[String]) {
val server = new HttpServer()
server.await()
}
}
import io.Source
import java.io.{IOException, InputStream}
/**
* Created with IntelliJ IDEA.
* User: Ivan
* Date: 12-11-24
* Time: 上午11:36
*/
//请求类,表示一个请求
//主要功能是从输入流中找到请求的文件名
class Request(input: InputStream) {
var uri: String = _
//此处本来使用mkString,但是会死这
//应该是input是流导致的
def parse() {
val lines = Source.fromInputStream(input).getLines()
if (lines.hasNext) {
uri = parseUri(lines.next())
}
}
/**
* 从请求中获得请求的资源链接
* 使用正则表达式组来匹配
* @param requestString
* @return
*/
def parseUri(requestString: String): String = {
val pattern = """[^ ]* *([^ ]*) *[\s\S]*""".r
val pattern(result) = requestString
result
}
}
import io.Source
import java.io.{File, FileInputStream, OutputStream}
/**
* Created with IntelliJ IDEA.
* User: Ivan
* Date: 12-11-24
* Time: 上午11:49
*/
//相应类,表示一个相应
//主要功能是向响应流中写入结果
class Response(output: OutputStream) {
var request: Request = _
//返回访问的文件,或者404
def sendStaticResource() {
val file = new File(HttpServer.WEB_ROOT, request.uri)
var fis: FileInputStream = null
try {
if (file.exists()) {
fis = new FileInputStream(file)
//将文件内容写到响应中
writeToResponse(fis)
} else {
//文件未找到,写入404信息
output.write(Response.FileNotFoundMessage.getBytes())
}
} finally {
if (fis != null)
fis.close()
}
}
//递归读取文件,写入到响应流
def writeToResponse(fis:FileInputStream){
val ch = fis.read(Response.bytes, 0, Response.BUFFER_SIZE)
if(ch != -1){
output.write(Response.bytes, 0, ch)
writeToResponse(fis)
}
}
}
object Response {
val BUFFER_SIZE = 1024
//bytes需要在BUFFER_SIZE后定义,否则大小为0
val bytes = new Array[Byte](Response.BUFFER_SIZE)
val FileNotFoundMessage = """HTTP/1.1 404 File Not Found
|Content-Type: text/html
|Content-Length: 23
|
|<h1>File Not Found</h1>"""
}
Blog URL:http://www.ivanpig.com/blog/?p=485
订阅:
博文评论 (Atom)
没有评论:
发表评论