1. Servlet简介

Servlet是sun公司提供的一门用于开发动态web资源的技术。sun公司在其API中提供了一个servlet接口,用户若想要发一个动态web资源,只需要完成以下两步即可:

1)编写一个servlet,即实现servlet接口的Java类;

2) 把开发好的servlet部署到web服务器中。

Servlet接口定义了所有servlet必须实现的方法。一个servlet是运行在web服务器中的一个小java程序,servlet通过HTTP协议接收并响应web客户端发来的请求。这个接口中定义的方法包括初始化servlet,服务请求,以及remove servlet,这些方法即servlet的生命周期方法,调用顺序如下:

1)某个创建servlet对象的时候,调用初始化方法: void init(ServletConfig config)

2)客户端发送请求的时候,service方法被执行:void service(ServletRequest req, ServletResponse res)

3)某个servlet对象被摧毁的时候,调用destroy方法: void destroy()

除了这些与生命周期有关的方法外,Servlet接口还提供了getServletConfig方法和getServletInfo方法,getServletConfig方法可以获得servlet的一些启动信息,getServletInfo方法可以返回servlet本身的一些信息。

sun公司定义了Servlet接口的两个默认实现类,分别为javax.servlet.GenericServlet和javax.servlet.http.HttpServlet。

HttpServlet指能够处理HTTP请求的servlet,它再原有的Servlet接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大,因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口。HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式,如为GET请求,则调用HttpServlet的doGet方法,如为Post请求,则调用doPost方法。因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法

2. Servlet的运行过程

Servlet程序是由web服务器调用,web服务器接收到客户端的Servlet访问请求后:
           1)web服务器首先检查是否已经装载并创建了该Servlet的实例对象,如果是,则直接执行第4步,否则执行第2步。
           2)装载并创建该Servlet的一个实例对象。
           3)调用Servlet实例对象的init()方法。
           4)创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP相应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
           5)web应用程序被停止或重新启动前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。

3. Servlet的几个细节

1. Servlet细节1

由于客户端是通过URL地址访问文本服务器中的资源,所以servlet程序若想被外界访问,必须把servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成。

1) <servlet>元素用于注册Servlet,它包含两个主要的子元素:

<servlet-name>:用于设置Servlet的注册名称

<servlet-class>:用于设置Servlet的完整类名

2)<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含两个子元素:

<servlet-name>:用于设置Servlet的注册名称

<url-pattern>:用于指定Servlet的对外访问路径(可以随便指定)

例如:

<web-app>
<servlet>
<servlet-name>AnyName</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AnyName</servlet-name>
<url-pattern>/demo/hello.html</url-pattern>
</servlet-mapping>
</web-app>

2. Servlet细节2

