1. 什么是Servlet?

Servlet是SUN公司提供的一套规范,名称就叫Servlet规范,它也是JavaEE规范之一。

  • 第一:Servlet是一个运行在web服务端的java小程序
  • 第二:它可以用于接收和响应客户端的请求
  • 第三:要想实现Servlet功能,可以实现Servlet接口,或者继承GenericServlet或者HttpServlet
  • 第四:客户端每次请求都会执行service方法
  • 第五:Servlet还支持配置

2. Servlet功能实现和执行过程

我们在实现Servlet功能时,可以选择以下三种方式:

实现Servlet接口,接口中的方法必须全部实现

public class ServletDemo01 implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("通过实现servlet接口,实现servlet功能");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}
}

继承GenericServlet,service方法必须重写,其他方可根据需求,选择性重写

public class ServletDemo02 extends GenericServlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("通过继承GenericServlet,实现servlet功能");}
}

继承HttpServlet,它是javax.servlet.http包下的一个抽象类,是GenericServlet的子类。 只需要重写doGet和doPost方法,不要覆盖service方法。、

public class ServletDemo03 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("通过继承HttpServlet,实现servlet功能");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

在web.xml声明servlet和映射servlet:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><!--servlet声明--><servlet><servlet-name>servletDemo03</servlet-name><servlet-class>com.yulu.servlet.ServletDemo03</servlet-class></servlet><!--servlet映射--><servlet-mapping><servlet-name>servletDemo03</servlet-name><url-pattern>/servletDemo03</url-pattern></servlet-mapping>
</web-app>

servlet的执行过程:客户通过浏览器发送请求,请求首先到达Tomcat服务器,由服务器解析请求URL(虚拟路径),然后在部署的应用列表中找到对应的web应用。接下来,在web应用中找应用里的web.xml配置文件,在web.xml中找到servlet映射和servlet声明,找到后执行service方法,最后由servlet响应客户浏览器。

3. Servlet的使用细节

3.1 servlet的生命周期

servlet的生命周期指:servlet从创建到销毁的过程。

出生:请求第一次到达Servlet时,servlet对象就创建出来并且初始化成功,并且只会创建一次放到内存中(注意:创建的时机可以修改)

活着:服务器提供服务的整个过程中,该对象一直存在,每次只是执行service方法。

死亡:当服务停止时,或者服务器宕机时,对象消亡。

Servlet对象只会创建一次,销毁一次。所以,Servlet对象只有一个实例。如果一个对象实例在应用中是唯一的存在,那么我们就说它是单实例的,即运用了单例模式。

3.2. Servlet线程安全问题

在Servlet中定义了类成员之后,多个浏览器都会共享类成员的数据。其实每一个浏览器端发送请求,就代表是一个线程,那么多个浏览器就是多个线程,多个线程会共享Servlet类成员中的数据,其中任何一个线程修改了数据,都会影响其他线程。因此,我们可以认为Servlet它不是线程安全的

