Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】
Servlet的调用图
前面我们已经学过了Servlet的生命周期了,我们根据Servlet的生命周期画出Servlet的调用图加深理解

Servlet的细节
一个已经注册的Servlet可以被多次映射
同一个Servlet可以被映射到多个URL上。
<servlet>
<servlet-name>Demo1</servlet-name>
<servlet-class>zhongfucheng.web.Demo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Demo1</servlet-name>
<url-pattern>/Demo1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Demo1</servlet-name>
<url-pattern>/ouzicheng</url-pattern>
</servlet-mapping>
无论我访问的是http://localhost:8080/Demo1还是http://localhost:8080/ouzicheng。我访问的都是Demo1。


Servlet映射的URL可以使用通配符
通配符有两种格式:
- *.扩展名
- 正斜杠(/)开头并以“/*”结尾。
匹配所有

匹配扩展名为.jsp的

如果.扩展名和正斜杠(/)开头并以“/”结尾两种通配符同时出现,匹配的是哪一个呢?
- 看谁的匹配度高,谁就被选择
- *.扩展名的优先级最低
Servlet映射的URL可以使用通配符和Servlet可以被映射到多个URL上的作用:
- 隐藏网站是用什么编程语言写的【.php,.net,.asp实际上访问的都是同一个资源】
- 用特定的后缀声明版权【公司缩写】
<servlet>
<servlet-name>Demo1</servlet-name>
<servlet-class>zhongfucheng.web.Demo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Demo1</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Demo1</servlet-name>
<url-pattern>*.net</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Demo1</servlet-name>
<url-pattern>*.asp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Demo1</servlet-name>
<url-pattern>*.php</url-pattern>
</servlet-mapping>
Servlet是单例的
为什么Servlet是单例的
浏览器多次对Servlet的请求,一般情况下,服务器只创建一个Servlet对象,也就是说,Servlet对象一旦创建了,就会驻留在内存中,为后续的请求做服务,直到服务器关闭。
每次访问请求对象和响应对象都是新的
对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。
线程安全问题
当多个用户访问Servlet的时候,服务器会为每个用户创建一个线程。当多个用户并发访问Servlet共享资源的时候就会出现线程安全问题。
原则:
- 如果一个变量需要多个用户共享,则应当在访问该变量的时候,加同步机制synchronized (对象){}
- 如果一个变量不需要共享,则直接在 doGet() 或者 doPost()定义.这样不会存在线程安全问题
load-on-startup
如果在元素中配置了一个元素,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。


作用:
- 为web应用写一个InitServlet,这个servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据
- 完成一些定时的任务【定时写日志,定时备份数据】
在web访问任何资源都是在访问Servlet
当你启动Tomcat,你在网址上输入http://localhost:8080。为什么会出现Tomcat小猫的页面?
这是由缺省Servlet为你服务的!
- 我们先看一下web.xml文件中的配置,web.xml文件配置了一个缺省Servlet
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- 什么叫做缺省Servlet?凡是在web.xml文件中找不到匹配的元素的URL,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求
- 既然我说了在web访问任何资源都是在访问Servlet,那么我访问静态资源【本地图片,本地HTML文件】也是在访问这个缺省Servlet【DefaultServlet】
- 证实一下:当我没有手工配置缺省Servlet的时候,访问本地图片是可以访问得到的

- 现在我自己配置一个缺省Servlet,Demo1就是我手工配置的缺省Servlet,覆盖掉web.xml配置的缺省Servlet
<servlet>
<servlet-name>Demo1</servlet-name>
<servlet-class>zhongfucheng.web.Demo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Demo1</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- 下面我继续访问一下刚才的图片,此时输出的是Demo1这个Servlet写上的内容了

- 总结:无论在web中访问什么资源【包括JSP】,都是在访问Servlet。没有手工配置缺省Servlet的时候,你访问静态图片,静态网页,缺省Servlet会在你web站点中寻找该图片或网页,如果有就返回给浏览器,没有就报404错误
ServletConfig对象
ServletConfig对象有什么用?
通过此对象可以读取web.xml中配置的初始化参数。
现在问题来了,为什么我们要把参数信息放到web.xml文件中呢?我们可以直接在程序中都可以定义参数信息,搞到web.xml文件中又有什么好处呢?
好处就是:能够让你的程序更加灵活【更换需求,更改配置文件web.xml即可,程序代码不用改】
获取web.xml文件配置的参数信息
- 为Demo1这个Servlet配置一个参数,参数名是name,值是zhongfucheng
<servlet>
<servlet-name>Demo1</servlet-name>
<servlet-class>zhongfucheng.web.Demo1</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>zhongfucheng</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Demo1</servlet-name>
<url-pattern>/Demo1</url-pattern>
</servlet-mapping>
- 在Servlet中获取ServletConfig对象,通过ServletConfig对象获取在web.xml文件配置的参数

ServletContext对象
什么是ServletContext对象?
当Tomcat启动的时候,就会创建一个ServletContext对象。它代表着当前web站点
ServletContext有什么用?
- ServletContext既然代表着当前web站点,那么所有Servlet都共享着一个ServletContext对象,所以Servlet之间可以通过ServletContext实现通讯。
- ServletConfig获取的是配置的是单个Servlet的参数信息,ServletContext可以获取的是配置整个web站点的参数信息
- 利用ServletContext读取web站点的资源文件
- 实现Servlet的转发【用ServletContext转发不多,主要用request转发】
Servlet之间实现通讯
ServletContext对象可以被称之为域对象
到这里可能有一个疑问,域对象是什么呢?其实域对象可以简单理解成一个容器【类似于Map集合】
实现Servlet之间通讯就要用到ServletContext的setAttribute(String name,Object obj)方法,
第一个参数是关键字,第二个参数是你要存储的对象
- 这是Demo2的代码
//获取到ServletContext对象
ServletContext servletContext = this.getServletContext();
String value = "zhongfucheng";
//MyName作为关键字,value作为值存进 域对象【类型于Map集合】
servletContext.setAttribute("MyName", value);
- 这是Demo3的代码
//获取ServletContext对象
ServletContext servletContext = this.getServletContext();
//通过关键字获取存储在域对象的值
String value = (String) servletContext.getAttribute("MyName");
System.out.println(value);
- 访问Demo3可以获取Demo2存储的信息,从而实现多个Servlet之间通讯

获取web站点配置的信息
如果我想要让所有的Servlet都能够获取到连接数据库的信息,不可能在web.xml文件中每个Servlet中都配置一下,这样代码量太大了!并且会显得非常啰嗦冗余。
- web.xml文件支持对整个站点进行配置参数信息【所有Servlet都可以取到该参数信息】
<context-param>
<param-name>name</param-name>
<param-value>zhongfucheng</param-value>
</context-param>
- Demo4代码
//获取到ServletContext对象
ServletContext servletContext = this.getServletContext();
//通过名称获取值
String value = servletContext.getInitParameter("name");
System.out.println(value);

- 试一下Demo3是否能拿到,相同的代码
//获取到ServletContext对象
ServletContext servletContext = this.getServletContext();
//通过名称获取值
String value = servletContext.getInitParameter("name");
System.out.println(value);

读取资源文件
第一种方式:
- 现在我要通过Servlet111读取1.png图片

- 按我们以前的方式,代码应该是这样的。
FileInputStream fileInputStream = new FileInputStream("1.png");
System.out.println(fileInputStream);
- 当我们访问的时候,却出错了!说找不到1.png文件

- 这是为什么呢?我们以前读取文件的时候,如果程序和文件在同一包名,可以直接通过文件名称获取得到的!,原因很简单,以前我们写的程序都是通过JVM来运行的,而现在,我们是通过Tomcat来运行的
- 根据web的目录规范,Servlet编译后的class文件是存放在WEB-INF\classes文件夹中的

- 看到这里,我们知道了要进入classes目录中读取文件,所以我们将代码改成以下方式
FileInputStream fileInputStream = new FileInputStream("D:\\zhongfucheng\\web\\WEB-INF\\classes\\zhongfucheng\\web\\1.png");
System.out.println(fileInputStream);
- 再去读取时,就发现可以获取到文件了。
- 但是现在问题又来了,我读取文件的时候都要写上绝对路径,这样太不灵活了。试想一下,如果我将该读取文件的模块移到其他的web站点上,我的代码就又要修改了【因为web站点的名字不一样】。
- 我们通过ServletContext读取就可以避免修改代码的情况,因为ServletContext对象是根据当前web站点而生成的
- 代码如下所示:
//获取到ServletContext对象
ServletContext servletContext = this.getServletContext();
//调用ServletContext方法获取到读取文件的流
InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/classes/zhongfucheng/web/1.png");

第二种方式:
- 如果我的文件放在web目录下,那么就简单得多了!,直接通过文件名称就能获取

- 代码如下所示
//获取到ServletContext对象
ServletContext servletContext = this.getServletContext();
//调用ServletContext方法获取到读取文件的流
InputStream inputStream = servletContext.getResourceAsStream("2.png");

第三种方式:
通过类装载器读取资源文件。
- 我的文件放在了src目录下【也叫做类目录】

- 代码如下所示
//获取到类装载器
ClassLoader classLoader = Servlet111.class.getClassLoader();
//通过类装载器获取到读取文件流
InputStream inputStream = classLoader.getResourceAsStream("3.png");

- 我的文件放在了src目录下的包下

- 代码如下,添加包名路径即可。
//获取到类装载器
ClassLoader classLoader = Servlet111.class.getClassLoader();
//通过类装载器获取到读取文件流
InputStream inputStream = classLoader.getResourceAsStream("/zhongfucheng/web/1.png");
原则:如果文件太大,就不能用类装载器的方式去读取,会导致内存溢出
Servlet第二篇【Servlet调用图、Servlet细节、ServletConfig、ServletContext】的更多相关文章
- Servlet第二篇(介绍、ServletConfig;ServletContext)
什么是Serlvet? Servlet其实就是一个遵循Servlet开发的java类.Serlvet是由服务器调用的,运行在服务器端. 为什么要用到Serlvet? 我们编写java程序想要在网上实现 ...
- 杂谈PID控制算法——第二篇:调·三个量
上面一篇文章讲了一下PID算法中的三个常量大致的在PID算法中起的一个作用,但在实际的使用中,究竟应该如何调节(或者用更加专业的话说是整定)PID控制算法的三个.首先可以将KP,KI,KD三个常量全部 ...
- javaweb回顾第六篇谈一谈Servlet线程安全问题
前言:前面说了很多关于Servlet的一些基础知识,这一篇主要说一下关于Servlet的线程安全问题. 1:多线程的Servlet模型 要想弄清Servlet线程安全我们必须先要明白Servlet实例 ...
- HTTP协议 Servlet入门 Servlet工作原理和生命周期 Servlet细节 ServletConfig对象
1 HTTP协议特点 1)客户端->服务端(请求request)有三部份 a)请求行--请求行用于描述客户端的请求方式.请求的资源名称,以及使用的HTTP协议版本号 请求行中的GET ...
- Servlet第一篇【介绍Servlet、HTTP协议、WEB目录结构、编写入门Servlet程序、Servlet生命周期】
什么是Serlvet? Servlet其实就是一个遵循Servlet开发的java类.Serlvet是由服务器调用的,运行在服务器端. 为什么要用到Serlvet? 我们编写java程序想要在网上实现 ...
- Servlet技术之——概述、实现、细节、获取资源、ServletConfig、ServletContext
Servlet概述.实现.细节.获取资源.ServletConfig.ServletContext (一) Setvlet基本概述 (1) 什么是Servlet ? Servlet(Server Ap ...
- 第二章 编写与设置Servlet
2.1 第一个Servlet package cc.openhome; import javax.servlet.ServletException; import javax.servlet.http ...
- Servlet追忆篇:那些年一起学习的Servlet
title: servlet notebook: javaWEB tags:servlet --- Servlet是什么? Servlet是JavaWeb的三大组件之一. 作用类似银行前台接待: 接收 ...
- 继续servlet理论篇
唉,毕业是件很麻烦的事情,实习也是一件很郁闷的事情,现在公司很注重基础,所以 所以还要看java,不过,我年轻,我有激情.来吧,来着不惧,说这话,有些心虚. HttpServlet类中所提供的doGe ...
随机推荐
- Objective-C写出Json文件(可作配置文件)
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC"; color: #008f00 } span. ...
- AugularJS1.X不升级到2.X
面试中提到AugularJS1.X不升级到2.X,而是改用React的原因是,可以利用很多React现成的组件,需要确认下 以及提到了Vue, Weex技术
- 使用GitHub Pages+Jekyll搭建个人博客
GitHub Pages 免费无限容量的站点数据托管工具(国内访问速度较慢),内置Jekyll服务,能将特定名称的代码仓库动态编译为静态网页 Jekyll 基于Ruby的静态网页生成系统,采用模板将M ...
- LAMP环境的搭建(三)----PHP7的安装
centos自带的PHP源是5.4版本的.如果需要安装PHP 5.4 直接输入 yum install php -y 即可 因为PHP7性能巨大的提升,因此本文选择安装PHP7 如果已经安装过了php ...
- Windbg调试关键区(CriticalSection)死锁
一. 准备工作 这里一个有关键区锁死问题的程序,运行之后依次点击"CS锁死"按钮.右上角退出按钮,程序就会卡死.(图1) 对于眼下的这个问题,界面完全失去响应,这说明负责消息处理的 ...
- WeQuant交易策略—BOLL
BOLL(布林线指标)策略 简介 BOLL(布林线)指标是技术分析的常用工具之一,由美国股市分析家约翰•布林根据统计学中的标准差原理设计出来的一种非常简单实用的技术分析指标.一般而言,价格的运动总是围 ...
- SpringMVC(二)--处理数据模型、ModelAndView、Model、Map、重定向、@ModelAttribute、
1.处理模型数据 Spring MVC 提供了以下几种途径输出模型数据: – ModelAndView:处理方法返回值类型为 ModelAndView 时, 方法体即可通过该对象添加模型数据 ...
- Java入门(7)——循环和debug 调试
循环: while 循环: 格式: int i = 0; ① //初始化条件 while(i < 10) { ② //判断条件 System.out.println(i); ④ //循环 ...
- [2017-08-21]Abp系列——如何使用Abp插件机制(注册权限、菜单、路由)
本系列目录:Abp介绍和经验分享-目录 Abp的模块系统支持插件机制,可以在指定目录中放置模块程序集,然后应用程序启动时会搜索该目录,加载其中所有程序集中的模块. 如何使用这套机制进行功能插件化开发? ...
- 互联网世界中的C语言——我的golang学习笔记:1(基础语法快速过)
前言 学习任何知识都会有一个学习背景 最近,我们团队乃至我司整个云服务,上go的呼声越来越高!新服务已经开始用go开发,部分现有Java版的服务重构为go也只是时间问题而已,故相关技术积累势在必行!在 ...