【HTTP协议与Web服务器】JavaWeb开发基础


Web

Java Web 开发是指使用 Java 技术构建动态的 Web 应用程序。它涉及到多个层次的开发,包括前端展示、业务逻辑处理和数据持久化。


Web软件架构

Web 软件架构涉及设计和组织 Web 应用程序的不同组件和层次,以确保系统的可维护性、扩展性和性能。以下是常见的 Web 软件架构组件和模式:

1. 客户端(前端)

  • 用户界面(UI):包括网页设计和用户交互元素,通常使用 HTML、CSS 和 JavaScript 开发。
  • 前端框架:如 React、Angular、Vue.js,用于构建动态和响应式用户界面。
  • 客户端逻辑:处理用户输入、验证、动态更新页面内容等功能。

2. 服务器端(后端)

  • 应用服务器:处理业务逻辑和数据处理,接收客户端请求并生成响应。常见的应用服务器包括 Apache Tomcat、Jetty、JBoss 等。
  • Web 服务器:如 Apache HTTP Server、Nginx,负责接收客户端请求并将其转发给应用服务器。

3. 服务层

  • 业务逻辑:处理应用程序的核心功能,如数据处理、计算和业务规则。
  • 服务接口:提供与客户端或其他服务交互的 API 接口,通常使用 RESTful API 或 GraphQL。

4. 数据层

  • 数据库:存储和管理应用程序的数据。包括关系型数据库(如 MySQL、PostgreSQL)和 NoSQL 数据库(如 MongoDB、Cassandra)。
  • 数据访问层:负责与数据库的交互,进行数据的增删改查操作。通常使用 ORM(对象关系映射)工具,如 Hibernate、JPA。

5. 安全层

  • 身份验证:验证用户的身份,确保用户是其声称的身份。常见的方法包括用户名/密码、OAuth、JWT(JSON Web Token)。
  • 授权:管理用户的权限,控制用户对特定资源的访问权限。
  • 数据加密:保护数据的机密性,使用 SSL/TLS 加密数据传输。

6. 缓存层

  • 缓存:提高系统性能,减少数据库访问次数。常见缓存工具包括 Redis、Memcached。
  • 内容分发网络(CDN):加速静态资源的分发,提高网站的加载速度,减少服务器负担。

7. 监控和日志

  • 监控:实时监控应用程序和服务器的性能,检测系统健康状况。工具如 Prometheus、Grafana。
  • 日志:记录应用程序的运行状态和错误信息,用于故障排查和性能分析。工具如 ELK Stack(Elasticsearch, Logstash, Kibana)。

8. 构建和部署

  • 构建工具:自动化编译、测试和打包过程,如 Maven、Gradle。
  • 持续集成/持续部署(CI/CD):自动化构建、测试和部署应用程序,提高开发效率和代码质量。
  • 容器化:使用 Docker 容器技术部署应用程序,确保环境一致性和便于扩展。

9. 架构模式

  • MVC(Model-View-Controller):将应用程序分为模型、视图和控制器三部分,分离业务逻辑和用户界面。
  • 微服务架构:将应用程序拆分为多个独立的服务,每个服务负责不同的功能,彼此通过 API 进行通信。
  • 单体架构:将应用程序的所有功能打包在一个单一的部署单元中,适用于小型应用程序或初期开发阶段。

Web 服务器

我们在学习与测试中,通常会使用TomCat来作为小型的Web服务器,Tomcat 是一个开源的 Servlet 容器,负责运行 Java Servlets 和 JSP(JavaServer Pages)。它实现了 Java EE(现在称为 Jakarta EE)规范中的 Servlet 和 JSP 部分,使得 Java Web 应用程序可以在其中运行。

这里便产生了一个问题,什么是Servlet?
Servlet 是 Java EE(现在称为 Jakarta EE)规范的一部分,用于创建动态 Web 应用程序的服务器端组件。它是一种 Java 类,通过实现 javax.servlet.Servlet 接口,处理客户端请求并生成响应。

