此博客用于记录在学习路上的点点滴滴,同时也把我的学习笔记分享给大家

Servlet

一 、Servlet是什么

  1. Servlet是JavaEE规范中的技术之一,是Java开发中最重要的动态资源
  2. 是一个运行在web容器(服务器)中的一个小的Java程序,能够接收来自客户端的基于HTTP协议的请求,并且对请求进行响应。
  3. 如果想实现Servlet的功能,可以通过实现此接口或者继承他的实现类
  4. 核心方法:service(),任何客户端的请求都会经过该方法。

二、执行流程

  1. 客户端(浏览器)向服务端发起HTTP请求;
  2. Tomcat服务器通过解析请求地址(URL),找到对应的web应用在这里插入图片描述
  3. 找到web应用的web.xml,解析出客户端想访问的web资源;
  4. 如果发现Servlet是第一次访问,服务器就会加载servlet,创建servlet对象;
  5. 调用servlet的init()方法;
  6. 再调用servlet的service()方法;
  7. service()方法执行完,服务器会响应数据给客户端浏览器;

三、配置方式(两种)

1. web.xml文件的配置
在这里插入图片描述
注意:

  1. 第一步是我们想要在浏览器去输入的虚拟目录下的一个地址;
  2. 步骤2和步骤3的名字一定要相同,不然会报错;
  3. 此图我们可以看到,第四步是全类名,服务器是通过反射的方式去拿到类的对象,并执行service()方法的;

2. 注解配置在这里插入图片描述

三、Servlet继承体系

  1. Servlet:顶层接口;
  2. GenericServlet:实现了Servlet接口,但是与协议无关,必须重写的方法是service
  3. HttpServlet:继承GenericServlet,基于HTTP协议的封装,需要重写doGet()和doPost()方法。
    在这里插入图片描述

四、Servlet的实现方式

  1. 第一种: 实现Servlet接口,实现所有抽象方法,该方式支持最大程度的自定义。
  2. 第二种: 继承GenericServlet抽象类,必须重写service()方法,其他方法可以选择重写,该方式让我们开发servlet变得简单,但是这种方式和http协议无关。
  3. 第三种: 继承HttpServlet抽象类需要重写doGet()和doPost()方法,该方式表示请求和响应都要和HTTP相关。
    **注意:**通常都使用第三种。
    在这里插入图片描述

五、Servlet的生命周期

  • 初始化(init()):默认情况下,Servlet对象会在第一次被访问的时候初始化,对应的init()方法得到执行,并且只会执行一次
  • 服务(service()):每当有一次来自于客户端的请求,Tomcat服务器会开启一个新的线程调用service()方法。
  • 销毁(destory()):服务器正常关闭,servlet对象会被销毁,对应的destory()方法执行,并且只会执行一次

注意: servlet对象从始至终都只会创建一次,销毁一次,所以servlet只有一个实例,也就是单例模式。
生命周期

六、Servlet线程安全问题

  • 为什么会出现线程安全问题?

    由于Servlet采用的是单例模式,而一个浏览器就代表一个线程,多个浏览器就是多线程,当我们要去对数据进行修改操作时,就容易出现线程安全问题。

  • 解决方案
    • 场景:当存在成员变量时,多个线程并发访问此变量
    • 解决方案:可变和共享,改变其中一个
  1. 改变共享属性:把成员变量变成局部变量;
  2. 改变可变属性:用final修饰,使其成为自定义常量;
  3. 同步锁:入synchronize同步锁;

注意:
加入同步锁,虽然解决了线程安全问题,但是Servlet却不能使用这种方式;
打个比方,当很多个人都在排队等待一个人用完资源,就会使得效率低下;

不过sun公司也想到了这个问题,sun公司提出的解决方法:

  1. 让Servlet去实现一个SingleThreadModel接口。
    见名知意,此接口的作用就是单线程模式,如果某个线程实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用service方法。

七、Servlet多映射方式

1. 第一种: 完全路径匹配
具体名称的方式,访问的资源路径必须和映射配置完全相同
2. 第二种: 目录匹配(/*)
/开头+通配符的方式,只要符合目录结构即可,不用考虑结尾是什么;
3. 第三种: 扩展名匹配(*.xxx)
通配符+固定格式结尾的方式,只要符合固定结尾格式即可;

优先级:越是具体的优先级越高,越是模糊通用的优先级越低。
结论:第一种>第二种>第三种
错误写法:

  1. 既不是/开头,也不是*开头;如:aaa
  2. *出现在中间;如:aaa/ */bbb

在这里插入图片描述

八、Servlet多路径映射

  • 我们可以给一个Servlet配置多个访问映射,从而根据不同的请求路径实现不同的功能。
    - 场景分析:

如果访问的路径是/VIP: 商品打9折;

  如果访问的路径是/svip:商品打5折;

 如果访问路径是其他: 商品不打折;

九、Servlet创建时机

1. 第一次访问时创建:

  • 优势:减少对服务器内存的浪费,提高了服务器启动的效率。
  • 弊端:如果有一些要在应用加载时就做的初始化操作,无法完成。

2. 服务器加载时创建:

  1. 优势:提前创建好了对象,提高了首次执行的效率,可以完成一些应用加载时要做的初始化操作。
  2. 弊端:对服务器内存占用较多,影响服务器启动效率。

3. 使用:

  • 修改servlet创建时机,在web.xml配置文件中的<Servlet>标签中,添加<load-on-startup>标签;

- 注意:

  1. 正整数嗲表服务器加载时创建,值越小,优先级越高;
  2. 负整数或不写代表第一次访问时创建。
  3. Servlet默认是第一次访问时创建。

在这里插入图片描述

十、默认Servlet

  1. 默认Servlet是由服务器提供的一个Servlet,它配置在Tomcat的conf目录中的web.xml中;
  2. 它的映射路径是<url-pattern>标签,我们在发送请求时,首先会在我们项目中的web.xml中查找映射配置,找到则执行,但是当找不到对应的Servlet路径时,就去找默认的Servlet,由默认的Servlet处理,所以,一切都是Servlet;

十一、总结

  1. Servlet是一个供其他Java程序(Servlet引擎)调用的Java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度。
  2. 针对客户端的多次Servlet请求,通常情况下服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,他就会驻留在内存中,为后续的其他请求服务,直至web容器退出,servlet才会销毁;
  3. 在Servlet的整个生命周期内,Servlet的init()方法只执行一次。
  4. 而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service()方法;对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service()方法再根据请求方式分别调用post或get方法。
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