servlet
Servlet是Server与Applet的缩写,是服务端小程序的意思。是SUN公司提供的一门用于开发动态Web资源的技术。
servlet首先是一个协议,主要用于满足java的web后端处理的协议
servlet也是java自带的类库,是对servlet协议的实现
servlet也指使用上面servlet类库实现的servlet程序
servlet程序是没有主函数中,不能单独运行,所以必须运行在servlet容器中,常用的servlet容器有tomcat,jetty和jboss等等。servlet容器又叫做servlet引擎。
Apache官方对各版本的解释:http://tomcat.apache.org/whichversion.html
https://www.cnblogs.com/whgk/p/6399262.html
1、servlet的生命周期是什么?
服务器启动时(web.xml中配置load-on-startup=1,默认为0)或者第一次请求该servlet时,就会初始化一个Servlet对象,也就是会执行初始化方法init(ServletConfig conf)
该servlet对象去处理所有客户端请求,在service(ServletRequest req,ServletResponse res)方法中执行
最后服务器关闭时,才会销毁这个servlet对象,执行destroy()方法。
2、为什么创建的servlet是继承自httpServlet,而不是直接实现Servlet接口?
3、servlet的生命周期中,可以看出,执行的是service方法,为什么我们就只需要写doGet和doPost方法呢?
查看源码,httpServlet的继承结构。
httpServlet继承GenericServlet。懂的人立马就应该知道,GenericServlet(通用Servlet)的作用是什么?大概的就是将实现Servlet接口的方法,简化编写servlet的步骤。具体下面详解
GenericServlet的继承结构,实现了Servlet接口和ServletConfig接口,
Servlet接口内容
从这里可以看到,Servlet生命周期的三个关键方法,init、service、destroy。还有另外两个方法,一个getServletConfig()方法来获取ServletConfig对象,ServletConfig对象可以获取到Servlet的一些信息,ServletName、ServletContext、InitParameter、InitParameterNames、通过查看ServletConfig这个接口就可以知道
ServletConfig接口内容
其中ServletContext对象是servlet上下文对象,功能有很多,获得了ServletContext对象,就能获取大部分我们需要的信息,比如获取servlet的路径,等方法。
到此,就知道了Servlet接口中的内容和作用,总结起来就是,三个生命周期运行的方法,获取ServletConfig,而通过ServletConfig又可以获取到ServletContext。而GenericServlet实现了Servlet接口后,也就说明我们可以直接继承GenericServlet,就可以使用上面我们所介绍Servlet接口中的那几个方法了,能拿到ServletConfig,也可以拿到ServletContext,不过那样太麻烦,不能直接获取ServletContext,所以GenericServlet除了实现Servlet接口外,还实现了ServletConfig接口,那样,就可以直接获取ServletContext了。
GenericServlet类的内容详解
看上图,用红色框框起来的就是实现Servlet和ServletConfig接口所实现的方法,有9个,这很正常,但是我们可以发现,init方法有两个,一个是带有参数ServletConfig的,一个有无参的方法,为什么这样设计?这里需要知道其中做了什么事情,来看看这两个方法分别做了什么事?
init(ServletConfig config)
init()
一个成员变量config
getServletConfig()
通过这几个方法一起来讲解,首先看init(ServletConfig config)方法,因为只有init(ServletConfig config)中带有ServletConfig对象,为了方便能够在其他地方也能直接使用ServletConfig对象,而不仅仅局限在init(ServletConfig config)方法中,所以创建一个私有的成员变量config,在init(ServletConfig config)方法中就将其赋值给config,然后通过getServletConfig()方法就能够获取ServletConfig对象了,这个可以理解,但是在init(ServletConfig config)中,158行,还调用了一个init()方法,并且这个init()方法是空的,什么读没有,这是为什么呢?这个原因是为了防止一件事情,当我们需要在init方法中做一点别的事情,我们想到的方法就是继承GenericServlet并且重写了init(ServletConfig config)方法,这样依赖,就破坏了原本在GenericServlet类中init(ServletConfig config)写的代码了,也就是在GenericServlet类中的成员变量config会一直是null,无法得到赋值,因为被重写了,就不会在执行GenericServlet中init(ServletConfig config)方法中的代码。要想赋值,就必须在重写的init(ServletConfig config)方法中调用父类的init(ServletConfig config)方法,也就是super.init(ServletConfig config),这样一来,就很不方便,怕有时候会忘了写这句代码,所以在GenericServlet类中增加一个init()方法,以后需要在init方法中需要初始化别的数据,只需要重写init()这个方法,而不需要去覆盖init(ServletConfig config)这个方法,这样设计,就好很多,不用在管init(ServletConfig config)这个其中的内容了。也不用出现其他的问题。
service(ServletRequest req, ServletResponse res)
一个抽象方法,说明在GenericServlet类中并没有实现该内容,那么我们想到的是,在它上面肯定还有一层,也就是还有一个子类继承它,实现该方法,要是让我们自己写的Servlet继承GenericServlet,需要自己写service方法,那岂不是累死,并且我们可以看到,service方法中的参数还是ServletRequest,ServletResponse。并没有跟http相关对象挂钩,所以我们接着往下面看。
HttpServlet类详解
继承了GenericServlet类,通过我们上面的推测,这个类主要的功能肯定是实现service方法的各种细节和设计。并且通过类名可以知道,该类就跟http挂钩了。
关注service(HttpServletRequest req, HttpServletResponse resp)方法和service(ServletRequest req, ServletResponse res)方法。
service(ServletRequest req, ServletResponse res)方法
该方法中就做一件事情,就是将ServletRequest和ServletResponse这两个对象强转为HttpServletRequest和HttpServletResponse对象。为什么能这样转?
首先要知道req、res是什么类型,通过打印System.out.println(req),可以知道,req实际上的类型是org.apache.catalina.connector.RequestFacade Tomcat中的源码。
通过图可以得知,req的继承结构:RequestFacade、httpServletRequest、ServletRequest,我们知道本身req是ServletRequest,那么从继承结构上看,它也可以看成HttpServletRequest,也可以看成ServletRequest,所以强转为HttpServletRequest是可以的,如果不明白,我举个例子,ArrayList、List、Object 这个,Object obj = new ArrayList(); List list = new ArrayList(); 一个ArrayList对象可以看成List对象, 也可以看成一个Object对象,现在obj是不是可以堪称List对象呢?答案是可以的,因为obj就是ArrayList对象,既然是ArrayList对象,那么就可以看成是List对象。一样的道理,RequestFacade 对应 ArrayList、httpServleRequest对应 List、 ServletRequest 对应 Object。
转换为httpServletRequest和HttpServletResponse对象之后,在调用service(HttpServletRequest req, HttpServletResponse resp)方法。
service(HttpServletRequest req, HttpServletResponse resp)
这个方法就是判断浏览器过来的请求方式是哪种,每种的处理方式不一样,我们常用的就是get,post,并且,我们处理的方式可能有很多的内容,所以,在该方法内会将get,post等其他5种请求方式提取出来,变成单个的方法,然后我们需要编写servlet时,就可以直接重写doGet或者doPost方法就行了,而不是重写service方法,更加有针对性。所以这里就回到了我们上面编写servlet时的情况,继承httpServlet,而只要重写两个方法,一个doGet,一个doPost,其实就是service方法会调用这两个方法中的一个(看请求方式)。所以也就解答了我们一开始提的问题3。
http://www.cnblogs.com/xdp-gacl/p/3763559.html
ServletConfig:作用是获取初始和上下文参数,用于有状态请求和线程共享数据
ServletContext:功能:tomcat为每个web项目都创建一个ServletContext实例,tomcat在启动时创建,服务器关闭时销毁,在一个web项目中共享数据,管理web项目资源,为整个web配置公共信息等,通俗点讲,就是一个web项目,就存在一个ServletContext实例,每个Servlet请求读可以访问到它。
http://www.cnblogs.com/rocomp/p/4814765.html
Cookie&Session
Tomcat
学习Servlet技术,就需要有一个Servlet运行环境,也就是需要有一个Servlet容器,本文用的是Tomcat。
Tomcat是一个免费的开放源代码的Servlet容器,它是Apache软件基金会(Apache Software Foundation)的一个顶级项目,由Apache、Sun和其他一些公司及个人共同开发而成。由于有了Sun的参与和支持,最新的Servlet和 JSP规范总是能在Tomcat中得到体现,Tomcat 6支持最新的Servlet 2.5和JSP 2.1规范。因为Tomcat技术先进、性能稳定,而且免费,因而深受Java爱好者的喜爱,并得到了部分软件开发商的认可,成为目前比较流行的Web服 务器。
Tomcat和IIS、Apache等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的 Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态HTML的能力不如Apache,我们可以将Apache和Tomcat集成在 一起使用,Apache作为HTTP Web服务器,Tomcat作为Web容器。
Tomcat服务器接受客户请求并做出响应的过程如下:
1)客户端(通常都是浏览器)访问Web服务器,发送HTTP请求。
2)Web服务器接收到请求后,传递给Servlet容器。
3)Servlet容器加载Servlet,产生Servlet实例后,向其传递表示请求和响应的对象。
4)Servlet实例使用请求对象得到客户端的请求信息,然后进行相应的处理。
5)Servlet实例将处理结果通过响应对象发送回客户端,容器负责确保响应正确送出,同时将控制返回给Web服务器。
Tomcat的体系结构
Tomcat服务器是由一系列可配置的组件构成的,其中核心组件是Catalina Servlet容器,它是所有其他Tomcat组件的顶层容器。我们可以通过查看Tomcat安装文件夹下的conf文件夹中的server.xml文件 来了解Tomcat各组件之间的层次关系。由于server.xml注释太多,特简化如下:
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/>
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost">
<Context path="" docBase="WORKDIR" reloadable="true"/>
</Host>
</Engine>
</Service>
</Server>
其中WORKDIR为你想要导入的项目路径。我们下面简单介绍一下各组件在Tomcat服务器中的作用。
(1)Server
Server表示整个的Catalina Servlet容器。Tomcat提供了Server接口的一个默认实现,这通常不需要用户自己去实现。在Server容器中,可以包含一个或多个Service组件。
(2)Service
Service是存活在Server内部的中间组件,它将一个或多个连接器(Connector)组件绑定到一个单独的引擎(Engine)上。在Server中,可以包含一个或多个Service组件。Service也很少由用户定制,Tomcat提供了Service接口的默认实现,而这种实现既简单又能满足应用。
(3)Connector
连接器(Connector)处理与客户端的通信,它负责接收客户请求,以及向客户返回响应结果。在Tomcat中,有多个连接器可以使用。
(4)Engine
在Tomcat中,每个Service只能包含一个Servlet引擎(Engine)。引擎表示一个特定的Service的请求处理流水线。作为一个Service可以有多个连接器,引擎从连接器接收和处理所有的请求,将响应返回给适合的连接器,通过连接器传输给用户。用户允许通过实现Engine接口提供自定义的引擎,但通常不需要这么做。
(5)Host
Host表示一个虚拟主机,一个引擎可以包含多个Host。用户通常不需要创建自定义的Host,因为Tomcat给出的Host接口的实现(类StandardHost)提供了重要的附加功能。
(6)Context
一个Context表示了一个Web应用程序,运行在特定的虚拟主机中。什么是Web应用程序呢?在Sun公司发布的Java Servlet规范中,对Web应用程序做出了如下的定义:“一个Web应用程序是由一组Servlet、HTML页面、类,以及其他的资源组成的运行在Web服务器上的完整的应用程序。它可以在多个供应商提供的实现了Servlet规范的Web容器中运行”。一个Host可以包含多个Context(代表Web应用程序),每一个Context都有一个唯一的路径。用户通常不需要创建自定义的Context,因为Tomcat给出的Context接口的实现(类StandardContext)提供了重要的附加功能。
Servlet3.0提供了注解(annotation),使得不再需要在web.xml文件中进行Servlet的部署描述。