通俗来讲,Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。
那么,我们应该学习他有哪些用法:

Servlet快速入门:

  1. 创建JavaEE项目

  2. 导入依赖

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
    </dependency>
    
  3. 定义一个类,实现Servlet接口

    public class ServletDemo1 extends HttpServlet
    
  4. 实现抽象类中的抽象方法

  5. 在web.xml中配置:

    <web-app>
        <display-name>Archetype Created Web Application</display-name>
        <servlet>
            <servlet-name>login</servlet-name>
            <servlet-class>com.codingfuture.ServletDemo1</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>login</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    

代码示例:

public class ServletDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        System.out.println("doGet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
        System.out.println("doPost");
    }
}

Servlet3.0

  • 好处:

支持注解配置。可以不需要配置web.xml了

  • 步骤:
  1. 创建JavaEE项目
  2. 定义一个类,实现Servlet接口
  3. 重写方法
  4. 在类上使用@WebServlet注解,进行配置

代码示例:

@WebServlet(urlPatterns = "/demo1")
@WebServlet(value = "/demo2")
@WebServlet(name = "/demo3")
@WebServlet("/demo4")

前端跳转Servlet

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="/servlet4" method="get">
    <input name="username">
    <input type="submit" value="提交">
</form>

</body>
</html>

@WebServlet("/servlet4")
public class Servlet4 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        System.out.println("doGet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
        System.out.println("doPost");
    }
}

Servlet相关配置

  1. urlpartten:Servlet访问路径
    1. 一个Servlet可以定义多个访问路径 : @WebServlet({“/d4”,“/dd4”,“/ddd4”})
    2. ​ 路径定义规则:
      1. /xxx:路径匹配
      2. /xxx/xxx:多层路径,目录结构
      3. *.do: 扩展名匹配

代码示例:

@WebServlet({"/d2", "/dd2", "/ddd2"})//都可以访问到
@WebServlet("/demo2/user") //多层路径
@WebServlet("/demo2/*") //通配符,  *任意字符
@WebServlet("*.do") // 任意字符.do 访问

HTTP协议

HTTP(HyperText Transfer Protocol)是一种用于在客户端(如浏览器)和服务器之间传输数据的协议。它是Web通信的基础,主要用于请求和响应的交换。

HTTP协议分层模型

协议分层模型
图片转载自:互联网协议 - 走看看

HTTP 协议可以从不同的层次进行分解和理解,但通常不直接划分为多层。我们可以从网络协议的层次结构和 HTTP 协议的设计角度来理解它的分层:

  1. 应用层
  • HTTP协议本身:在OSI模型和TCP/IP模型中,HTTP 处于应用层。它定义了客户端和服务器之间的数据交换格式,包括请求和响应的结构、方法、状态码、头信息等。
  • HTTP的请求和响应:包括 HTTP 请求方法(如 GET、POST)、状态码(如 200 OK、404 Not Found)、头信息(如 Content-Type、Authorization)和正文(body)等。
  1. 传输层
  • TCP:在实际的数据传输中,HTTP 协议通常运行在 TCP 协议之上。TCP 提供了可靠的、面向连接的传输服务,确保 HTTP 消息的正确传输。
  • TLS/SSL:当 HTTP 被加密(使用 HTTPS)时,SSL/TLS 协议在传输层提供加密和安全保障。
  1. 网络层
  • IP:HTTP 数据包在网络中传输时,IP 协议负责将数据从源地址传输到目标地址。IP 协议位于网络层,提供了数据包的寻址和路由功能。
  1. 数据链路层
  • 以太网/Wi-Fi等:在最底层,数据链路层协议负责在物理网络上传输数据帧,包括以太网、Wi-Fi等技术。

