Servlet:

Servlet是SUN公司提供的一套规范,名称就叫Servlet规范,它也是JavaEE规范之一。使用JavaEE的API。目前在Oracle官网中的最新版本是JavaEE8,

  • Servlet是一个运行在web服务端的java小程序
  • 它可以用于接收和响应客户端的请求
  • 要想实现Servlet功能,可以实现Servlet接口,继承GenericServlet或者HttpServlet
  • 每次请求都会执行service方法
  • Servlet还支持配置
Servlet执行过程:
  1. 客户端浏览器发起请求
  2. Tomcat服务器解析URL
  3. 通过URL找到对应的应用
  4. 通过应用找到web.xml
  5. 解析请求资源地址URL
  6. 找到应用的资源
  7. 执行service方法,响应给客户端浏览器
Servlet关系视图:

Servlet实现方式:

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

表示接口中的所有方法在需求方面都有重写的必要。这种方式支持最大程度的自定义。

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

表示只在接收和响应客户端请求这方面有重写的需求,而其他方法可根据实际需求选择性重写,使开发Servlet变得简单。但是,此种方式是和HTTP协议无关的。

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

表示我们的请求和响应需要和HTTP协议相关。也就是说通过HTTP协议来访问的。那么每次请求和响应都符合HTTP协议的规范。请求的方式就是HTTP协议所支持的方式

实现Servlet:
public class ServletDemo03 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方式");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {}
}
继承GenericServlet:
public class ServletDemo01 extends GenericServlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("service方法执行了...");}
}
继承HttpServlet::
public class ServletDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("Servlet执行了");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
配置文件:
<?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_4_0.xsd"version="4.0"><!--Servlet配置--><servlet><servlet-name>servletDemo</servlet-name><servlet-class>com.example.demo.ServletDemo</servlet-class></servlet><!--映射配置--><servlet-mapping><servlet-name>servletDemo</servlet-name><url-pattern>/servletDemo</url-pattern></servlet-mapping><!--生命周期配置--><servlet><servlet-name>servletDemo02</servlet-name><servlet-class>com.example.demo.ServletDemo02</servlet-class></servlet><servlet-mapping><servlet-name>servletDemo02</servlet-name><url-pattern>/servletDemo02</url-pattern></servlet-mapping></web-app>
Servlet生命周期:
  • 对象的生命周期,就是对象从生到死的过程,
  • 出生:请求第一次到达Servlet时,对象就创建出来,并且初始化成功。只出生一次,就放到内存中。
  • 活着:服务器提供服务的整个过程中,该对象一直存在,每次都是执行service方法。
  • 死亡:当服务停止时,或者服务器宕机时,对象消亡。
  • Servlet对象只会创建一次,销毁一次。所以,Servlet对象只有一个实例。如果一个对象实例在应用中是唯一的存在,用了单例模式。

演示:

public class ServletDemo02 extends HttpServlet {// 对象出生@Overridepublic void init() throws ServletException {System.out.println("出生了");}// 对象服务@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("收到客户端请求");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}// 对象死亡@Overridepublic void destroy() {System.out.println("挂了");}
}
线程安全:

在Servlet中定义了类成员之后,多个浏览器都会共享类成员的数据。其实每一个浏览器端发送请求,就代表是一个线程,那么多个浏览器就是多个线程,多个线程会共享Servlet类成员中的数据,其中任何一个线程修改了数据,都会影响其他线程。因此,所以Servlet它不是线程安全的。分析产生这个问题的根本原因,其实就是因为Servlet是单例,单例对象的类成员只会随类实例化时初始化一次,之后的操作都是改变,而不会重新初始化。

解决:

在Servlet中定义类成员要慎重。如果类成员是共用的,并且只会在初始化时赋值,其余时间都是获取的话,那么是没问题。如果类成员并非共用,或者每次使用都有可能对其赋值,那么就要考虑线程安全问题了,把它定义到doGet或者doPost方法里面去就可以了。或者是直接加synchronized

