通过Java编写一个服务器理解动态Web,静态Web

静态Web

说到Servlet自然就要说到Web,Web分为静态Web和动态Web,之前我一直都傻傻分不清两者的区别,直到用JAVA编写了一个服务器后才明白二者的区别,所谓静态Web,实际上就是指,客户端要请求的资源文件,服务器已经提前把它放在了文件系统(磁盘)上,看下面用Java实现的一个静态Web服务器
public class HTTPService {
    private static HashMap<String,Servlet> servletCache = new HashMap<>();

    public static void init(){
        servletCache.put("HTTPServlet",new HTTPServlet());
    }

    public static void main(String[] args) {
        init();
        int port;
        ServerSocket serversocket;
        port=8080;
        try {
            serversocket = new ServerSocket(port);  //默认服务器套接字ip为本地地址
            System.out.println("服务器正在监听端口:8080");
            while (true) {
                try{
                   Socket socket = serversocket.accept();//会进入阻塞状态,直到客户端与服务器TCP建立
                   System.out.println("建立了与客户端的一个新的tcp连接,客户端地址为" + socket.getInetAddress() + ":" + socket.getPort());
                   service(socket);
            }catch (Exception e){
                    System.out.println("客户端请求资源不存在");
                }
            }
        } catch (Exception e) {
            System.out.println("客户端请求资源不存在");
        }
    }

    public static void service(Socket socket) throws Exception {
        InputStream socketIn = socket.getInputStream();//获得客户端请求信息流
        Thread.sleep(500);  //与客户端TCP请求已建立,还需要等待客户端发送http请求,如果在TCP后立马响应HTTP,socket内容可能为空
        int size = socketIn.available();
        byte[] buffer = new byte[size];
        socketIn.read(buffer);
        String request = new String(buffer);
        int endIndex = request.indexOf("\r\n");
        if (endIndex==-1)
            endIndex = request.length();
        String firstLineOfRequest = request.substring(0,endIndex);
        String[] parts = firstLineOfRequest.split(" ");
        String uri="";
        String contentType="";
        if (parts.length>=2){
            uri = parts[1];
        }
      
     
            //静态web
            if (uri.indexOf("html") != -1)
                contentType = "text/html";
            else if (uri.indexOf("jpg") != -1)
                contentType = "image/jepg";
            else
                contentType = "application/octet-stream";
            String firstLineOfResponse = "HTTP/1.1 200 OK\r\n";  //响应行
            String responseHeader = "Content-Type:" + contentType + "\r\n\r\n";
            // FileInputStream in = new FileInputStream("E:\\IDEA WORKSPACE\\ServiceDemo\\resources\\index.html");
            System.out.println(HttpServer.class.getResource(""));

            InputStream in = HTTPService.class.getResourceAsStream("root/" + uri);
            System.out.println(HTTPService.class.getResource("root/" + uri));
            OutputStream output = socket.getOutputStream();
            output.write(firstLineOfResponse.getBytes());
            output.write(responseHeader.getBytes());
            buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                System.out.println(1);
                output.write(buffer, 0, len);
            }
        
        Thread.sleep(1000);//睡眠1秒,等待客户端接收http响应结果,socket代表两者间的tcp连接,如果立马断开,客户端可能就收不到响应结果了
        socket.close();
    }

}

将事先准备好的index.html文件放在磁盘上,将代码运行起来,此时HTTPServer就作为一个服务开始监听电脑上的8080端口了,打开浏览器,在url地址栏输入localhost:8080/index.html,结果如下:
在这里插入图片描述
在这里插入图片描述
工作原理如下:
在这里插入图片描述

HTTPServer接收到来自客户端的请求后,就会在磁盘上查找客户端请求的资源文件,然后把文件响应给客户端,index.html就事先存放在磁盘上,然后当浏览器请求index.html,HTTPServer就把html文件响应给浏览器,浏览器再解析html文件后,就是我们看到的Hello页面了。

动态Web

网上经常能看见一句话,动态Web就是每个用户看到的东西是不一样的,这句话没错,但是还不太能够帮助我们理解动态Web。那么动态Web到底是什么,动态Web就是指客户端可以与服务器进行交互,并且客户端请求的资源文件,是由服务器动态生成的。举这么一个例子,假设D是一个在某城市居住了很久的人,这一天A向D问路X街怎么走,D经过思考后,告诉了A,此时B又来问路Y街怎么走,对于C来说,简直轻而易举。上述中A,B看作客户端,D是服务器,而问路可以看作客户端向服务器请求的资源文件,去某城市可以看作是客户端与服务器的交互,很明显,A和B得到的响应内容都是不同的,服务器在得到客户端的请求后,执行业务逻辑操作,得出了通往某城市怎么走,然后响应给客户端。
public class HTTPService {
    private static HashMap<String,Servlet> servletCache = new HashMap<>();

    public static void init(){
        servletCache.put("HTTPServlet",new HTTPServlet());
    }

    public static void main(String[] args) {
        init();
        int port;
        ServerSocket serversocket;
        port=8080;
        try {
            serversocket = new ServerSocket(port);  //默认服务器套接字ip为本地地址
            System.out.println("服务器正在监听端口:8080");
            while (true) {
                try{
                   Socket socket = serversocket.accept();//会进入阻塞状态,直到客户端与服务器TCP建立
                   System.out.println("建立了与客户端的一个新的tcp连接,客户端地址为" + socket.getInetAddress() + ":" + socket.getPort());
                   service(socket);
            }catch (Exception e){
                    System.out.println("客户端请求资源不存在");
                }
            }
        } catch (Exception e) {
            System.out.println("客户端请求资源不存在");
        }
    }

