HTTP详解

1. web

1.1 web相关概念

软件架构
  1. C /S:客户端/服务器端

    1. 需要安装客户端应用
  2. B/S:浏览器/服务器端

    1. 不需要安装客户端应用,对于用户来说只需要记住域名访问就可以,高效,客户端零维护
资源分类
  1. 静态资源:所有用户访问后,得到的结果都是一样的,称为静态资源.静态资源可以直接被浏览器解析

    • 如: html、css,、JavaScript
  2. 动态资源:每个用户访问相同资源后,得到的结果可能不一样。称为动态资源。动态资源被访问后,需要先转换为静态资源,在返回给浏览器,(浏览器内部含有静态资源解析引擎)

    • 如:servlet/jsp、php、asp....

1.2 web服务器软件

相关概念
  1. 服务器:安装了服务器软件的计算机 ,比如之前电脑安装了mysql软件,那么你的电脑就是一台mysql服务器,

    根据ip地址就可以让其它主机访问到你的mysql服务器,并访问到相应的数据。

    • 服务器软件:接收用户的请求,处理请求,做出响应

    • web服务器软件:接收用户的请求,处理请求,做出响应。

    • 在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目,也称之为web容器

  2. 常见的java相关的web服务器软件:

    webLogic:oracle公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。

    webSphere:IBM公司,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。

    JBOSS:JBOSS公司的,大型的JavaEE服务器,支持所有的JavaEE规范,收费的。

    Tomcat:Apache基金组织,中小型JavaEE服务器,仅支持少量的JavaEE规范servlet/jsp。开源,免费。

    JavaEE:Java语言在企业级开发中使用的技术规范的总和,一共规定了13项大的规范

Tomcat:web服务器软件
  1. 下载:http://tomcat.apache.org/

  2. 安装:解压压缩包即可,注意:安装目录建议不要有中文和空格

  3. 启动:运行startup.bat/startup.sh

  4. 停止:运行shutdown.bat/shutdown.sh

1.3 Tomcat集成IDEA

概述:

将Tomcat集成到IDEA中,并且创建JavaEE的项目,部署项目。

1.4 Servlet

概念:
  • server applet ,运行在服务器端的小程序

  • Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。

  • 将来我们自定义一个类,实现Servlet接口,复写方法。

1.5 快速入门:

  1. 创建JavaEE项目

  2. 导入依赖

    XML 复制代码
      <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>4.0.1</version>
        </dependency>
  3. 定义一个类,实现Servlet接口

    java 复制代码
    public class ServletDemo1 extends HttpServlet
  4. 实现抽象类中的抽象方法

    java 复制代码
    public class ServletDemo1 extends HttpServlet {
    ​
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("前端发送了一个get请求");
        }
        
    }
  5. 在web.xml中配置:

    XML 复制代码
    <web-app>
        <display-name>Archetype Created Web Application</display-name>
        <servlet>
            <servlet-name>servlet</servlet-name>
            <servlet-class>com.codingfuture.ServletDemo1</servlet-class>
        </servlet>
    ​
        <servlet-mapping>
            <servlet-name>servlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    ​
    </web-app>

6.访问方式

XML 复制代码
http://localhost:8080/Test_war_exploded/ServletDemo1

1.6 Servlet3.0

  • 好处:

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

  • 步骤:
  1. 创建JavaEE项目

  2. 定义一个类,实现Servlet接口

  3. 重写方法

  4. 在类上使用@WebServlet注解,进行配置

代码示例:
java 复制代码
@WebServlet(urlPatterns = "/demo1")
@WebServlet(value = "/demo2")
@WebServlet(name = "/demo3")
@WebServlet("/demo4")
java 复制代码
http://localhost:8080/Http_Demo_war_exploded/servletDemo1
http://localhost:8080
/Http_Demo_war_exploded -- 虚拟路径  实际开发中我们会将虚拟路径配置成/
/servletDemo1   -- 资源路径 -- 资源路径是工作类的首字母小写
修改之后的路径是:
http://localhost:8080/servletDemo1