演示:

public class ServletDemo03 extends HttpServlet {private String username;@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {synchronized (this) {// 在这里声明的话,就是把成员变量变成局部变量,谷歌进来是一个username,火狐进来又是另一个就不会出现出数据不安全了// String username = null;// String getParameter(String name):根据参数名称获取参数值username = req.getParameter("username");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// resp.getWriter  传数据给前端PrintWriter writer = resp.getWriter();writer.println("username:" + username);writer.close();}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);}
}
Servlet映射三种方式:
  1. 指名道姓,给具体的名称,访问路径必须和配置的一样
  2. /开头+通配符的方式,只要符合目录结构,无视结尾
  3. 通配符+固定格式结尾方式,只要符合固定结尾,无视前面路径

说明:映射优先级:越具体优先级越高,1>2>3

演示:

<?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_4_0.xsd"version="4.0"><!--&lt;!&ndash;ServletHttp配置&ndash;&gt;<servlet><servlet-name>servletDemo</servlet-name><servlet-class>com.example.demo.ServletDemo</servlet-class></servlet><servlet-mapping><servlet-name>servletDemo</servlet-name><url-pattern>/servletDemo</url-pattern></servlet-mapping>--><!--    &lt;!&ndash;/开头+通配符的方式&ndash;&gt;<servlet><servlet-name>servletDemo</servlet-name><servlet-class>com.example.demo.ServletDemo</servlet-class></servlet><servlet-mapping><servlet-name>servletDemo</servlet-name><url-pattern>/servlet/*</url-pattern></servlet-mapping>--><!--通配符+固定格式结尾  结尾写什么就写什么,开心就好--><servlet><servlet-name>servletDemo</servlet-name><servlet-class>com.example.demo.ServletDemo</servlet-class></servlet><servlet-mapping><servlet-name>servletDemo</servlet-name><url-pattern>*.itzhuzhu</url-pattern></servlet-mapping>
</web-app>

实现类:

public class ServletDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 定义一个商品金额int money = 1000;// 获取访问路径String uri = req.getRequestURI();// public int lastIndexOf(int ch): 返回指定字符在此字符串中最后一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。uri = uri.substring(uri.lastIndexOf("/"));// 条件判断if ("/vip".equals(uri)) {System.out.println("原价:" + money + "尊敬的Vip您的折后价是:" + money * 0.8);} else if ("/svip".equals(uri)) {System.out.println("原价:" + money + "尊敬的Sip您的折后价是:" + money * 0.1);} else {System.out.println("会员都不开还想打折?打骨折");}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
Servlet创建时机:

第一种:服务器加载时创建

优势:
在服务器启动时,就把需要的对象都创建完成了,从而在使用的时候减少了创建对象的时间,提高了首次执行的效率。
弊端:
因为在应用加载时就创建了Servlet对象,因此,导致内存中充斥着大量用不上的Servlet对象,造成了内存的浪费。

第二种:第一次访问时创建

优势:
就是减少了对服务器内存的浪费,因为那些一直没有被访问过的Servlet对象都没有创建,因此也提高了服务器的启动时间。
弊端:
如果有一些要在应用加载时就做的初始化操作,它都没法完成,从而要考虑其他技术实现。
修改创建时机:在标签中添加标签

标签里的数字越小优先级越高,正整数代表服务器加载时创建,负数不写代表第一次访问的时候创建

