【javaweb发展】
一、什么是javaweb
首先,客户端浏览器(Browser)到服务器(Client)是需要http协议沟通的。通过抓包工具查看一些http信息。

可以看到在请求数据报文中,http请求包含了三个部分,第一部分叫请求行,包含请求方法,url,协议,协议版本等。第二部分叫请求头,第三部分叫请求体。客户端(浏览器)发起这样的http请求。再来看响应数据报文。

一般来说,http响应包含了三个部分,第一部分叫响应行。第二部分叫响应头,第三部分叫响应体。一般来说,第三部分是html,类似以下数据:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>巴巴博弈</title>
</head>
<body>
<div id="app" class="fit">
<router-view></router-view>
</div>
</body>
</html>
那么在服务器端实现这样的http响应就能实现数据传输给客户端了,首先,http传输是基于tcp连接的,那么我们使用java自带的socket来写就行。以下是别人写好的代码(侵删)
public class Server { public static void main(String[] args) throws IOException { ServerSocket ss = new ServerSocket(8080); // 监听指定端口 System.out.println("server is running..."); for (;;) { Socket sock = ss.accept(); System.out.println("connected from " + sock.getRemoteSocketAddress()); Thread t = new Handler(sock); t.start(); } } } class Handler extends Thread { Socket sock; public Handler(Socket sock) { this.sock = sock; } public void run() { try (InputStream input = this.sock.getInputStream()) { try (OutputStream output = this.sock.getOutputStream()) { handle(input, output); } } catch (Exception e) { } finally { try { this.sock.close(); } catch (IOException ioe) { } System.out.println("client disconnected."); } } private void handle(InputStream input, OutputStream output) throws IOException { var reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); var writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8)); // TODO: 处理HTTP请求 } }
接下来只需要在handle中用reader读取http请求,用writer返回http响应即可实现服务器自动返回http数据。
private void handle(InputStream input, OutputStream output) throws IOException { System.out.println("Process new http request..."); var reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); var writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8)); // 读取HTTP请求: boolean requestOk = false; String first = reader.readLine(); if (first.startsWith("GET / HTTP/1.")) { requestOk = true; } for (;;) { String header = reader.readLine(); if (header.isEmpty()) { // 读取到空行时, HTTP Header读取完毕 break; } System.out.println(header); } System.out.println(requestOk ? "Response OK" : "Response Error"); if (!requestOk) { // 发送错误响应: writer.write("HTTP/1.0 404 Not Found\r\n"); writer.write("Content-Length: 0\r\n"); writer.write("\r\n"); writer.flush(); } else { // 发送成功响应: String data = "<html><body><h1>Hello, world!</h1></body></html>"; int length = data.getBytes(StandardCharsets.UTF_8).length; writer.write("HTTP/1.0 200 OK\r\n"); writer.write("Connection: close\r\n"); writer.write("Content-Type: text/html\r\n"); writer.write("Content-Length: " + length + "\r\n"); writer.write("\r\n"); // 空行标识Header和Body的分隔 writer.write(data); writer.flush(); } }
像这样,监听特定端口,解析http请求,返回http数据报的服务器程序,就是web服务器。实际上使用时不用自己写服务器,我们有现成的web服务器-tomcat,以下是使用tomcat里边的servlet实现web服务的例子(需要注意的是servlet服务需要导入jar包,请查看自己的包管理器怎么导入servletAPI的jar包):
// WebServlet注解表示这是一个Servlet,并映射到地址/: @WebServlet(urlPatterns = "/") public class HelloServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 设置响应类型: resp.setContentType("text/html"); // 获取输出流: PrintWriter pw = resp.getWriter(); // 写入响应: pw.write("<h1>Hello, world!</h1>"); // 最后不要忘记flush强制输出: pw.flush(); } }
可以看到,相比于自己写web服务,servlet简化了大量的操作。但是这样开发任然存在效率低下,配置时间长,代码耦合度高的弊端。
一、现代web开发。
现代web开发是tomcat向上集成在spring,再向上集成在springboot。
没有什么是增加中间层解决不了的,如果有,就在加一层。
为了解决代码耦合的问题,我们将返回http数据报的部分划分为三个部分,也就是MVC架构。对于现代javaweb开发,一般三层架构是指controller-处理用户请求,返回响应。service-逻辑处理。mapper(DAO)-数据库CRUD。不管哪种代码设计架构,都只是一些规范,重点在于架构实现了什么样的效果,比如mvc架构实现了代码的部分解耦,但是层与层之间还是耦合的,比如在service层调用mapper层的类,必然会导入mapper的包,那么mapper包改名之后,service层也得修改名称。为了实现完全解耦,spring引入了一个中间层-IoC容器。将创建对象的事情交给IoC容器来做,这样代码就实现了完全解耦,可以任意修改一层的代码而不必改动其他使用了该层的代码。详情可以找之前的博客。
二、springcloud
随着时代发展,springboot也不能很好解决大型、复杂且需要快速迭代和持续交付的项目开发。为了解决这样的问题,我们又加了四个中间层,Nacos(服务注册,在里面存ip:端口),OpenFeign服务调用(类似tomcat,实现底层协议书写(如http)),Sentinel(流量管理与安全层),RocketMQ(消息队列,实现异步通信)。

浙公网安备 33010602011771号