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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值