    <servlet><servlet-name>servletDemo</servlet-name><servlet-class>com.example.demo.ServletDemo</servlet-class><!--数字越小越高,负数或者不写就是第一次访问的时候创建--><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>servletDemo</servlet-name><url-pattern>/servletDemo</url-pattern></servlet-mapping>
默认Servlet:

默认Servlet是由服务器提供的一个Servlet,它配置在Tomcat的conf目录下web.xml中。它的映射路径是<url-pattern>/<url-pattern>,在发送请求时,首先会在应用中的web.xml中查找映射配置,找到就执行。找不到对应的Servlet路径时,就去找默认的Servlet,由默认Servlet处理。

ServletConfig:

ServletConfig是Servlet的配置参数对象,在Servlet规范中,允许为每个Servlet都提供一些初始化配置。所以,每个Servlet都一个自己的ServletConfig。它的作用是在Servlet初始化期间,把一些配置信息传递给Servlet。比如servlet是个孩子,ServletConfig就是保姆

生命周期:

由于它是在初始化阶段读取了web.xml中为Servlet准备的初始化配置,并把配置信息传递给Servlet,所以生命周期与Servlet相同。需要注意的是,如果Servlet配置了1,那么ServletConfig也会在应用加载时创建。

配置ServletConfig:

<servlet>标签中,通过<init-param>标签配置,有两个子标签
<param-name>:代表初始化参数的key
<param-value>:代表初始化参数的value

ServletConfig方法:
返回值 方法名 说明
String getInitParameter(String name) 根据参数名称获取参数的值
Enumeration getInitParameterNames() 获取所有参数名称的枚举
String getServletName 获取Servlet的名称
SerlvetContext getServletContext 获取ServletContext对象
演示:

配置信息:

    <servlet><servlet-name>servletDemo05</servlet-name><servlet-class>com.example.demo.ServletDemo05</servlet-class><!--配置ServletConfig,是以键值对的形式存在的--><init-param><param-name>itz</param-name><param-value>itzhuzhu</param-value></init-param></servlet><servlet-mapping><servlet-name>servletDemo05</servlet-name><url-pattern>/servletDemo05</url-pattern></servlet-mapping>

实现类:

public class servletDemo04 extends HttpServlet {// 声明ServletConfigprivate ServletConfig config;// 因为ServletConfig是在初始化期间传递信息,所以要在init方法里去获取@Overridepublic void init(ServletConfig config) throws ServletException {// 通过init方法,对ServletConfig对象赋值this.config = config;}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// getInitParameter(String name):根据key获取valueString encodingValue = config.getInitParameter("encoding");System.out.println(encodingValue);// getInitParameterNames():获取所有keyEnumeration<String> keys = config.getInitParameterNames();while (keys.hasMoreElements()) {// 获取每一个keyString key = keys.nextElement();// 根据key获取valueString value = config.getInitParameter(key);System.out.println(key + " : " + value);}// getServletName  获取Servlet的名称String servletName = config.getServletName();System.out.println(servletName);// getServletContext  获取ServletContext对象ServletContext servletContext = config.getServletContext();System.out.println(servletContext);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

ServletContext:

ServletContext对象,它是应用上下文对象。每一个应用有且只有一个ServletContext对象。

作用:

它可以配置和获取应用的全局初始化参数,实现所有Servlet之间的数据共享。

生命周期:
  • 出生: 应用一加载,该对象就被创建出来了。一个应用只有一个实例对象。(Servlet和ServletContext都-是单例的)
  • 活着:只要应用一直提供服务,对象就一直存在。
  • 死亡:应用被卸载(或者服务器挂了),对象死亡。
域对象概念:
  • 域对象:指的是对象有作用域(作用范围)
  • 域对象的作用:域对象可以实现数据共享。
  • 不同作用范围的域对象,共享数据的能力不一样。在Servlet规范中,一共有4个域对象。ServletContext就是其中一个。也是web应用中最大的作用域,叫application域。每个应用只有一个application域(应用域),它可以实现整个应用间的数据共享功能。
ServletContext配置:

ServletContext被称之为应用上下文对象,所以它的配置是针对整个应用的配置,而非某个特定Servlet的配置。它的配置被称为应用的初始化参数配置。

配置的方式,需要在标签中使用来配置初始化参数

<param-name>:全局初始化参数的key
<param-value>:全局初始化参数的value

常用方法:
返回值 方法名 说明
String getInitParameter(String name) 根据名称获取全局配置的参数
String getContextPath() 获取当前应用访问的虚拟目录
String getRealPath 根据虚拟目录获取应用部署的磁盘绝对路径
应用域常用方法:
返回值 方法名 说明
void setAttribute(String name,Object value) 向应用域对象中存储数据
Object getAttribute(String name) 通过名称获取应用域对象中的数组
void removeAttribute(String name) 通过名称移除应用域对象中的数据

配置文件:

<!--因为servletContext它不属于某一个servlet,它是配置全局的,所以不能写在servlet里--><context-param><param-name>desc</param-name><param-value>This is Ser vletContextDemo</param-value></context-param><servlet><servlet-name>servletContextDemo</servlet-name><servlet-class>com.example.demo.ServletContextDemo</servlet-class></servlet><servlet-mapping><servlet-name>servletContextDemo</servlet-name><url-pattern>/servletContextDemo</url-pattern></servlet-mapping>

实现类:

public class ServletContextDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取ServletContext对象 , GenericServlet底层已经实现了getInitParameter所以可以直接调用  ServletConfig sc = this.getServletConfig();ServletContext context = getServletContext();//获取全局配置参数的descString value = context.getInitParameter("desc");System.out.println(value);//获取应用的访问虚拟目录String contextPath = context.getContextPath();System.out.println(contextPath);//根据虚拟目录获取应用部署的磁盘绝对路径String realPath = context.getRealPath("/");System.out.println(realPath);// 在src、wabapp、webinf创建三个文件获取路径//获取a.txt文件的绝对路径String a = context.getRealPath("/WEB-INF/classes/a.txt");System.out.println(a);//获取b.txt文件的绝对路径String b = context.getRealPath("/b.txt");System.out.println(b);String c = context.getRealPath("/WEB-INF/c.txt");System.out.println(c);//向域对象中存储数据context.setAttribute("username", "itzhuzhu");//移除域对象中username的数据,删除了再访问就变成null了context.removeAttribute("username");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

获取共享数据:

public class ServletDemo05 extends HttpServlet {// 声明ServletConfigprivate ServletConfig config;// 因为ServletConfig是在初始化期间传递信息,所以要在init方法里去获取@Overridepublic void init(ServletConfig config) throws ServletException {// 通过init方法,对ServletConfig对象赋值this.config = config;}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// getServletContext  获取ServletContext对象ServletContext servletContext = config.getServletContext();System.out.println(servletContext);// getAttribute(String name)   通过名称获取应用域对象中的数组Object username = servletContext.getAttribute("username");System.out.println(username);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}

Request方法详解:

Servlet方法详解相关推荐

