2020.1.12

  1. Servlet生命周期

    • init()::::::服务类第一次请求的时候,创建对象就会调用init()方法初始化类对象信息
      1. 第一次访问被创建出来-------------默认是一个负数值
      2. 在服务器启动的时候,被创建出来--------------这个时候是设置为 0或者正整数的
        • 注意:
          • 标签[load-on-startup]是用来标记容器是否在启动的时候就加载这个Servlet类,实例化这个类并执行init()方法
          • 标签[load-on-startup]必须是一个整数表示Servlet加载的顺序
          • 当值大于等于0的时候表示容器在启动的时候就加在初始化这个Servlet类
          • 当值小于0的时候表示容器在该Servlet被选中的时候才会去加载----->不选择是不会主动加载的
          • 当正数值越小表示在容器中的优先级越高,应用启动的时候就月线加载
          • 当值想通的时候容器会自动选择一个Servlet去加载
          • 在Servlet中这个init()方法只会加载一次,说明一个Servlet在内存中只会存储一个对象,也表明这个Servlet是单例的哟想要床架新的对象必须先销毁之前的对象,对象销毁之后再被穿件出来也不是相同的对象
            • 狭义单例:一个类在内存中有且仅有一个类对象,而且自始至终都只有同一个对象---->做法:把该累的构造器私有化
            • 广义单例:只要满足在整个系统中有且仅有一个示例即可,不一定是同一个对象----->Servlet中的对象就是广义的
            • 在Servlet 3.1规范中,当自定义Servlet类没有实现,SingleTheadModel接口的时候,Servlet类才是单位,如果实现该接口,每次请求Servlet类的时候,容器都会先创建一个新的Servlet类对象
            • 面试题:Servlet容器,如何保证在多线程环境下访问数据安全性问题
              • Servlet容器默认采用打你多线程方式处理多个请求
                • 当web容器启动的时候(或者客户端发送请求的时候),Servlet对象就会被加载并实例化,
                • 容器初始化主要就是读取配置文件----web.xml---在Tomcat容器中也有一个web.xml和server.xml--在server.xml中可以设置线程池中的数目,初始化线程池需要通过web.xml
                • 当客户端请求到达的时候Servlet容器可以通过线程调度它管理下的线程池中的等待执行的线程
                • 线程执行Servlet类中的service方法
                • 当线程执行完毕就会归还线程到线程池中
                • 当多个用户同时访问同一个Servlet类的时候就会存在现成数据安全问题,
                • 解决方法:不要Servlet类当中定义成员变量,避免多个线程同时操作同一份资源,如果定义了就只能查询不要修改
    • service():::::每次发送请求的时候会被执行。
      • ServletRequest:代表请求,会把Http请求的所有信息装配到ServletRequest对象中
      • ServletResponse:代表响应,会把Http响应中的信息装配到ServletReponse对象中
      • 手动指定话Servlet类对象创建时机---->通过在Servlet中配置标签[load-on-startup]标签
    • destory():Servlet类对象被销毁的时候就会被调用--->比如代码该了,类对象就被销毁了,服务器被关闭

Servlet 3.0

在以前的时候,每次有一个新的Servlet类都要都要去修改web.xml,当服务器运行的时候会加载web,xml如果Servlet类对象很多那么就会加载很慢,.3.0提供了注解