HTTP的基本特点

  1. 请求-响应模型:
  • 客户端请求:客户端(如浏览器)发起HTTP请求,向服务器请求资源或服务。
  • 服务器响应:服务器处理请求并返回HTTP响应,包含请求结果或错误信息。
  1. 无状态:
  • 每个请求都是独立的,与之前或之后的请求无关。服务器不会记住客户端的状态或会话信息。
  1. 方法:
  • GET:请求资源,通常用于获取数据。
  • POST:提交数据,通常用于提交表单数据或创建资源。
  • PUT:更新资源,用于替换指定资源的内容。
  • DELETE:删除资源,用于请求删除指定资源。
  • HEAD:类似于GET,但只请求头信息,不返回实际数据。
  • OPTIONS:请求支持的HTTP方法。
  1. 状态码:
  • 2xx:成功(如200 OK)。
  • 3xx:重定向(如301 Moved Permanently)。
  • 4xx:客户端错误(如404 Not Found)。
  • 5xx:服务器错误(如500 Internal Server Error)。
  1. 头信息:
  • HTTP头信息包含请求和响应的元数据,如Content-Type、Content-Length、User-Agent等,用于描述数据的格式、长度和客户端信息。
  1. 协议版本:
  • HTTP/1.0:较早的版本,支持基础功能。
  • HTTP/1.1:引入了持久连接和管道化等功能,提升了性能。
  • HTTP/2:改进了性能,支持多路复用和压缩头信息,减少了延迟。
  • HTTP/3:基于QUIC协议,进一步减少延迟并提升性能。

请求(Request)与响应(Response)

理解 HTTP 中的请求与响应是掌握 Web 通信的基础。HTTP 请求和响应是客户端(如浏览器)与服务器之间交换信息的方式。以下是对 HTTP 请求和响应的详细理解:

Request

体系结构

HttpServletRequest 继承自 ServletRequest 接口。

ServletRequest      -- 父接口
         ⬆️
HttpServletRequest  -- 子接口
request 功能
获取请求行数据

请求行示例:GET /day02/demo1?name=zhangsan HTTP/1.1

1. 获取请求方式:GET
   * String getMethod()
2. 获取虚拟目录:/day02
   * String getContextPath()
3. 获取 Servlet 资源路径:/demo1
   * String getServletPath()
4. 获取 GET 请求参数:name=zhangsan
   * String getQueryString()
5. 获取请求 URI/day02/demo1
   * String getRequestURI()
   * StringBuffer getRequestURL() // http://localhost/day02/demo1
6. 获取协议及版本:HTTP/1.1
   * String getProtocol()

代码示例:

System.out.println(req.getMethod()); // GET/POST
System.out.println(req.getContextPath()); // /day02
System.out.println(req.getServletPath()); // /demo1
System.out.println(req.getQueryString()); // name=zhangsan
System.out.println(req.getRequestURI()); // /day02/demo1
System.out.println(req.getRequestURL()); // http://localhost:8080/day02/demo1
System.out.println(req.getProtocol()); // HTTP/1.1
获取请求头数据

方法:

  • String getHeader(String name):获取请求头的值
  • Enumeration<String> getHeaderNames():获取所有请求头名称

代码示例:

Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
    String name = headerNames.nextElement();
    String value = request.getHeader(name);
    System.out.println(name + "-----" + value);
}

获取浏览器信息:

String agent = req.getHeader("user-agent");
if (agent.contains("Chrome")) {
    System.out.println("谷歌浏览器");
} else if (agent.contains("Firefox")) {
    System.out.println("火狐浏览器");
}
获取请求体数据

请求体仅在 POST 请求中存在。

步骤:

  1. 获取流对象:
    • BufferedReader getReader():获取字符输入流

代码示例:

HTML 表单:

<form action="/requestDemo04" method="post">
    <input name="username" placeholder="输入用户名"><br>
    <input name="password" placeholder="输入密码"><br>
    <input type="submit" value="注册">
</form>

Servlet 代码:

@WebServlet("/requestDemo04")
public class RequestDemo04 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
        BufferedReader reader = request.getReader();
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
    }
}
获取请求参数

通用方法:

  1. String getParameter(String name):获取参数值
  2. String[] getParameterValues(String name):获取参数值的数组

