servlet之模板方法和多线程
接触了一小段时间的servlet,以下就总结一下关于servlet的两个方面的知识,一个是模板方法的应用。另外一个是servlet多线程产生的原因。
1. 模板方法设计模式
定义一个操作中的算法的骨架。而将步骤延迟到子类中。
模板方法使得子类能够不改变一个算法的结构就可以重定义算法的某些特定步骤。
2. Servlet中模板方法的应用
模板方法在servlet中的应用的类图
当client请求一个servlet的时候首先被调用的是service方法。Service方法就是定义骨架的方法,在service方法中会依据HTTP请求的类型(GET,POST还是其它)来调用详细的doGet和doPost等方法;即实际的处理委派给了doGet和doPost等方法。这些子类的方法来终于处理浏览器的请求。以下是HttpServlet对service方法的详细实现。
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String method = req.getMethod(); if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
} } else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp); } else if (method.equals(METHOD_POST)) {
doPost(req, resp); } else if (method.equals(METHOD_PUT)) {
doPut(req, resp); } else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp); } else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
// String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
3. servlet并非严格的依照模板方法来设计的
我们常说详细问题详细分析。在这里也是。servlet 讲模板方法的精髓应用到了,可是却没有全然依照模板方法设计。
3.1 子类能够重写service()方法
模板方法模式是通过把不变的行为搬移到超类。去除了子类中的反复代码。所以超类中的模板方法普通情况下是不会被重写的。模板方法同意子类又一次定义算法的某些 步骤。而不改变算法的结构。可是在servlet中的service方法中是能够被子类重写的。当子类重写了service方法之后就破坏掉了原本定义好的模板方法。
3.2 doGet和doPost方法有默认的实现
在HttpServlet类中对于这两个被子类详细实现的方式是有实现的。
以下是HttpServlet对于这两个实现的代码
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_post_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_get_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
这些说明在使用设计模式的时候并非生搬硬套,而是依据详细的情况灵活变动。可是其本质是不变的。
4. 为什么会出现线程安全问题
在学习servlet过程中一直听到的一个问题就是线程问题。学习的资料中提到servlet是多线程。不安全的。
servlet是由web容器管理的,当请求这个servlet的时候。web容器会依据web.xml中的配置实例化这个servlet。
当再次请求这个servlet的时候不会再实例化此servlet而是多线程的使用第一次请求的时候实例化的servlet。也就是一个servlet仅仅实例化一次。
当面对多个请求的时候web容器就会使用多线程来处理这些请求。
以下的图形是servlet多线程的结构图形
从图中能够看出,当容器收到一个请求servlet的请求的时候会从线程池中分出一个工作线程来处理这个请求,当有另外一个请求的时候会从线程池中分出另外一个工作线程来处理这个请求。所以假设多个用户同一时候请求同一个servlet,那么在容器中就会出现一个servlet对象的service方法并发运行。多线程是共享资源的,当他们并发运行的时候就非常有可能出现訪问资源冲突问题。
这样的处理请求的方式就是我们常常说的单实例多线程的处理方式。
以下是自己查找到的一个作者:http://blog.csdn.net/zljjava/article/details/6887266从内存的角度来分析的servlet的多线程问题。
假设有兴趣的话能够看看。
从内存中看一下这个问题能够总结以下的两种图形。当中一张是我们都知道JMM模型图
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveV9sb3ZlX2Y=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
另外一张是多个用户请求同一个servlet的多线程运行的过程是:
主内存中的实例变量是在多个线程之间共享的。每一个线程在自己的工作线程中拷贝自己须要的实例变量到自己的缓存中。就如同上面图形中的A,当线程1改动了A,可是线程2中的A还是主存中的样子,并没有立即同步到线程2和线程3中就会出现线程安全问题。
5. 总结
对于servlet的单实例多线程问题知道的原因就能够对症下药的找解决方式了。
主要是针对变量要注意。对于模板方法能够看到我们的应用非常多可是也要注意活学活用。
servlet之模板方法和多线程的更多相关文章
- Spring MVC:DispatchServlet类
Spring MVC架构 Spring Web MVC是基于Servlet API构建的原始Web框架,从一开始就已包含在Spring框架中.传统的模型层被拆分为了业务层(Service)和数据访问层 ...
- Servlet 单例多线程
Servlet如何处理多个请求访问? Servlet容器默认是采用单实例多线程的方式处理多个请求的: 1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在 ...
- Servlet单实例多线程模式
http://kakajw.iteye.com/blog/920839 前言:Servlet/JSP技术和ASP.PHP等相比,由于其多线程运行而具有很高的执行效率.由于Servlet/JSP默认是以 ...
- servlet单例多线程
Servlet如何处理多个请求访问? Servlet容器默认是采用单实例多线程的方式处理多个请求的: 1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在 ...
- 对于多线程下Servlet以及Session的一些理解
今天,小伙伴突然问到了Servlet是不是线程安全的问题.脑子当时一卡壳,只想到了单实例多线程.这里做一些总结. Servlet体系是建立在Java多线程的基础之上的,它的生命周期是由Tomcat来维 ...
- Servlet 单例多线程【转】
源地址:Servlet 单例多线程 Servlet如何处理多个请求访问?Servlet容器默认是采用单实例多线程的方式处理多个请求的:1.当web服务器启动的时候(或客户端发送请求到服务器时),Ser ...
- [转]Servlet 单例多线程
Servlet如何处理多个请求访问? Servlet容器默认是采用单实例多线程的方式处理多个请求的: 1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在 ...
- Servlet 单例多线程详解(六)
一.Servlet 单例多线程 Servlet如何处理多个请求访问?Servlet容器默认是采用单实例多线程的方式处理多个请求的:1.当web服务器启动的时候(或客户端发送请求到服务器时),Servl ...
- Http协议&Servlet
http协议 针对网络上的客户端 与 服务器端在执行http请求的时候,遵守的一种规范. 其实就是规定了客户端在访问服务器端的时候,要带上哪些东西, 服务器端返回数据的时候,也要带上什么东西. 版本 ...
随机推荐
- 伪分布模式安装hadoop
准备工具: 虚拟机:VMware Linux系统:CentOS hadoop-1.1.2.tar.gz jdk-7u75-linux-x64.gz CentOS的网络配置 1.设置主机中VMware ...
- 反射机制2,Class类的使用
class是反射源头,不光可以取得对象所在类信息,也可直接通过class类的方法进行对象的实例化操作. 使用关键字new为对象实例化.如果已经实例化好了class对象,就可以通过class类中提供的n ...
- zabbix_get :command not found 解决办法
zabbix_get 找不到命令是因为没有安装上zabbix_get ,解决办法: 1.yum list all |grep zabbix 返回一个列表,表中出现 zabbix-get.x86_84 ...
- CentOS7 升级到7.4
2 升级CentOS7.4 自己电脑上的系统还是CentOS7.2,服务器是CentOS7.3, 打算统统升级到最新版 升级前查看 > lsb_release -a LSB Version: : ...
- C语言-常用函数处理
1.使用fgets #define SLEN 50 char str[SLEN]; fgets(str, SLEN, stdin); i = ; while (str[i] != '\n' & ...
- Python 使用 UTF-8 编码(转)
Python 使用 UTF-8 编码(转) 原文出处:http://blog.chenlb.com/2010/01/python-use-utf-8.html 一般我喜欢用 utf-8 编码,在 py ...
- jms、amqp、mqtt区别与联系
消息传递作为基本通信机制已经在全世界成功运用.无论是人与人.机器与人还是机器与机器之间,消息传递一直都是唯一常用的通信方式.在双方(或更多)之间交换消息有两种基本机制. 同步消息传递 异步消息传递 同 ...
- json再理解
一.Json的简单介绍 从结构上看,所有的数据最终都可以分成三种类型: 第一种类型是scalar(标量),也就是一个单独的string(字符串)或数字(numbers),比如“北京”这个单独的词. 第 ...
- Python 统计代码的行数,Python脚本 统计代码
# coding=utf-8 import os import time # 需要统计的文件夹或者文件,这是在windows下运行的,如果使用Linux系统可以使用 basedir = '/app/l ...
- Mysql的replace into语句
Mysql语句 replace into 跟 insert 功能类似,不同点在于:replace into 首先尝试插入数据到表中, 1. 如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删 ...