实现Servlet接口就是一个Servlet类

  • 步骤

    1. 创建一个Servlet类,选择Servlet3.0以上

    2. 在Servlet类上面添加@WebServlet()

    3. 在@WebServlet请求资源路径--不要忘记前面的斜杠)的小括号里面写url路径---->/demo01表示只能通过demo01来访问ServletDemo01,如果想要多个访问url用逗号隔开

      @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      public @interface WebServlet {
          String name() default ""; //相当于web.xml中的servlet-name标签
      
          String[] value() default {}; // 
      
          String[] urlPatterns() default {};
      
          int loadOnStartup() default -1;
      

欢迎页面

404

当我们向浏览器中输入我们的服务器地址,路径url格式:http://localhost:8080/day48/,此时tomcat会自动按照在web.xml文件汇总配置的welcome-file-list标签列表从上到下依次查找对应的web资源,如果全部找完都没有发现对应的资源,服务器就会给浏览器客户端返回一个404状态码(表示没找到web资源)--->有可能就是web路径写错了,找到了就是一个欢迎界面.访问当前应用根目录下的web文件夹下的资源

注意:我们访问的一般都是web文件夹下的资源,但是有一个文件夹下面的资源直接糖果浏览器是访问不道德,这个目录就称为安全目录(WEB-INF)--->只能他通过服务器内部来访问

两种访问web资源的方式

  • 内部转发:---->服务器行为

  • 重定向:------>客户端行为

    Servlet相关配置

    我们主要配置url-pattern标签客户端访问web应用资源的路径
    String[] urlPattern():一个Servlet可以配置多个访问路径 @WebServlet({"/demo01","/demo02","/demo03"....})
    路径定义的规则:
    /xxx:路径匹配/完全匹配
    /xxx/yyy/...:多层路径匹配或者目录匹配

    .do 或者 .action:---->叫做扩展名,服务器后面带有一个后缀,,,@WebServlet(".do") //表示再服务器访问的时候写啥都是可以的

    注意: *.do 或者 *.action是不需要斜杠的

    / 缺省配置:url-padding只写一个斜杠其他啥也不写,当访问web应用中的资源(Servlet)都不匹配,找不到的话就会寻找缺省配置的Servle

    让这个缺省配置的Servlet来处理请求资源,当前这个Servlet能处理的资源包括Servlet和静态资源,但是jsp资源解决不了

    / * 表示全部处理,包含静态,动态和jsp都能包含到,直接借助Servlet中访问方式:内部转发和重定向

HTTP

超文本传输协议,是互联网中应用最广泛的一种网络协议

传输协议:定义了客户端和服务器端通信时,发送数据的[ 格式 ]

  • 特点

    • 基于TCP/IP的协议
    • 默认端口号是: 80
    • 基于请求与响应模型的,一次请求对应一次响应
    • 无状态的:每次请求之间是相互独立的,每次请求之间不能进行数据的交互
  • 历史版本

    • 1.0:每次请求都要建立连接,每次都是新连接

    • 1.1---->主流常用的版本,持久连接(不用每次都建立新连接,这也是最大的变化),连接可以多次复用

      不用再声明:Connection:keep-alive

      • 如果发现客户端和服务器端一段时间没有活动,就会主动关闭连接,如果在客户端发送最后一个请求时,这个歌请求如果发送了Connection:close就是明确要求服务器关闭TCP连接

      • 目前大多数浏览器对于同一个域名最多同时允许建立六个持久连接,提高了带宽的利用率,

      • 加入了管道机制,在同一个连接里面允许发送多个请求,增加了并发性,改善了HTTP协议的效率

    • 2.0

      • 为了解决利用率不高的问题继续优化,提出了2.0版本的操作,增加了一个双工模式.不仅客户端能够同时发送多个请求,服务器端也能同时处理多个请求.解决了队列头堵塞问题.
  • 协议的组成与过程

    HTTP协议它是由HTTP请求和HTTP响应组成的,当在客户端中输入一个url地址,浏览器会把我们的请求信息封装为一个HTTP请求的格式发送个服务器,服务器端收到这个请求消息之后,服务器端就会解析这个请求消息,,,,解析这个请求消息将他装配到ServletRequest中,做完业务逻辑之后,会组织响应数据服装为一个HTTP响应的格式,返回给浏览器客户端-----------这个过程就是请求与响应----由此可以看出没有请求就没有响应.

  • 抓包分析

    使用谷歌知道的抓包工具,可以看到数据之间相互传播的课程

HTTP请求

get请求-----HTTP默认的请求方式是get请求(直接在客户端的地址栏中输入url和使用),对于form表单可以开于指定请求方式为post(是可以的不会有影响)

// 请求行:请求方式   请求路径  http版本号
GET /checkUser?username=admin&password=123456 HTTP/1.1
// 本机服务器的ip地址  域名    
Host: localhost:8080
// 连接的方式  长连接    
Connection: keep-alive
// 告诉服务器,自己支持你这中操作,我能读懂服务器发送的的信息,建议使用https而不是用http    
Upgrade-Insecure-Requests: 1
//用户使用的浏览器客户端的内核 还包括操作系统相关的信息
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
// 接收的数据格式   
// 告诉服务器端浏览器客户端能够接收的哪种类型的数据
Accept:
// mime类型  大范围/小范围
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
// 来源地--->浏览器通知服务器,当前的请求时来自于哪个地方
// Referer:经常用于防盗链  防止盗取我的连接信息 如果你是直接请求资源,没有referer
Referer: http://localhost:8080/
// 接收的压缩格式  浏览器通知服务器我可以接收哪些类型压缩格式的数据
Accept-Encoding: gzip, deflate, br
// 浏览器可支持的语言
Accept-Language: zh-CN,zh;q=0.9
// Cookie  JSESSIONID
Cookie: Idea-ac70df0d=96318eda-906d-4909-81b5-89db73f5358a; JSESSIONID=43EE4E93151302CD4B10579871CB8328

POST请求:

POST /checkUser HTTP/1.1
Host: localhost:8080
Connection: keep-alive
// 内容的长度    
Content-Length: 30
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8080
// 如果是post请求在请求体中的数据使用url编码
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: Idea-ac70df0d=96318eda-906d-4909-81b5-89db73f5358a; JSESSIONID=43EE4E93151302CD4B10579871CB8328
// 请求体内容
username=admin&password=123456

HTTP响应

// 响应行   http协议   状态码
HTTP/1.1 200
// 响应头 
// 响应正文的内容长度    当前为0
Content-Length: 0
// 响应的时间    
Date: Tue, 12 Jan 2021 07:49:14 GMT
Keep-Alive: timeout=20
Connection: keep-alive

常用的状态码

常用状态码 描述
200 请求成功
302 重定向
304 读取本地缓存的文件
404 请求的页面或资源找不到
405 请求方式不正确(比如:浏览器客户端使用get请求,服务器端接收使用的post就会报405)
500 服务器端代码错误,需要修改源代码

Servlet体系结构

在实际开发中我们创建Servlet类,大多数时间都是使用的service方法,由于必须遵从Servlet接口而不得不去重写其他的抽象方法,就很烦

这些方法大多数时候是闲置不用的,在Servlet中有一个HttpServlet类就把Servlet中我哥抽象方法封装起来了.我们以后可以定义一个类来继承这个类,最后的类也是一个Servlet类

GenericServlet基本上继承了Servlet接口中所有的抽象方法,处理service方法,需要子类来实现,但是由于客户端发送请求方式的区别,在service方法中还要做具体判断,不方便,他的子类HttpServlet当中实现了servlet方法,做了区分不同请求方式的实现,对外提供了七个请求的方法,由于目前阶段我们只使用get和post请求方式,所以关注重点也在doGet和doPost方法

查看源码发现doGet和doPost方法两个参数分别是HttoServletRequest和HttpServletResponse,就是我们需要的请求对象和响应对象

原文地址:https://www.cnblogs.com/tushao/p/14274797.html