注意:

  • 对于 POST 请求,设置编码为 UTF-8 以避免中文乱码:
    request.setCharacterEncoding("utf-8");
    

代码示例:

HTML 表单:

<form action="/Day02/requestDemo05" method="post">
    <input name="username" placeholder="输入用户名"><br>
    <input name="password" placeholder="输入密码"><br>
    <input type="checkbox" name="hobby" value="game">游戏
    <input type="checkbox" name="hobby" value="study">学习
    <input type="submit" value="注册">
</form>

Servlet 代码:

@WebServlet("/requestDemo05")
public class RequestDemo05 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
        String username = request.getParameter("username");
        System.out.println("请求参数:" + username);

        String[] hobbies = request.getParameterValues("hobby");
        for (String hobby : hobbies) {
            System.out.println(hobby);
        }
    }
}
请求转发

服务器内部的资源跳转。

步骤:

  1. 获取请求转发器对象:
    • RequestDispatcher getRequestDispatcher(String path)
  2. 使用 RequestDispatcher 对象进行转发:
    • forward(ServletRequest request, ServletResponse response)

代码示例:

@WebServlet("/requestDemo06")
public class RequestDemo06 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
        RequestDispatcher dis = request.getRequestDispatcher("/request2");
        dis.forward(request, response);
    }
}
共享数据
  • request 域:请求范围内的数据共享。
    • void setAttribute(String name, Object obj):存储数据
    • Object getAttribute(String name):获取数据
    • void removeAttribute(String name):移除数据

代码示例:

Servlet 1:

@WebServlet("/requestDemo08")
public class RequestDemo08 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
        request.setAttribute("msg", "我是RequestDemo08的资源");
        RequestDispatcher dis = request.getRequestDispatcher("/requestDemo09");
        dis.forward(request, response);
    }
}

Servlet 2:

@WebServlet("/requestDemo09")
public class RequestDemo09 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
        Object msg = request.getAttribute("msg");
        System.out.println("我访问到的资源是:" + msg);
    }
}
获取 ServletContext
  • ServletContext 是一个全局存储空间,所有用户都可以访问。

方法:

ServletContext servletContext = this.getServletContext();
servletContext.setAttribute("name", "zhangsan");

代码示例:

Servlet 1:

@WebServlet("/request1")
public class Request1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
        ServletContext sc = request.getServletContext();
        sc.setAttribute("msg", "hello1");
        request.getRequestDispatcher("/request2").forward(request, response);
    }
}

Servlet 2:

@WebServlet("/request2")
public class Request2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
        ServletContext sc = request.getServletContext();
        System.out.println("msg = " + sc.getAttribute("msg"));
    }
}

Response

响应消息
  1. 响应行:包括协议/版本、响应状态码、状态码描述

    • 例如:HTTP/1.1 200 OK
  2. 响应头

    • 格式:头名称: 值
    • 示例:Content-Type: text/html;charset=UTF-8
  3. 响应空行

  4. 响应体:传输给客户端的数据

响应体示例:

HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length: 101
Date: Thu, 17 Sep 2020 02:59:05 GMT
Location: /servletB

我是response
重定向
  • 重定向:资源跳转的方式
    • 设置状态码为 302
    • 设置响应头 Location

代码示例:

@WebServlet("/responseServlet01")
public class ResponseServlet01 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
        response.sendRedirect("/Day03/responseServlet02");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
        this.doPost(request, response);
    }
}
@WebServlet("/responseServlet02")
public class ResponseServlet02 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
        System.out.println("responseServlet02");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
        this.doPost(request, response);
    }
}
forwardredirect 区别
  • 重定向 (redirect):

    1. 地址栏发生变化
    2. 可以访问其它站点资源
    3. 两次请求,不能使用 request 对象共享数据
  • 转发 (forward):

    1. 地址栏路径不变
    2. 只能访问当前服务器资源
    3. 一次请求,可以使用 request 对象共享数据

注意: 不能使用重定向来访问 request 域中的数据。

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值