zoukankan      html  css  js  c++  java
  • 一个由request/response构成的static web server

      声明:资料来自Tomcat剖析一书,该程序是基于java socket的,socket和stream类作为概念背景,现在仅仅是使用其作为基础类,并不关注其本身,关注点在一个服务器的外部功能和体系结构!

    • 代码目录

      

    • HttpServer 
    package simpleserver;
    
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    /**
     * 说明:   server该服务亲自管理request,和response,当前服务只是一个静态资源服务;
     *         request用来解析请求的数据流,抽象成请求对象
     *         response根据请求路径到根目录寻找资源,并输出;该程序的响应只有响应体
     * 
     * 作为一个静态服务器,该程序还需要完善:响应对象本身
     * @author Administrator
     *
     */
    public class HttpServer {
        
        public static final String WEB_ROOT = System.getProperty("user.dir")+File.separator+"webroot";   //指定静态资源目录,请求路径的根目录 
        
        private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
        
        private boolean shutdown = false;
        
        public static void main(String[]args) {
            System.out.println("打印输出web_root"+WEB_ROOT);
            HttpServer serverSocket = new HttpServer();
            serverSocket.await();  //服务启动
        }
        
        public void await() {
            ServerSocket serverSocket = null;   
            int port = 8080;
            try {
                serverSocket = new ServerSocket(port, 1, InetAddress.getByName("192.168.1.102"));//绑定服务的端口号,连接数量,要连接该服务的地址
            }catch(IOException e) {
                e.printStackTrace();
                System.exit(1);
            }
            while(!shutdown) {
                Socket socket = null;
                InputStream input = null;
                OutputStream output = null;
                try {
                    socket = serverSocket.accept();               //1在此监听,阻塞
                    input = socket.getInputStream();  
                    output = socket.getOutputStream();
                    Request request = new Request(input);       //2把数据传递给request,令其解析;请求使用socket的输入流
                    request.parse(); 
                    Response response = new Response(output);   //3响应对象根据已解析的请求路径,寻找资源;响应使用socket的输出流
                    response.setRequest(request);
                    response.sendStaticResource();
                    socket.close();                                //4发回响应后socket关闭;服务还在
                    shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
                }
                catch(Exception e) {
                    e.printStackTrace();
                    continue;
                }
                
            }
            
        }
    }
    View Code
    • Request
    package simpleserver;
    
    import java.io.IOException;
    import java.io.InputStream;
    /**
     * @说明:对socket类的inputStream进行解析后生成诸多属性,隶属于该类
     * @author Administrator
     *
     */
    public class Request {
        private InputStream input;
        private String uri;
    
        public Request(InputStream input) {   
            this.input = input;
        }
    
        public String getUri() {
            return uri;
        }
    
        public void parse() {
            StringBuffer request = new StringBuffer();
            int i;
            byte[]buffer = new  byte[2048];
            try {
                i = input.read(buffer);
            }catch(IOException e) {
                e.printStackTrace();
                i = -1;
            }
            for(int j=0;j<i;j++) {
                request.append((char)buffer[j]);
            }
            System.out.println(request.toString()); 
            uri = parseUri(request.toString());
            System.out.println("截取出来的路径"+uri);
        }
        private String parseUri(String requestString) { //只解析出请求数据中的uri属性
            int index1, index2;
            index1 = requestString.indexOf(' ');
            if(index1 != -1){
                index2 = requestString.indexOf(' ', index1 + 1);
                if(index2 > index1) {
                    return requestString.substring(index1+1, index2);
                }
            }
            return null;
        }
    
    }
    View Code
    • Response
    package simpleserver;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    
    public class Response {
        private static final int BUFFER_SIZE =1024;
        Request request;
        OutputStream output;      
        public Response(OutputStream output) {
            this.output = output;
        }
        public void setRequest(Request request) {
            this.request = request;
        }
        
        
        public void sendStaticResource() throws IOException{
            byte[] bytes = new byte[BUFFER_SIZE];
            FileInputStream fis = null;
            try {
                File file = new File(HttpServer.WEB_ROOT, request.getUri());    //1根目录拼接请求路径
                System.out.println("请求路径"+file.getAbsolutePath());
                if(file.exists()){
                    System.out.println("文件存在");
                    fis = new FileInputStream(file); 
                    int ch = fis.read(bytes, 0, BUFFER_SIZE);
                    while(ch!=-1){
                        output.write(bytes, 0, ch);                             //2.1请求的响应数据写入输出流 
                        ch = fis.read(bytes, 0, BUFFER_SIZE);
                    }
                }
                else {
                    String errorMessage = "HTTP/1.1 404 File Not Found
    "     //2.2响应数据写入输出流
                            + "Content-Type: text/html
    "
                            + "Content-Length: 23
    "
                            + "
    "
                            + "<h1>File Not Found</h1>";
                    output.write(errorMessage.getBytes());
                }
            }catch(Exception e){
                System.out.println(e.toString());
            }finally {
                if(fis!=null){
                    fis.close();
                }
            }
            
        }
    
            
    
    }
    View Code

     代码分析:

      类的关系:HttpServer类与另两个类独立,response类组合了request类

      对象关系:Httpserver传递socket输入流给request构造器,用于创建request对象,并调用其parse方法产生request对象属性值;传递已解析出属性值的request对象和socket输         出流给response;response对象根据request对象的属性(请求路径)去指定跟目录找请求资源,并处理。

      结论:HttpServer的awai主程序管理了整个服务过程,生成请求,生成响应,执行响应处理;具体的响应处理由响应对象完成,负责根据请求路径自动地返回或有或无时的处理       结果!

    很遗憾,当前没有能力以UML等更优雅或更符合业内标准的语言来描述,只能以文字说明,虽然我也很痛恨这种方法,但自己写的总算读来不困难,如果是读别人的,说实话很抵触,尤其是很多国内的书籍都是一大堆文字,个人很鄙视,好在我写来是给自己看的,而且下阶段的目标就是形式化描述。再次强调一下,形式化语言中代码其实是比数学公理化,符号化,逻辑推理更优雅进步的语言,这样的潦草描述,只能说是很个人色彩。

  • 相关阅读:
    移动端rem屏幕设置
    封装ajax库,post请求
    获取浏览器url参数
    身份证验证
    jq封装插件
    页面分享功能,分享好友、朋友圈判断,用share_type做标记 这里用的是jweixin-1.3.2.js
    @RequestParam和@RequestBody区别
    400报错
    IDEA中用Maven构建SSM项目环境入门
    Eclipse搭建Spring开发环境
  • 原文地址:https://www.cnblogs.com/10000miles/p/9211231.html
Copyright © 2011-2022 走看看