1.7 前端发送请求

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
​
<form action="/servletDemo1" method="post">
    <p>账户:
        <input name="username" type="text">
    </p>
    <p>
        密码: <input name="password" type="password">
    </p>
    <input type="submit" value="提交">
</form>
​
</body>
</html>
java 复制代码
@WebServlet("/servletDemo1")
public class ServletDemo1 extends HttpServlet {
​
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("前端发送了一个get请求");
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("前端发送了一个post请求");
    }
​
}

1.8 Servlet相关配置

  1. urlpartten:Servlet访问路径

    1. 一个Servlet可以定义多个访问路径 : @WebServlet({"/d4","/dd4","/ddd4"})

    2. 路径定义规则:

      1. /xxx:路径匹配

      2. /xxx/xxx:多层路径,目录结构

      3. *.do: 扩展名匹配

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

2.0 Http

2.1 TCP与UDP

  • 网络分层模型

  • IP IPv4 与IPv6

  • TCP (基于连接) 打电话 电话接通 互相通话 结束挂断

    • 如何实现连接: 三次握手 传输确认 四次挥手

    • 优点:传输稳定性强,适用于对网络通讯要求较高的场景 比如传输文件,发送邮件,浏览网页等等

  • UDP (基于非连接) 写信 对方是否收到,内容是否完整,顺序是否正确

    • 优点: 速度快,但是可能产生丢包,适用于对实时性要求比较高,对少量丢包没有太大要求,如语音通话,视频直播等
  • 无状态

    • 会话技术

      • Cookie

      • Session

2.2 Http超文本传输协议

Hyper Text Transfer Protocol (http)超文本传输协议 ,定义了,客户端和服务器端通信时,发送数据的格式

特点
  1. 基于TCP/IP的高级协议,安全

  2. 默认端口号:80

  3. 基于请求/响应模型的:一次请求对应一次响应

  4. 无状态的:每次请求之间相互独立,不能交互数据

2.3 HTTPS

  • HTTPS是HTTP协议的安全版本,HTTP协议的数据传输是明文的,是不安全的,HTTPS使用了 SSL/TLS 非对称加密协议进行了加密处理。

  • HTTP和HTTPS使用连接方式不同,默认端口也不一样,HTTP是80,HTTPS是443。

  • 对称加密与非对称加密(CA)

2.4 请求

请求行

请求方式 请求url 请求协议/版本 GET /login.html HTTP/1.1

请求方式:

HTTP协议有多种请求方式,常用的有2种

  • GET:

    1. 请求参数在请求行中,在url后。

    2. 请求的url长度有限制的

    3. 不太安全

  • POST:

    1. 请求参数在请求体中

    2. 请求的url长度没有限制的

    3. 相对安全

请求头

请求头:客户端浏览器告诉服务器一些信息 请求头名称: 请求头值 一种键值对形式

  • 常见的请求头:

    1. User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息

      • 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
  1. Referer:http://localhost/login.html

    • 告诉服务器,我(当前请求)从哪里来
  2. 演示

java 复制代码
   @Override
      protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          System.out.println("前端发送了一个post请求");
          String header = req.getHeader("User-Agent");
          if (header.contains("Chrome")) {
              System.out.println("用户当前使用的是谷歌浏览器");
          }
      }
请求空行

空行,就是用于分割POST请求的请求头,和请求体的。

请求体(正文):
  • 封装POST请求消息的请求参数的

java 复制代码
username: zs
password: 123

**注意:**username=123 请求体 ,只有post请求才可以查看到,get请求是没有的,get请求参数是在url中。

请求消息数据格式:
bash 复制代码
字符串格式:
POST /login.html    HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests:1
​
username: zs
password: 123

2.5 Request

体系结构

request对象继承体系结构:

java 复制代码
ServletRequest      --  父接口
            ⬆️  
HttpServletRequest  -- 子接口      
request功能
1.获取请求行数据

GET /day02/demo1?name=zhangsan HTTP/1.1