  1. Java Servlet关键点详解

    Java Servlet关键点详解 1.理解Servlet的生命周期 Servlet引擎控制着Servlet的生命周期 Servlet的生命周期由以下三个方法进行描述(五个生命周期阶段) 1)初始化 ...

  2. java kaptcha_java相关:kaptcha验证码使用方法详解

    java相关:kaptcha验证码使用方法详解 发布于 2020-6-7| 复制链接 摘记: 本文为大家分享了kaptcha验证码的使用方法,供大家参考,具体内容如下1.首先在pom.xml文件中导入 ...

  3. Response响应方法详解

    Response: 响应:服务器把请求的处理结果告知客户端.在B/S架构中,响应就是把结果带回浏览器. 响应对象:在项目中用于发送响应的对象 常用状态码: 状态码 说明 200 执行成功 302 它和 ...

  4. java读写json格式的文件方法详解.txt,并批量存储进redis

    捐躯赴国难,视死忽如归.恸哭六军俱缟素,冲冠一怒为红颜.君子坦荡荡,小人长戚戚.风日晴和人意好,夕阳箫鼓几船归.民为贵,社稷次之,君为轻.Java 读写json格式的文件方法详解 文章录入:7747. ...

  5. 删除oracle数据库的三种方法,oracle数据库的删除方法详解

