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请求的时候,遵守的一种规范. 其实就是规定了客户端在访问服务器端的时候,要带上哪些东西, 服务器端返回数据的时候,也要带上什么东西. 版本 ...
随机推荐
- 从源代码制作iDempiere Server安装软件(Ubuntu Desktop 12.04 LTS 64位)
怀揣着为中小企业量身定做一整套开源软件解决方案的梦想开始了一个网站的搭建.http://osssme.org/ 在Eclipse中寻找org.adempiere.server-feature项目 右击 ...
- 重写kinect2_viewer,编译高博kinect2在orbslam2上跑的程序(解决cmakefile中库依赖和头文件的问题)
该方法详述了高博kinect2_viewer的编译过程 //...................................................................... ...
- c++ abs与fabs
在stdlib.h中定义的abs只针对整数取决对值,如果要对浮点数取绝对值,应该用fabs(或fabsf). 而math.h中定义的abs是可以对浮点数取绝对值的. 所以如果包含了stdlib.h和m ...
- 点滴积累【other】---存储过程删除所有表中的数据(sql)
USE [QG_Mis24] GO /****** Object: StoredProcedure [dbo].[p_set1] Script Date: 07/18/2013 13:25:57 ** ...
- [elk]logstash的最佳实战-项目实战
重点参考: http://blog.csdn.net/qq1032355091/article/details/52953837 不得不说这是一个伟大的项目实战,是正式踏入logstash门槛的捷径 ...
- [na]台式机装原版Win2008R2
坑了老半天,总结出几点 1,系统os下载: http://msdn.itellyou.cn/ 注:其他地方下载的,装后发现不是起不来就是驱动装不了. 2,u盘里放个压缩软件: 好呀压缩 和 浏览 ...
- PHP QR Code - QR code generator, an LGPL PHP library
http://phpqrcode.sourceforge.net/examples/index.php http://phpqrcode.sourceforge.net/examples/index. ...
- 使用 xlue 实现 tips
经常遇到如下的需求 鼠标hover到目标对象一定时间后,弹出tips或者窗口; 鼠标离开目标对象一定时间后,隐藏tips或者窗口; 鼠标从目标对象移动到弹出的窗口上,这种状况下不隐藏窗口; 考虑到这种 ...
- Selenium操作之滚动条
在用Selenium做UI自动化时,经常会遇到有些元素找不到之类的问题,但是自己的代码并没有错,元素就是找不到,这是为什么呢?原因很简单,由于页面内容较多,有些内容需要下拉滚动条才会显示,这里介绍一种 ...
- Windows调试神器:WinDBG
Q:WinDBG的Watch窗口中我想要查看长字符串,但是后面的内容都被省略为...了怎么办? A:如图,双击你要查看的内容,出现光标后,移动光标即可查看后面被省略的内容 Q:WinDBG如何给程序设 ...