Java与.NET机制比较分析
一、概述
不管是什么语言开发的web应用程序,都是在解决一个问题,那就是用户输入url怎么把对应的页面响应出来,如何通过url映射到响应的类,由于自己做asp.net的时间也不短了,还算是对asp.net的整个流程还算是了解,所以在自学JavaWeb的时候也很好奇JavaWeb中是如何处理的。
二、asp.net的工作原理
下面的对asp.net的工作流程的介绍(红字)以及我个人的理解。这里也给学asp.net的推荐一本书<<asp.net本质论>>,这本书对http请求流程讲的比较详细,也是一本挺不错的书。
以IIS 6.0为例,在工作进程w3wp.exe中,利用Aspnet_ispai.dll加载.NET运行时(如果.NET运行时尚未加载)。IIS 6引入了应用程序池的概念,一个工作进程对应着一个应用程序池。一个应用程序池可以承载一个或者多个Web应用,每个Web应用映射到一个IIS虚拟目录。与IIS 5.x一样,每一个Web应用运行在各自的应用程序域中。
下图是我本地电脑的IIS应用程序池列表。
上图红线部分也显示的很清楚,应用程序池与工作进程相关联,包含一个或多个应用程序,并提供不同应用之间的隔离。在我本地Test应用池中就有2个应用。具体创建可以参考Nginx负载均衡篇http://www.cnblogs.com/5ishare/p/6129775.html.
如果HTTP.SYS接收到的HTTP请求是对该Web应用的第一次访问,当成功加载了运行时后,会通过AppDomainFactory为该Web应用创建一个应用程序域(AppDomain)。随后,一个特殊的运行时IsapiRuntime被加载。IsapiRuntime定义在程序集System.Web中,对应的命名空间为System.Web.Hosting。IsapiRuntime会接管该HTTP请求。
这里的应用程序域提供了四个重要的机制。
1.隔离 不同应用程序域直接不能直接访问
2.卸载 被加载的应用程序集只能以应用程序域为单位来卸载
3.安全 以应用程序域为边界的安全机制
4.配置 以应用程序域为边界的配置
IsapiRuntime会首先创建一个IsapiWorkerRequest对象,用于封装当前的HTTP请求,并将该IsapiWorkerRequest对象传递给ASP.NET运行时:HttpRuntime,从此时起,HTTP请求正式进入了ASP.NET管道。根据IsapiWorkerRequest对象,HttpRuntime会创建用于表示当前HTTP请求的上下文(Context)对象:HttpContext。
IsapiWorkerRequest是比较底层的对象,HttpRuntime接到请求之后会将其分析拆解,创建HttpRequest、HttpResponse对象,一次Http请求需要好几个对象,还有HttpServerUtility类型的对象处理网站虚拟路径和服务器文件系统之间的映射关系,为了管理这些对象,定义了HttpContext来统一处理参数的表示问题。
随着HttpContext被成功创建,HttpRuntime会利用HttpApplicationFactory创建新的或者获取现有的HttpApplication对象。实际上,ASP.NET维护着一个HttpApplication对象池,HttpApplicationFactory从池中选取可用的HttpApplication用户处理HTTP请求,处理完毕后将其释放到对象池中。HttpApplicationFactory负责处理当前的HTTP请求。HttpRuntime创建HttpContext成功之后,会创建HttpApplication对象,需要注意的是HttpApplication对象创建的来源,一是通过HttpApplicationFactory创建一种是HttpApplication对象池获取,它和Java Web中可不太一样。JavaWeb中的Servlet是单例多线程,通过Servlet对象只创建一个,通过线程池来响应请求。
在HttpApplication初始化过程中,会根据配置文件加载并初始化相应的HttpModule对象。对于HttpApplication来说,在它处理HTTP请求的不同的阶段会触发不同的事件(Event),而HttpModule的意义在于通过注册HttpApplication的相应的事件,将所需的操作注入整个HTTP请求的处理流程。ASP.NET的很多功能,比如身份验证、授权、缓存等,都是通过相应的HttpModule实现的。
当请求转入ASP.NET管道后,最终负责处理该请求的是与请求资源类型相匹配的HttpHandler对象,但是在Handler正式工作之前,ASP.NET会先加载并初始化所有配置的HttpModule对象。HttpModule在初始化的过程中,会将一些功能注册到HttpApplication相应的事件中,那么在HttpApplication整个请求处理生命周期中的某个阶段,相应的事件会被触发,通过HttpModule注册的事件处理程序也得以执行。所有的HttpModule都实现了IHttpModule接口。
这里的HttpModule起到了过滤的功能,这就和JavaWeb的Filter有点类型,利用它们可以做一些例如权限等一些处理。这种设计的好处也很明显,扩展性很强,用户可以自己选择使用。
而最终完成对HTTP请求的处理实现在另一个重要的对象中:HttpHandler。对于不同的资源类型,具有不同的HttpHandler。比如.aspx页对应的HttpHandler为System.Web.UI.Page,WCF的.svc文件对应的HttpHandler为System.ServiceModel.Activation.HttpHandler。
HttpHander有点类似JavaWeb的Servlet,最终处理还是需要它们,而且都是web的基础,JavaWeb中jsp最终还是会以Servlet对象来运行,asp.net中也是一样。
三、JavaWeb的工作流程
上面asp.net主要是关于池子的问题,下面JavaWeb主要是关于容器的问题。
Tomcat 的容器分为四个等级,真正管理 Servlet 的容器是 Context 容器,一个 Context 对应一个 Web 工程。这里有点类似asp.net的应用程序域。
一个 Web 应用对应一个 Context 容器,也就是 Servlet 运行时的 Servlet 容器,添加一个 Web 应用时将会创建一个 StandardContext 容器,并且给这个 Context 容器设置必要的参数。最重要的一个配置是 ContextConfig,这个类将会负责整个 Web 应用配置的解析工作,最后将这个 Context 容器加到父容器 Host 中。
1.其实我们在用eclipse将工程添加到tomcat服务器的过程就是在执行上面的工作。注意下面红线的部分,If server is started,publish changes immediately.服务器启动时,对Context 容器做的改变会立刻发布。能做到立刻发布,主要是靠观察者设计模式的Listener。ContextConfig 继承了 LifecycleListener 接口,所以对ContextConfig的修改也会立刻生效。
2.ContextConfig对象
关于ContextConfig对象,我们可以逆向的思考,我们创建一个Servlet类的同时需要在web.xml中进行配置servlet-name、servlet-calss、servlet-mapping、init-param,那Context容器又是怎么知道它们的对应关系和初始化参数呢?于是ContextConfig出现了。找到了这么多的初始化参数和映射关系,通过这些参数和映射将Servlet、Filter、Listener放入容器中,
3.Servlet实例化、初始化
上面虽然通过ContextConfig将Servlet各个初始化属性添加到Context容器中,但并没有将Servlet进行实例化初始化,所以还是不能使用。如果 Servlet 的 load-on-startup 配置项大于 0,那么在 Context 容器启动的时候就会被实例化。而实例化就要找到对应的类,对于jsp文件实质也是Servlet,servletClass 就是 conf/web.xml 中定义的 org.apache.jasper.servlet.JspServlet。而Servlet对象只会创建、初始化一次,如果有多个请求同时访问,会从线程池中获取一个线程还是用这个Servlet对象处理用户请求,算是单例多线程,这就会带来一个问题,线程安全问题,访问特别是修改Servlet类中的全局变量时会导致数据错误,所以尽量不使用在Servlet类中声明全局变量。实在不行就需要给线程加锁。
4.Servlet的生命周期
生命周期这个词在开发中很常见,Servlet也不例外。
Servlet 生命周期:Servlet 加载--->实例化(init())--->服务(Service())--->销毁(destroy())。
加载和实例化已在tomcat启动的时候完成,当客户端发起请求,Servlet是调用service()方法对请求进行响应的,service()方法中对请求的方式进行了匹配,选择调用doGet,doPost等这些方法,然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应.
destroy(): 仅执行一次,在服务器端停止且卸载Servlet时执行该方法。当Servlet对象退出生命周期时,负责释放占用的资源。一个Servlet在运行service()方法时可能会产生其他的线程,因此需要确认在调用destroy()方法时,这些线程已经终止或完成.
5.Servlet的继承关系
我们创建的每一次Servlet都是继承abstract HttpServlet,而HttpServlet 又继承了javax.servlet.GenericServlet。GenericServlet是一个通用的,不特定于任何协议的Servlet,它实现了Servlet接口.
Servlet接口和GenericServlet是不特定于任何协议的,而HttpServlet是特定于HTTP协议的类,所以HttpServlet中实现了service()方法,并将请求ServletRequest、ServletResponse 强转为HttpRequest 和 HttpResponse。
Java与.NET机制比较分析的更多相关文章
- Java虚拟机类加载机制——案例分析
转载: Java虚拟机类加载机制--案例分析 在<Java虚拟机类加载机制>一文中详细阐述了类加载的过程,并举了几个例子进行了简要分析,在文章的最后留了一个悬念给各位,这里来揭开这个悬 ...
- 【转载】Java虚拟机类加载机制与案例分析
出处:https://blog.csdn.net/u013256816/article/details/50829596 https://blog.csdn.net/u013256816/articl ...
- [转]Java虚拟机类加载机制
原文地址:http://blog.csdn.net/u013256816/article/details/50829596 看到这个题目,很多人会觉得我写我的java代码,至于类,JVM爱怎么加载就怎 ...
- Java 类反射机制分析
Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...
- Java 动态代理机制分析及扩展
Java 动态代理机制分析及扩展,第 1 部分 王 忠平, 软件工程师, IBM 何 平, 软件工程师, IBM 简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟 ...
- [转]Java 动态代理机制分析及扩展
引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执 ...
- 【JVM】深度分析Java的ClassLoader机制(源码级别)
原文:深度分析Java的ClassLoader机制(源码级别) 为了更好的理解类的加载机制,我们来深入研究一下ClassLoader和他的loadClass()方法. 源码分析 public abst ...
- Java 动态代理机制分析及扩展--转
http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/#icomments http://www.ibm.com/developerworks/c ...
- Java 动态代理机制分析及扩展,第 1 部分
Java 动态代理机制分析及扩展,第 1 部分 http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/ 本文通过分析 Java 动态代理的机制和特 ...
随机推荐
- centos关于vsftpd的配置、配置说明及常见问题
一.安装vsftpd 安装yum install -y vsftpd 开机启动 chkconfig vsftpd on 启动 service vsftpd start 加入防火墙 vi /etc/sy ...
- RxJava异步请求加载状态控制
在我看来,RxJava最大的特点就是异步,无论你是解析复杂的数据或是IO操作,我们都可以利用它内置的线程池进行线程间的调度,简单的使用 subscribeOn(Schedulers.io()).doO ...
- OOP Class具体解释
对象[编辑] 对象(Object)是类的实例.比如."狗"这个类列举狗的特点,从而使这个类定义了世界上全部的狗. 而莱丝这个对象则是一条详细的狗,它的属性也是详细的.狗有皮毛颜色. ...
- 算法笔记_096:蓝桥杯练习 算法提高 求最大值(Java)
目录 1 问题描述 2 解决方案 1 问题描述 问题描述 给n个有序整数对ai bi,你需要选择一些整数对 使得所有你选定的数的ai+bi的和最大.并且要求你选定的数对的ai之和非负,bi之和非负 ...
- es6 对象简化写法-函数
表达式还可以用于定义方法名. let obj = { ['h' + 'ello']() { return 'hi'; } }; obj.hello() // hi
- Google 收购 Android 十周年 全面解读Android现状
--訪传智播客Android学科教学总监传智·平一指 Android以前是一家创立于旧金山的公司的名字,该公司于2005年8月份被Google收购,并从此踏上了飞速发展的道路.经过十年的发展,它已经发 ...
- macOS中安装docker
如官方文档中所说: 1.点击进入boot2docker/osx-installer release页面. 2.在下载页面中点击 Boot2Docker-x.x.x.pkg 来下载 Boot2Docke ...
- 在DATASET中要是想添加进另一个表怎么办?
问:sql="select * from banzhu_manage ";adapter=new SqlDataAdapter(sql,banzhu_conn);adapter.F ...
- 基于leveldb,levigo做二次开发
Leveldb是一个C++库,它有提供标准的C接口,头文件在include/leveldb/c.h中 levigo是leveldb 的一个go wrapper,它主要基于Leveldb中inlude/ ...
- Oem7F7 通用完美激活v7.0绿色版 永久激活Windows7/2008
http://www.21andy.com/blog/20100906/1942.html