java 复制代码
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():        /day02/demo1
* StringBuffer getRequestURL()  :http://localhost/day02/demo1
* URI:统一资源标识符 : demo01/loginServlet    范围大        共和国
* URL:  统一资源定位符 : http://localhost/demo01/loginServlet    中华人民共和国
6.获取协议及版本:HTTP/1.1
* String getProtocol()
代码示例:
java 复制代码
System.out.println(req.getMethod());//1.获取请求方式 :GET/POST
System.out.println(req.getContextPath());//2.获取虚拟目录:
System.out.println(req.getServletPath());//3.获取Servlet资源路径: /demo3
System.out.println(req.getQueryString());//4.获取get方式请求参数:username=zs
System.out.println(req.getRequestURI());//5.URI:统一资源标识符 :/虚拟目录/demo3
System.out.println(req.getRequestURL());//6.URL:统一资源定位符http://localhost:8080/demo3
System.out.println(req.getProtocol());//7.获取协议及版本:HTTP/1.1HTTP/1.1
2.获取请求头数据
  • 方法:

    • String getHeader(String name):通过请求头的名称获取请求头的值

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

代码示例:
java 复制代码
 //1.获取所有请求头的值
  Enumeration<String> headernames = request.getHeaderNames();
  //2.遍历
  while (headernames.hasMoreElements()) {
  String name = headernames.nextElement();
  //3.根据名称获取头的值
  String value = request.getHeader(name);
  System.out.println(name + "-----" + value);
  }

getHeader 介绍,判断客户端是哪个浏览器

java 复制代码
//获取请求头数据  user - agent
String agent = req.getHeader("user-agent");//不区分大小写
//判断浏览器版本
if (agent.contains("Chrome")) {
      //处理兼容性问题
    System.out.println("谷歌浏览器");
} else if (agent.contains("Firefox")) {
    System.out.println("火狐浏览器");
}
3.获取请求参数:

演示:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
​
<form action="/servletDemo2" method="post">
    <p>账户:
        <input name="username" type="text">
    </p>
    <p>
        密码: <input name="password" type="password">
    </p>
    <p>
        <input type="checkbox" name="hobby" value="coding"> coding
        <input type="checkbox" name="hobby" value="football"> football
        <input type="checkbox" name="hobby" value="basketball"> basketball
    </p>
    <input type="submit" value="注册">
</form>
​
</body>
</html>
  1. 获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数

    1. String getParameter(String name):根据参数名称获取参数值 username=zs&password=123

    2. String\[\] getParameterValues(String name):根据参数名称获取参数值的数组 hobby=study&hobby=game

    • 中文乱码问题:

      • get方式:tomcat8 已经将get方式乱码问题解决了

      • post方式:会乱码

        解决:在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");​

java 复制代码
 /**
 * 获取请求参数通用方式
 */
​
@WebServlet("/servletDemo2")
public class ServletDemo2 extends HttpServlet {
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决post乱码问题 get请求中英文都可以
        //req.setCharacterEncoding("utf-8");
      
        System.out.println("前端发送了一个post请求");
        //1.根据参数名称获取参数值
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username);
        System.out.println(password);
       //2.根据参数名称获取参数值的数组 //String[] getParameterValues(String name)
        String[] hobbys = req.getParameterValues("hobby");
        for (String hobby : hobbys) {
            System.out.println(hobby);
        }
    }
}
4.请求转发(考点)

请求转发:一种在服务器内部的资源跳转方式

  1. 步骤:

    1. 通过request对象获取请求转发器对象:

      RequestDispatcher getRequestDispatcher(String path)

    2. 使用RequestDispatcher对象来进行转发:

      forward(ServletRequest request, ServletResponse response)

  2. 特点:

    1. 浏览器地址栏路径不发生变化

    2. 只能转发到当前服务器内部资源中。

    3. 转发是一次请求

5. 共享数据
  • 域对象:一个有作用范围的对象,可以在范围内共享数据

  • request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据

  • 方法:

    1. void setAttribute(String name,Object obj):存储数据

    2. Object getAttitude(String name):通过键获取值

    3. void removeAttribute(String name):通过键移除键值对