同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。在Servlet映射到的URL中也可以使用*通配符,但是只能有两种固定的格式:一种格式是:“*.扩展名”;另一种格式是:以“/”开头,并以“/*”结尾。例如:

<servlet-mapping>
<servlet-name>AnyName</servlet-name>
<url-pattern>*do</url-pattern>
</servlet-mapping>

也可以映射到另一个url:

<servlet-mapping>
<servlet-name>AnyName</servlet-name>
<url-pattern>/action/*</url-pattern>
</servlet-mapping>

3. servlet细节3

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

4. servlet细节4

如果再<servlet>元素中配置了一个<load-on-startup>元素,那么web应用程序在启动时,就会装载并创建Servlet的实例对象,以及调用Servlet实例对象的init()方法。该技术可以用来为web写一个initServlet,这个servlet配置为启动时装载,为整个web应用床架必要的数据库表和数据。如:

<servlet>
<servlet-name>...</servlet-name>
<servlet-class>...</servlet-class>
<load-on-startup>1<load-on-startiup>
</servlet>

5. servlet细节5

如果某个Servlet的映射路径仅仅为一个正斜杠(/),那么这个Servlet就成为当前Web应用程序的缺省Servlet。凡是在web.xml文件中找不到匹配的<servlet-mapping>元素的url,它们的访问请求都将交给缺省Servlet处理,也就是说,缺省Servlet用于处理所有其他Servlet都不处理的访问请求。
        在<tomcat安装目录>\conf\web.xml文件中,注册了一个名称为org.apache.catalina.servlets.DefaulServlet的Servlet,并将这个Servlet设置为了缺省Servlet。当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet。
        假设现在在工程名为test的WebRoot目录下新建一个1.html,在web.xml文件中并没有配置<servlet-mapping>,即在工程中没有Servlet映射成1.html,然后访问:http://localhost:8080/test/1.html时,这时候这个请求就交给缺省的Servlet,缺省的Servlet收到请求后,会首先看一下web应用下面有没有这个1.html,如果有则读取并返回到浏览器,如果没有则返回一个错误页面。

6. servlet细节6

当多个客户端并发访问同一个Servlet时,web服务器会为每一个客户端的访问请求创建一个线程,并在这个线程上调用Servlet的service方法,因为Servlet只有一个实例化对象,因此service方法内如果访问了同一个资源的话,就有可能引发线程安全问题。那么如何解决Servlet中的线程安全问题呢?
       1) 如果某个Servlet实现了SingleThreadModel接口,那么Servlet引擎将以单线程模式来调用其service方法。该接口没有任何方法,它起到了一个标志的作用。对于实现了SingleThreadModel接口的Servlet,Servlet引擎仍然支持对该Servlet的多线成并发访问,其采用的方式是产生多个Servlet实例对象,并发的每个线程分别调用一个独立Servlet实例对象。

2)使用synchronized 关键字,synchronized能保证一次只有一个线程可以访问被保护的区段,从而可以通过同步块操作来保证线程的安全。

3)尽量避免在Servlet里使用实例变量,只要在Servlet里面的任何方法里面都不使用共有的实例变量,那么该Servlet就是线程安全的。

以上三种方式中,实现SingleThreadModel接口可以解决问题,但是并不是真正解决Servlet的线程安全问题,因为Servlet引擎会创建多个Servlet实例对象,而真正意义上解决多线程安全问题是指一个Servlet实例对象被多个线程同时调用的问题。另外,创建多个Servlet实例对象也会引起大量的开销。事实上,在Servlet API 2.4中,已经将SingleThreadModel标记为过时的了。

同样,如果在程序中使用同步来保护要使用的共享的数据,也会使系统的性能大大下降。这是因为被同步的代码块在同一时刻只能有一个线程执行它,使得其同时处理客户请求的吞吐量降低,而且很多客户处于阻塞状态。所以在实际的开发中也应避免或最小化 Servlet 中的同步代码。

所以,在Servlet中避免使用实例变量是保证Servlet线程安全的最佳选择。

3. Servlet的Hello Word

最后写一个再简单不过的Hello Word吧……

public class ServletDemo extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("Hello word!");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

web.xml:

<servlet>
<servlet-name>ServletDemo</servlet-name>
<servlet-class>servlet.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的更多相关文章

  1. Scrapy001-框架初窥

    Scrapy001-框架初窥 @(Spider)[POSTS] 1.Scrapy简介 Scrapy是一个应用于抓取.提取.处理.存储等网站数据的框架(类似Django). 应用: 数据挖掘 信息处理 ...

  2. 初窥Kaggle竞赛

    初窥Kaggle竞赛 原文地址: https://www.dataquest.io/mission/74/getting-started-with-kaggle 1: Kaggle竞赛 我们接下来将要 ...

  3. scrapy2_初窥Scrapy

    递归知识:oop,xpath,jsp,items,pipline等专业网络知识,初级水平并不是很scrapy,可以从简单模块自己写. 初窥Scrapy Scrapy是一个为了爬取网站数据,提取结构性数 ...

  4. WWDC15 Session笔记 - Xcode 7 UI 测试初窥

    https://onevcat.com/2015/09/ui-testing/ WWDC15 Session笔记 - Xcode 7 UI 测试初窥 Unit Test 在 iOS 开发中已经有足够多 ...

  5. Java发送邮件初窥

    一.背景 最近朋友的公司有用到这个功能,之前对这一块也不是很熟悉,就和他一起解决出现的异常的同时,也初窥一下使用Apache Common Email组件进行邮件发送. 二.Java发送邮件的注意事项 ...

  6. 【软件工程】week5-个人作业-敏捷开发方法初窥

    敏捷开发方法初窥 引言:本周的软件工程个人博客作业是阅读关于敏捷开发方法的文章(http://martinfowler.com/agile.html),并撰写自己的读后感.文章内容非常丰富,对敏捷开发 ...

  7. 网页3D效果库Three.js初窥

    网页3D效果库Three.js初窥 背景 一直想研究下web页面的3D效果,最后选择了一个比较的成熟的框架Three.js下手 ThreeJs官网 ThreeJs-github; 接下来我会陆续翻译 ...

  8. iOS视频直播初窥:高仿<喵播APP>

    视频直播初窥 视频直播,可以分为 采集,前处理,编码,传输, 服务器处理,解码,渲染 采集: iOS系统因为软硬件种类不多, 硬件适配性比较好, 所以比较简单. 而Android端市面上机型众多, 要 ...

  9. php面向对象(一) 初窥

    初窥php面向对象 1.类:类就是属性和方法的集合 是一个抽象的概念比如生活中的“人”,"汽车"2.对象:对象是具体的事物 比如一叫“小强”的人 一辆叫“奥迪a7”的汽车3.类和对 ...

随机推荐

  1. python 666

    运行下面代码会输出什么? __builtins__.我们来运行下这行代码看看="666" #!/usr/bin/env python # encoding: utf-8 def _ ...

  2. python描述符的应用

    使用描述符为python实现类型检测 class Typed: def __get__(self, instance, owner): print(instance) print(owner) def ...

  3. jquery做一个表单验证

    正则表达式的写法: var re=new RegExp('规则', '可选参数');var re=/规则/参数;(这个最常用) 正则表达式的规则 和其他语言的正则表达式规则一样,可以参考我的另一边博文 ...

  4. AC日记——Roma and Poker codeforces 803e

    803E - Roma and Poker 思路: 赢或输或者平的序列: 赢和平的差的绝对值不得超过k: 结束时差的绝对值必须为k: 当“?”时可以自己决定为什么状态: 输出最终序列或者NO: dp( ...

  5. Guava源码学习(二)Ordering

    基于版本:Guava 22.0 Wiki:Ordering 0. Ordering简介 Guava的Ordering提供了链式风格的比较器的实现,我们可以用Ordering轻松构建复杂的比较器. 1. ...

  6. 中矿新生赛 H 璐神看岛屿【BFS/DFS求联通块/连通块区域在边界则此连通块无效】

    时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32768K,其他语言65536K64bit IO Format: %lld 题目描述 璐神现在有张n*m大小的地图,地图上标明了陆地(用 ...

  7. AppScan 浏览器兼容解决

    手动探索的时候,因为打开的浏览器是appscan自带的,可能会存在兼容性问题,有些页面无法正常打开.那么是否可以用我们电脑上的浏览器(IE .火狐.谷歌)来进行录制 菜单栏--工具---选项----首 ...

  8. JSK 11: 移除数组中的重复元素

    题目描述 给定一个升序排列的数组,去掉重复的数,并输出新的数组的长度. 例如:数组 $A = \{1, 1, 2\}$,你的程序应该输出 $2$ 即新数组的长度,新数组为 $\{1, 2\}$. 要求 ...

  9. vue.js 微信浏览器不支持lambda表达式

    最近尝试在用vue重构一个微信网页,然后发现在本地测试是可以的,在微信测试工具里也是正常的,然后在手机里有人正常有人不正常,后来发现规律,微信比较新的是不支持的,微信比较旧的是不支持的.然后网上谷歌了 ...

  10. iOS:UICollectionView纯自定义的布局:堆叠式布局、圆式布局 (一般用来制作相册)

    集合视图的自动布局:UICollectionViewLayout是抽象根类,必须用它的子类才能创建实例,下面是重写的方法,计算item的布局属性 //每一次重新布局前,都会准备布局(苹果官方推荐使用该 ...