Java In Mind

HTTP 与 Java Web

2019-11-01  本文已影响0人  SevenLin1993

技术公众号:Java In Mind(Java_In_Mind),欢迎关注!

HTTP协议

HTTP(HyperText Transfer Protocol,超文本传输协议),是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网数据通信的基础。

HTTP始于1989年,于1999年的HTTP/1.1版本流行至今(2015年HTTP/2,2018年HTTP/3),已经成为互联网不可或缺的协议,HTTP协议属于应用层,底层基于提供可靠传输的网络协议(基本基于TCP/IP协议,但HTTP协议没有规定使用具体协议),实现客户端与服务端的通信(请求/响应)。

HTTP客户端发起连接默认使用80端口,可以自定义端口,服务器则监听客户端请求,进行对应处理后放回响应结果(状态码,响应内容等信息)

HTTP/1.1中定义了8方法

GET

一般使用GET发出查询/读取请求,不应该产生副作用(即,幂等性),通过请求路径和请求参数或来指定要查询的资源,一般没有请求体,某些服务器,浏览器可能会对GET请求做缓存,所以不要将GET用于操作数据

HEAD

与GET类似,只不过服务区不回传资源信息,获取报头信息(元数据)

POST

向服务器提交数据,请求服务器进行数据处理(如,表单提交、文件上传等),数据包含在请求体中提交到服务器,一般用于创建资源或者修改资源。

PUT

与POST类似,一般用于更新资源,PUT操作不同于POST的是它是幂等性的,意味着多次请求结果会是一样的

DELETE

请求服务器删除指定资源

TRACE

回显服务器收到的请求,主要用于测试或诊断

OPTIONS

用于服务器告诉客户端请求的资源的所有支持的HTTP请求方法,也可以对整站(通过将 URL 设置为“*”)使用该方法。

CONNECT

HTTP/1.1协议中预留给能够将连接改为管道方式(tunnel)的代理服务器,通常用于SSL加密服务器的连接(HTTPS)

其他

HTTP支持自定义拓展方法,例如,PATCH用于修改局部资源,非幂等性

状态码

1XX

请求已经被服务器接收,例如,使用websocket,会通过101来进行协议切换

2XX

成功,请求成功被服务器接收,理解,并处理,如,200请求成功

3XX

重定向,需要后续操作才能完成这次请求,如,301会根据Location头进行重定向

4XX

请求错误,请求不被服务端理解,无法处理,一般为客户端发出的请求格式问题,如,401没有认证

5XX

服务端错误,服务端在处理该请求的时候出现错误,如,500服务内部错误

理解HTTP协议

HTTP报文

格式:

起始行(请求行/响应行)

头部

空行(CRLF)

实体

一个简单的HTTP请求报文:

GET /demo HTTP/1.1
Host: localhost

一个简单的HTTP响应报文:

HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Content-Length: 10
Date: Thu, 31 Oct 2019 11:44:49 GMT

HelloWorld

使用Java实现一个简单HttpClient

@RestController
@RequestMapping("/demo")
@SpringBootApplication
public class DemoApplication{

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @GetMapping
    public String helloWorld() {
        return "<h3>HelloWorld</h3>";
    }

}

public class SimpleClient {

    public static void main(String[] args) throws Exception {

        Socket socket = new Socket("localhost", 8080);

        OutputStream out = socket.getOutputStream();

        String http = "GET /demo HTTP/1.1\r\n" +
                "Host: localhost:8080\r\n" +
                "\r\n";

        out.write(http.getBytes(StandardCharsets.UTF_8));

        out.flush();

        InputStream in = socket.getInputStream();

        BufferedReader reader = new BufferedReader(new InputStreamReader(in,StandardCharsets.UTF_8));

        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }

        in.close();

        socket.close();

    }

}

思考

如果我们把Server端也用ServerSocket来实现,那么解析客户端不同的HTTP报文做出不同的响应不就实现了一个简单的Servlet容器的效果么?把HTTP的报文封装成request和response,把处理程序封装成Servlet,根据URL做路由,这就是Java Web的实现逻辑,而通过ServerSocket实现的程序就类似Tomcat容器,只是真实的Servlet容器要考虑许多东西,如:高并发、性能方面的问题。

public class SimpleHttpServer {

    private static boolean shutdown = false;

    public static void main(String[] args) throws Exception {
        SimpleHttpServer server = new SimpleHttpServer();
        server.await();
    }


    public void await() throws Exception {

        ServerSocket serverSocket = new ServerSocket(8888, 10, InetAddress.getByName("localhost"));

        while(!shutdown){

            Socket socket = serverSocket.accept();

            InputStream in = socket.getInputStream();
            StringBuilder builder = new StringBuilder();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String line = reader.readLine();
            while (line != null){
                if("".equalsIgnoreCase(line)){
                    builder.append(line);
                    break;
                }
                builder.append(line).append("\r\n");
                line = reader.readLine();
            }
            System.out.println(builder.toString());

            PrintWriter out = new PrintWriter(socket.getOutputStream());

            // Version & status code
            out.print("HTTP/1.1 200 \r\n");
            // The type of data
            out.print("Content-Type: text/html\r\n");
            // Will close stream
            out.print("Connection: close\r\n");
            // End of headers
            out.print("\r\n");
            out.println("<p>helloworld</p>");

            out.close();
            in.close();
            socket.close();

        }
        serverSocket.close();

    }

}

以上例子就可以实现从浏览器访问,然后返回一个简单的helloword页面,如果进一步把请求报文封装成request,把处理程序封装成servlet,把响应报文封装成response,那么就实现一个比较简易的HttpServer,然后把连接通过Connector管理起来,把servlet通过容器管理起来,这就是一个简单Servlet容器。

参考

上一篇 下一篇

猜你喜欢

热点阅读