代码示例:
java 复制代码
/**
 * 请求转发:一种在服务器内部的资源跳转方式
 * 服务器内部资源跳转
 * 从一个Servlet跳转到另一个Servlet中
 * 这里是servletDemo1 跳转到servletDemo2中
 */
​
@WebServlet("/servletDemo1")
public class ServletDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String usernameValue = req.getParameter("username");
        // request 域
        req.setAttribute("username", usernameValue);
        // 请求转发
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servletDemo2");
// RequestDispatcher requestDispatcher = req.getRequestDispatcher("/http://www.baidu.com");
        requestDispatcher.forward(req, resp);
    }    
}
​
@WebServlet("/servletDemo2")
public class ServletDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object usernameValue = req.getAttribute("username");
        System.out.println(usernameValue);
​
    }
}
  • session域(多次请求,会话期间)

    java 复制代码
    @WebServlet("/servletDemo1")
    public class ServletDemo1 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String usernameValue = req.getParameter("username");
            // session 域
            HttpSession session = req.getSession();
            session.setAttribute("username", usernameValue);
          
           try {
                Thread.sleep(5000);
                // 除此此外,浏览器主动关闭,session域中的数据也会销毁
                session.removeAttribute("username");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    ​
    @WebServlet("/servletDemo2")
    public class ServletDemo2 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            HttpSession session = req.getSession();
            Object username = session.getAttribute("username");
            System.out.println(username);
    ​
        }
    }

获取ServletContext(Application域)

Servlet三大域对象: request、session、ServletContext。

ServletContext就是三大域对象之一。

  1. ServletContext是一个全局的储存信息的空间,在服务器启动时创建,在服务器关闭时销毁,

    • 一个JavaWeb应用只创建一个ServletContext对象,

    • 作用范围:所有的用户都可以取得此信息,此信息在整个服务器上被保留。

    • 属性范围值:只要设置一次,则所有的网页窗口都可以取得数据。

    • 方法:

      java 复制代码
      ServletContext servletContext = req.getServletContext(); 
      ServletContext servletContext = this.getServletContext();
      servletContext.setAttribute("username","zhangsan");
  2. request,一个用户可有多个。

    • reques:表示一个请求,只要发出一个请求就会创建一个request,它的作用域:仅在当前请求中有效。

    • 用处:常用于服务器间同一请求不同页面之间的参数传递

    • 方法:request.setAttribute();

  3. session,一个用户一个。

    • 会话:用户打开浏览器会话开始,直到关闭浏览器会话才会结束。一次会话期间只会创建一个session对象。

    • 用处:常用于web开发中的登陆验证界面(当用户登录成功后浏览器分配其一个session键值对)。

    • 方法:session.setAttribute();

三大域对象在使用上一样,只是三者作用域范围大小不一样。从小到到范围依次是:request < session < ServletContext

代码示例:
java 复制代码
@WebServlet("/servletDemo1")
public class ServletDemo1 extends HttpServlet {
​
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String usernameValue = req.getParameter("username");
        //ServletContext
        ServletContext servletContext = req.getServletContext();
        servletContext.setAttribute("username", usernameValue);
    }
}
​
java 复制代码
@WebServlet("/servletDemo2")
public class ServletDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        Object username = servletContext.getAttribute("username");
        System.out.println(username);
    }
}

2.6 Response