    public static void service(Socket socket) throws Exception {
        InputStream socketIn = socket.getInputStream();//获得客户端请求信息流
        Thread.sleep(500);  //与客户端TCP请求已建立,还需要等待客户端发送http请求,如果在TCP后立马响应HTTP,socket内容可能为空
        int size = socketIn.available();
        byte[] buffer = new byte[size];
        socketIn.read(buffer);
        String request = new String(buffer);
        int endIndex = request.indexOf("\r\n");
        if (endIndex==-1)
            endIndex = request.length();
        String firstLineOfRequest = request.substring(0,endIndex);
        String[] parts = firstLineOfRequest.split(" ");
        String uri="";
        String contentType="";
        if (parts.length>=2){
            uri = parts[1];
        }
        System.out.println(uri);
        if(uri.indexOf("servlet")!=-1){   //动态web
            String servletName = "";
            if (uri.indexOf("?")!=-1)
                 servletName = uri.substring(uri.indexOf("servlet/")+8,uri.indexOf("?"));
            else
                 servletName = uri.substring(uri.indexOf("servlet/")+8,uri.length());
            System.out.println(servletName);
            Servlet servlet = servletCache.get(servletName);
            System.out.println(servletCache);
            System.out.println(servlet);
            if (servlet == null)
                throw new Exception();
            servlet.init();
            servlet.service(request,socket.getOutputStream());
        }
        else {
            //静态web
            if (uri.indexOf("html") != -1)
                contentType = "text/html";
            else if (uri.indexOf("jpg") != -1)
                contentType = "image/jepg";
            else
                contentType = "application/octet-stream";
            String firstLineOfResponse = "HTTP/1.1 200 OK\r\n";  //响应行
            String responseHeader = "Content-Type:" + contentType + "\r\n\r\n";
            // FileInputStream in = new FileInputStream("E:\\IDEA WORKSPACE\\ServiceDemo\\resources\\index.html");
            System.out.println(HttpServer.class.getResource(""));

            InputStream in = HTTPService.class.getResourceAsStream("root/" + uri);
            System.out.println(HTTPService.class.getResource("root/" + uri));
            OutputStream output = socket.getOutputStream();
            output.write(firstLineOfResponse.getBytes());
            output.write(responseHeader.getBytes());
            buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                System.out.println(1);
                output.write(buffer, 0, len);
            }
        }
        Thread.sleep(1000);//睡眠1秒,等待客户端接收http响应结果,socket代表两者间的tcp连接,如果立马断开,客户端可能就收不到响应结果了
        socket.close();
    }

}

public class HTTPServlet implements Servlet{
    @Override
    public void init() {

    }

    @Override
    public void service(String request, OutputStream out) throws IOException {
        int endIndex = request.indexOf("/r/n");
        String firstOfRequest = "";
        if (endIndex!=-1)
            firstOfRequest = request.substring(0,endIndex);
        else
            firstOfRequest = request;
        String[] parts = firstOfRequest.split(" ");
        String method = parts[0];
        String uri = parts[1];
        String userName="";
        if (method.equalsIgnoreCase("get")){
            if (uri.indexOf("username=")!=-1){
                String[] params = uri.substring(uri.indexOf("?") + 8, uri.length()).split("&");
                String[] params_parts = params[0].split("=");
                userName = params_parts[1];
            }
        }
        if (method.equalsIgnoreCase("post")){
            if (request.indexOf("\r\n\r\n")!=-1){
                String content = request.substring(request.indexOf("\r\n\r\n"+4,request.length()));
                if (content.indexOf("username=")!=-1){
                    String[] contentParts = content.split("&");
                    userName = (contentParts[0].split("="))[1];
                }
            }
        }

        userName = URLDecoder.decode(userName,"utf-8");
        System.out.println(userName);
        out.write("HTTP/1.1 200 OK\r\n".getBytes());
        out.write("Content-Type:text/html\r\n\r\n".getBytes());
        out.write(("<meta charset=\"UTF-8\"> <h1>Hello,"+userName+"</h1>").getBytes());
    }
}
public interface Servlet {
    public void init();
    public void service(String request, OutputStream out) throws IOException;
}

前面说过,动态Web中服务器在接收到请求后,会执行业务逻辑操作,这个业务逻辑操作其实就是由服务器内的servlet模块实现的,下面的图就是上述的代码的执行原理
在这里插入图片描述

如果客户端的URL访问的是servlet目录下,那么就代表是访问动态资源,服务器就会交给servlet处理,否则就会当成普通静态文件处理,从磁盘上取出响应即可。学习过一点如何编写webapp的同学会发现,上述代码中的servlet缓冲池(servletCache)与web.xml中的servlet映射很相似,都是通过名字来映射到一个具体的servlet实现类,服务器动态加载servlet类实现业务逻辑操作也体现了动态Web的特性。
在浏览器的url地址栏输入http://localhost:8080/servlet/HTTPServlet?username=“王小虎”,结果如下在这里插入图片描述
在动态Web中,客户端可以与服务器交互,服务器通过与客户端的交互,来动态响应客户端。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值