    oracle数据库的删除方法详解 1.图形界面删除 练习之前记得创建快照 执行命令之前要保证数据库属于open状态 SQL> alter database open; [oracle@local ...

  6. html页面设置拦截器,SpringBoot拦截器Filter的使用方法详解

    SpringBoot拦截器Filter的使用方法详解 发布时间:2020-08-27 22:44:03 来源:脚本之家 阅读:107 作者:玉天恒 前言: 最新Servlet 3.0拦截器的使用 1. ...

  7. python统计csv行数_对Python 多线程统计所有csv文件的行数方法详解

    如下所示: #统计某文件夹下的所有csv文件的行数(多线程) import threading import csv import os class MyThreadLine(threading.Th ...

  8. python修改文件内容_Python批量修改文本文件内容的方法详解

    这篇文章主要介绍了Python批量修改文本文件内容的方法的相关资料,需要的朋友可以参考下 Python批量替换文件内容,支持嵌套文件夹 import os path="./" fo ...

  9. python二维元组_python中读入二维csv格式的表格方法详解(以元组/列表形式表示)

    如何去读取一个没有表头的二维csv文件(如下图所示)? 并以元组的形式表现数据: ((1.0, 0.0, 3.0, 180.0), (2.0, 0.0, 2.0, 180.0), (3.0, 0.0, ...

最新文章

  1. linux命令:系统裁剪之五dropbear嵌入式系统专用ssh服务
  2. winform 窗口 属性
  3. 关于DataFormWebPart中CreatedModifiedInfo信息的分开使用
  4. Flink DataStream 编程入门
  5. 团队冲刺第一阶段第五天
  6. 云小课 | DSC:快速识别敏感数据并脱敏
  7. python 密度聚类 使用_使用python+sklearn实现硬币图像上的结构化Ward层次聚类演示...
  8. 通过Shell脚本快速搭建高效Rsync服务
  9. 打印机(Brother MFC-7860DN)一直提示更换墨盒
  10. Asp.net 调用sqlserver存储过程参数传中文乱码!
  11. 蓝桥杯2017年第八届C/C++省赛C组第一题-贪吃蛇长度
  12. itexpdf同一个段落不同文字,如何设置不同的格式
  13. SQL Server数据库的查询语句
  14. 前端对页面中的 checked 选中状态的展示
  15. The7 — 响应式多用途 WordPress 主题 免费下载
  16. 《东周列国志》第七十八回 会夹谷孔子却齐 堕三都闻人伏法
  17. 隐藏微信公众号右上角的分享按钮
  18. 运用VBA将Excel中【以文本存储的数字】转换为【数字】格式(去除绿色小三角)
  19. 计算机语言的发明者,Lisp语言发明者、“人工智能之父” John McCarthy与世长辞
  20. ntp 服务 --Centos

热门文章

  1. spss多元非线性曲线拟合_快速掌握SPSS数据分析
  2. python获取文件路径下指定的类型的文件_python学习1-列出指定目录下的指定类型文件...
  3. 为什么自己编写的页面总是在那里抖动_别克威朗为什么销量不佳?
  4. java使用计算器完成加法、减法运算
  5. 用php 用拼出一个菱形_这可是我没来过的杭州呀!远在开封的他,用一种特殊的方式,拼出一个彩色杭州...
  6. 交叉渡线道岔规格_交叉渡线道岔选择基本原则
  7. linux 多个定时器,timer: 一个Linux下的超级精简的多重定时器:可实现成千上万个定时任务,定时精度可达纳秒级别,且同一时间点可添加不同的任务!适用于云后台服务和嵌入式等各种环境。...
  8. 【OpenCV 例程200篇】81. 频率域高斯低通滤波器
  9. flume数据丢失与重复_Flume监听文件到kafka,文件通道,kafka消费重复问题
  10. python多标签分类_如何通过sklearn实现多标签分类?