响应消息

  1. 请求消息:客户端发送给服务器端的数据

    • 数据格式:

      • 请求行

      • 请求头

      • 请求空行

      • 请求体

  2. 响应消息:服务器端发送给客户端的数据

    • 数据格式:

      • 响应行

      • 响应头

      • 响应空行

      • 响应体

    1. 响应行

      1. 组成:协议/版本 响应状态码 状态码描述

        HTTP/1.1 200 OK

      2. 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。

        1. 状态码都是3位数字

        2. 分类:

          1xx:试探性请求,服务器接收客户端消息,没接受完成,等待一段时间后,发送1xx状态码

          100: 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分

          2xx:成功。代表:200 服务器已经成功处理了请求

          3xx:重定向。代表:302(重定向),304(访问缓存)

          4xx:客户端错误。

          代表:

          404(请求路径没有对应的资源)

          405:比如请求方式 没有对应的doXxx方法

          5xx:服务器端错误。代表:500(服务器内部出现异常) ,比如运算错误

    2. 响应头:

      1. 格式:

        java 复制代码
        头名称 : 值 
      2. 常见的响应头:

        java 复制代码
        /*  Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式 
        /*  text/html;charset=utf-8
    3. 响应空行

    4. 响应体

      传输给前端的数据

      响应字符串格式

java 复制代码
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
java 复制代码
@WebServlet("/servletDemo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            // resp.setCharacterEncoding("utf-8");
            // Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
            // text/html;charset=utf-8
            resp.setContentType("text/html;charset=utf-8");
            int i = 5 / 0;
        } catch (ArithmeticException e) {
            System.out.println(e.getMessage());
            resp.getWriter().println("<h1>服务器正在维护。。。see you later</h1>");
        }
    }
}

2.7 重定向

  1. 重定向:资源跳转的方式

    代码实现:

    1. 设置状态码为302

      response.setStatus(302);

    2. 设置响应头location

      response.setHeader("location","/responseServlet02");

    3. 简单的重定向方法

      response.sendRedirect("/responseServlet02");

    代码示例:

java 复制代码
/**
 * @author Petrel
 */
@WebServlet("/responseServlet01")
public class ResponseServlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("访问了responseServlet01");
        // 访问 /responseServlet01  会跳转到 /responseServlet02资源
        // 方法一
        // 1.设置状态码为302
        // resp.setStatus(302);
        // 2.置响应头location
        // resp.setHeader("location", "/responseServlet02");
        // 方法二
        // 3.简单的重定向方法
        // resp.sendRedirect("/responseServlet02");
        // resp.sendRedirect("http://www.baidu.com");
    }
}
​
@WebServlet("/responseServlet02")
public class ResponseServlet02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("访问了responseServlet02");
    }
}
forward 和 redirect 区别
  1. 重定向的特点:redirect

    1. 地址栏发生变化

    2. 重定向可以访问其它站点(服务器)的资源

    3. 重定向是两次请求。不能使用request对象来共享数据

  2. 转发的特点:forward

    1. 转发地址栏路径不变

    2. 转发只能访问当前服务器下的资源

    3. 转发是一次请求,可以使用request对象来共享数据

  3. 注意

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

相关推荐
数据知道15 分钟前
SSTI 模板注入:Jinja2 沙箱逃逸实战
网络·安全·网络安全
m0_7494922222 分钟前
化工反应釜维护作业口罩选型方案
人工智能·网络协议
瀚高PG实验室27 分钟前
几种因网络波动导致应用与数据库操作异常的现象
运维·网络·数据库·postgresql·瀚高数据库
风曦Kisaki28 分钟前
# Kubernetes(K8s)笔记Day15:K8s网络工作原理【Pod 网络模型,CNI 网络插件,Calico 工作模式详解,BGP协议,路由反射器】
运维·网络·nginx·云原生·容器·kubernetes
allforgood30 分钟前
管理 SELinux 安全性
linux·运维·网络
Fnetlink134 分钟前
Fnet 云网安 260810
网络·安全·web安全
Safeploy安策数据40 分钟前
网络保密机如何部署?破解敏感数据跨域流转安全难题
网络·安全
xixiaoyunya3 小时前
移动办公场景下手机远程访问内网设备的技术方案选型与实践
网络·智能手机·智能路由器
caimouse11 小时前
TDI (传输驱动接口 Transport Driver Interface) 详细分析
网络协议
weixin_4462608513 小时前
从被动镜像到主动智能体:面向网络物理人工智能的整体论数字孪生(HDT-Net)
网络·人工智能