/*
* servlet线程安全问题
* */public class ServletDemo04 extends HttpServlet {//定义一个用户名的成员变量,//多个浏览器访问同一个servlet,//相当于多个线程访问servlet,对于共享变量会出现安全问题private String username;@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//String username = null;//如定义在方法内,每一个浏览器进入后都是一个新的变量声明//通过name属性获取用户名//首先启动火狐 username=aaa,//再启动谷歌,将username修改为bbbsynchronized (this) {//this代表servlet对象,单例唯一username = req.getParameter("username");//将每个线程都睡眠一下try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}//将用户名响应到浏览器PrintWriter pw = resp.getWriter();pw.println("welcom   " + username);pw.close();}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

解决办法:

如果类成员是共用的,并且只会在初始化时赋值,其余时间都是获取的话,那么不会产生线程安全问题。如果类成员并非共用,或者每次使用都有可能对其赋值,那么就要考虑线程安全问题了,把它定义到doGet或者doPost方法里面去就可以了,或者使用同步代码块将代码锁起来也可以。

3.3 Servlet的三种映射方式

第一种:路径只有和映射配置一模一样时,Servlet才会接收和响应来自客户端的请求。

第二种:/开头+通配符的方式,只要符合目录结构即可,不用考虑结尾是什么。

第三种:通配符+固定格式结尾,只要符合固定结尾格式即可,其前面的访问URI无须关心(注意协议,主机和端口必须正确)

/*servlet多种映射的应用
* 不同访问路径得到商品价格不同
* */
public class ServletDemo05 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {int money = 1000;//得到资源的访问路径String path = req.getRequestURI();//得到最后一个斜杠后的子字符串path = path.substring(path.lastIndexOf('/'));//条件判断if ("/vip".equals(path)){System.out.println("原价为:" + money + "打折后为:" + money*0.9);}else if("/svip".equals(path)){System.out.println("原价为:" + money + "打折后为:" + money*0.5);}else {System.out.println("商品价格为:" + money);}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

配置文件:

<!--servlet多映射--><servlet><servlet-name>servletDemo05</servlet-name><servlet-class>com.yulu.servlet.ServletDemo05</servlet-class></servlet><servlet-mapping><servlet-name>servletDemo05</servlet-name><url-pattern>/servletDemo/*</url-pattern></servlet-mapping>

3.4 Servlet创建时机

Servlet的创建默认情况下是请求第一次到达Servlet时创建的

第一种:应用加载时(服务器启动之时)就创建Servlet,它的优势是在服务器启动时,就把需要的对象都创建完成了,从而在使用的时候减少了创建对象的时间,提高了首次执行的效率。

第二种:请求第一次访问时创建Servlet,它的优势就是减少了对服务器内存的浪费,因为那些一直没有被访问过的Servlet对象都没有创建,因此也提高了服务器的启动时间。

修改方法:在<servlet>标签中添加<load-on-startup>1</load-on-startup>,正整数代表在服务器加载的时候创建,值越小优先级越高。负整数或者不写代表在第一次访问时创建

3.5 默认的Servlet

默认Servlet是由服务器提供的一个Servlet,它配置在Tomcat的conf目录下的web.xml中。 它的映射路径是<url-pattern>/<url-pattern>我们在发送请求时,首先会在我们自己应用中的web.xml中查找映射配置,找到就执行。但是当找不到对应的Servlet路径时,就去找默认的Servlet,由默认Servlet处理(当我们访问servlet路径错误的时候,页面的错误信息就是通过默认的servlet显示)。所以,一切都是Servlet。

4. ServletConfig

4.1 ServletConfig介绍

  • ServletConfig 是 Servlet 的配置参数对象,在 Servlet 的规范中,允许为每一个 Servlet 都提供一些初始化的配置。所以,每个 Servlet 都有一个自己的 ServletConfig。
  • ServletConfig 作用:在Servlet 的初始化时,把一些配置信息传递给 Servlet。
  • ServletConfig 生命周期:和Servlet 相同。

4.2 ServletConfig的配置和使用

配置:Servlet的初始化参数都是配置在Servlet的声明部分的。每个Servlet都支持有多个初始化参数,并且初始化参数都是以键值对的形式存在

<!--ServletConfig--><servlet><servlet-name>servletConfigDemo</servlet-name><servlet-class>com.yulu.servlet.ServletConfigDemo</servlet-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>desc</param-name><param-value>This is a servletconfig</param-value></init-param></servlet><servlet-mapping><servlet-name>servletConfigDemo</servlet-name><url-pattern>/servletConfigDemo</url-pattern></servlet-mapping>

ServletConfig常用方法的使用:

public class ServletConfigDemo extends HttpServlet {//声明一个ServletConfig对象private ServletConfig config;//在初始化servlet的时候给ServletConfig赋值@Overridepublic void init(ServletConfig config) throws ServletException {this.config = config;}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//ServletConfig常用方法演示//1. 通过key得到valueString encodingValue = config.getInitParameter("encoding");System.out.println(encodingValue);//2. 获得所有的key,以枚举的形式Enumeration<String> keys = config.getInitParameterNames();while (keys.hasMoreElements()){//得到每一个keyString key = keys.nextElement();//根据key获取valueString value = config.getInitParameter(key);System.out.println(key + ":" + value);}//3. 获取Servlet的名称<servlet-name>中的名字String servletName = config.getServletName();System.out.println(servletName);//4. 获得ServletContext对象ServletContext servletContext = config.getServletContext();System.out.println(servletContext);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

5. ServletContext

5.1 ServletContext介绍

  • ServletContext 是应用上下文对象。每一个应用中只有一个 ServletContext 对象。
  • 作用:可以获得应用的全局初始化参数,可以实现 Servlet 之间的数据共享。
  • 生命周期:应用一加载则创建,应用被停止则销毁。

域对象:

  • 域对象指的是对象有作用域,也就是有作用范围。域对象可以实现数据的共享。不同作用范围的域对象,共享数据的能力也不一样。
  • 在 Servlet 规范中,一共有 4 个域对象。ServletContext 就是其中的一个。它也是 web 应用中最大的作用域,也叫 application 域。它可以实现整个应用之间的数据共享!

5.2 ServletContext配置全局初始化参数

  • ServletContext不属于某个Servlet配置,而是针对于整个应用的配置也叫全局的初始化参数。
  • 在<web-app>标签中,通过<context-param>标签来配置。有两个子标签。
  • <param-name>:代表全局初始化参数的 key。
  • <param-value>:代表全局初始化参数的 value。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"version="3.1"><!--servlet配置--><servlet><servlet-name>servletContextDemo</servlet-name><servlet-class>com.yulu.servlet.ServletContextDemo</servlet-class></servlet><servlet-mapping><servlet-name>servletContextDemo</servlet-name><url-pattern>/servletContextDemo</url-pattern></servlet-mapping><!--配置ServletContext--><context-param><param-name>globalEncoding</param-name><param-value>UTF-8</param-value></context-param><context-param><param-name>globalDesc</param-name><param-value>This is a ServletContext</param-value></context-param>
</web-app>

5.3 ServletContext常用方法

ServletContext获取全局参数:

public class ServletContextDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获得ServletContext对象ServletContext context = getServletContext();//常用方法演示//1. 获取全局配置参数,根据key获取valueString value = context.getInitParameter("globalDesc");System.out.println(value);//2. 获取应用的虚拟目录String contextPath = context.getContextPath();System.out.println(contextPath);//3. 根据虚拟目录获取绝对路径String realPath = context.getRealPath("/");System.out.println(realPath);//例如在web文件夹下的a.txt此时的目录只是在代码中的路径//通过getRealPath可以拿到a.txt在项目发布后所在的目录String realPath1 = context.getRealPath("/a.txt");System.out.println(realPath1);//获取WEB-INF下的b.txt绝对路径String realPath2 = context.getRealPath("/WEB-INF/b.txt");System.out.println(realPath2);//获取src目录下的c.txt的绝对路径String realPath3 = context.getRealPath("/WEB-INF/classes/c.txt");System.out.println(realPath3);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

ServletContext实现数据共享:

public class ServletContextDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//获得ServletContext对象ServletContext context = getServletContext();//常用方法演示//在ServletContextDemo类中设置一个应用域的共享数据context.setAttribute("username", "zhangsan");//在ServletConfig类中获取ServletContextDemo中设置的共享数据// Object username = servletContext.getAttribute("username");//删除共享数据context.removeAttribute("username");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

如有错误欢迎留言评论,2021年7月4日 羽露风

Servlet功能实现和执行过程、servlet的生命周期、Servlet线程安全问题、Servlet的三种映射方式、ServletConfig、ServletContext相关推荐

  1. Servlet的生命周期和线程安全问题

    目录 Servlet简介 Servlet 架构图 Servlet 任务 Servlet的生命周期 init() 方法 service() 方法 doGet() 方法 doPost() 方法 destr ...

  2. linux监控命令执行,你可能不知道的 即时监控 Linux 使用者执行指令的三种方法...

    原标题:你可能不知道的 即时监控 Linux 使用者执行指令的三种方法 这里介绍如何在 Linux 系统上以管理者权限即时监控一般使用者所执行的任何指令. Linux 的 root 管理者可对系统进行 ...

  3. jvm类加载过程_JVM类生命周期概述:加载时机与加载过程

    作者:菜鸟小于 https://www.cnblogs.com/Young111/p/11359700.html 一个.java文件在编译后会形成相应的一个或多个Class文件,这些Class文件中描 ...

  4. extjs 方法执行顺序_(软件工程)非结构化程序变为结构化程序的三种方法

    适用于软工考研.张海藩软件工程导论中结构化中结构化非结构化看完这篇文章应该就懂了. 结构化程序的思想 程序由顺序.选择和循环这三种基本结构组成.且它们都具有以下特点:只有一个入口;只有一个出口;结构中 ...

  5. Java 语言的开发和执行过程_开发与运行Java程序需要经过的三个主要步骤为 和 。...

    开发与运行Java程序需要经过的三个主要步骤为 和 . 更多相关问题 [单选] 孕.乳妇维持体内铁平衡需每矢从食物摄铁量为() [单选] 大多数HL患者的首发症状是() [单选] 侵及末梢血液造成赛塞 ...

  6. linux 跟踪命令执行过程,Linux的strace命令跟踪线程死锁

    strace命令,是Linux提供的跟踪系统调用的命令,需要sudo或root权限,可以查看进程(线程)使用的系统调用. 基本用法:sudo strace -p 进程号 如果一个线程递归获取同一个锁, ...

  7. 构建从目标到研发过程的全生命周期体验

    作者/PingCode研发PV孙敬云 最近有客户提出这样一个问题:现在的工具功能都大同小异,PingCode有什么特别之处? 那么要回答这个问题,我可能要从"根"上说起. 一.首先 ...

  8. 尚硅谷2020最新版宋红康JVM教程-中篇-第3章类的加载过程(类的生命周期)详解-4-过程三:Initialization(初始化)阶段

    static与final的搭配问题 初始化阶段,简言之,为类的静态变量赋予正确的初始值. 具体描述 类的初始化是类装载的最后一个阶段.如果前面的步骤都没有问题,那么表示类可以顺利装载到系统中.此时,类 ...

  9. python如何在所有线程结束后执行最后操作_Python线程的生命周期

    在线程的生命周期中,从创建到执行以及最终终止,线程通常处于四种状态之一:开始态.可调度状态.阻塞态和终止态. 父线程和子线程 当一个新的进程或程序开始运行时,它将以一个线程开始,这个线程被称为主线程. ...

最新文章

  1. test markdown
  2. 边缘AI芯片市场将在2025年首次反超云端AI芯片市场
  3. Spring Cloud中Hystrix仪表盘与Turbine集群监控
  4. Linux下支持rz/sz上传下载文件
  5. Mysql InnoDB索引分析
  6. flutter自定义弹窗
  7. RUNOOB python练习题30 回文数
  8. 一步步编写操作系统 14 CPU与外设通信——IO接口 上
  9. mysql导出数据不锁表_mysqldump锁表出错及解决方法
  10. 隐马尔科夫模型,第三种问题解法,维比特算法(biterbi) algorithm python代码
  11. 大学心理学课本_大学心理学的教材依次(全部)都有哪些?
  12. 企业入职测试题目及答案_[企业入职性格测试题以及答案信息] 新员工入职性格测试题...
  13. python修改ppt的字体和颜色_ppt-页面大小和颜色更改
  14. SAP ABAP 取物料号的采购订单文本内容
  15. Doevent()理解
  16. macOS 安装 aria2 下载 BitTorrent 替代迅雷
  17. Android Studio 屏幕分辨率适配
  18. [极客大挑战 2019]Http1(BUCTF在线评测)
  19. HTML我的家乡宁夏学生网页设计作品 dreamweaver作业静态HTML网页设计模板 宁夏旅游景点网页作业制作
  20. linux usb信息查看工具,Linux下,查看USB设备信息

热门文章

  1. 常用网络测试命令——ipconfig命令
  2. 大江大湖大桥大武汉--2019.9
  3. 最全MBTI人格测试
  4. 玖章算术荣获信通院“生成式人工智能技术和应用优秀案例”奖
  5. CPA将成为所有广告联盟和网站联盟的救命法宝--DoNews.com--IT社区写作平台ii
  6. String数组的拆分
  7. 贾跃亭被解除FF高级管理人员职务 公司面临摘牌危险
  8. GetOpenFileName打开文件对话框的使用
  9. Mathtype嵌入word和公式编号的问题
  10. 如何学好Python——你到底在学什么!