根据Servlet-API源码分析学习Servlet.docx

根据Servlet-API源码分析学习Servlet.docx

ID:31996108

大小:326.88 KB

页数:15页

时间:2019-01-30

上传者:U-1075
根据Servlet-API源码分析学习Servlet.docx_第1页
根据Servlet-API源码分析学习Servlet.docx_第2页
根据Servlet-API源码分析学习Servlet.docx_第3页
根据Servlet-API源码分析学习Servlet.docx_第4页
根据Servlet-API源码分析学习Servlet.docx_第5页
资源描述:

《根据Servlet-API源码分析学习Servlet.docx》由会员上传分享,免费在线阅读,更多相关内容在学术论文-天天文库

根据Servlet-API源码分析学习Servlet  Servlet  介于Servlet是JavaWeb开发的基础,因此好好看了一下Servlet3.0.1的源码,于是有了这篇记录。  Servlet和JSP是众多javaEE定义的技术当中的两种,其他还有JMS,EJB等等,运行JEE程序需要一个JEE容器,如GlassFish、JBOSS、WebLogic等,ServletJSP也可以部署在JEE容器中,不过用Servlet/JSP容器已经足够了,而且比JEE容器更加轻量化,Tomcat和Jetty不属于JEE容器,不能运行EJB或JMS。  ServletAPI概述  首先,下载Servlet-api源码,可以使用IDE,maven等方式,本文使用maven下载,命令如下(或者自行搜索下载源码):mavendependency:sources  servletAPI中有4个Java包,包括:  javax.servlet定义Servlet和Servlet容器之间的七月类和接口。  javax.servlet.http定义HTTPServlet与Serlvet容器之间的契约和接口  javax.servlet.annotation包含对Servlet、Filter和Listener进行标注的注解。还为标注元件指定元数据。  javax.servlet.descriptor包含为Web应用程序的配置星系提供编程式访问的类型。  javax.servlet包  不完整截图:   Servlet包中的主要成员:   Servlet接口是核心接口,是所有Serlvet都必须直接或间接实现的一个接口,Servlet接口定义了Servlet与Servlet容器之间的约定,总的来说就是Servlet容器会把Servlet类加载到内存中,并在Servlet实例中调用特定方法,在一个应用程序中,每个Servlet类型只能有一个实例。当用户的请求引发service方法,并给这个方法传入一个ServletRequest实例和一个ServletResponse实例。ServletRequest封装当前的HTTP请求,让开发者不必去解析和操作原始的HTTP数据,同理,ServletResponse表示当前用户的HTTP响应,它的作用是使得将响应回传给用户更容易。Servlet容器还为每个应用程序创建一个ServletContext实例。这个对象封装context(应用程序)的环境细节,而每个context只有一个ServletContext。每个Servlet实例还有一个封装Servlet配置信息的ServletConfig。  Servlet  下面先看看Servlet接口,(如果别人问你什么是Servlet,你可以告诉他,就是一个java接口,分分钟定义出来给你看,不过人们常说的Servlet应该是指任何实现了Servlet接口的类)看源码发现有234行(3.0.1版),仔细一看也就5个抽象方法,其他的全是注释,所以兄弟们,看源码不要虚,这就是传说中的和Servlet容器之间的约定(有没有很熟悉的感觉):  init第一次请求我们编写的Serlvet时,Servlet容器调用此方法,后续不在调用,可以利用这个方法做一些初始化的工作。在调用这个方法时,Servlet容器会传递一个ServletConfig。一般会将这个ServletConfig赋给一个类级变量,以方便其他方法也可以使用这个对象。  service每次用户请求service时,servlet容器都会调用这个方法,我们对请求的处理就是在这里完成的。  destroy要销毁Servlet时,Servlet容器就会调用这个方法,它通常发生在卸载应用程序,或者关闭Servlet容器的时候,这里一般我们会写一些资源清理相关的代码。  Servlet中另外另个费生命周期的方法:getServletInfo和getServletConfig  getServletInfo就是字面意思,返回Servlet的描述   getServletConfig这个方法返回由Servlet容器传给init方法的ServletConfig,上面说了,一般在init方法中将ServletConfig赋给一个类级变量,免得本方法返回null。  PS:由于Servlet是线程安全的,一个应用程序中所有的用户公用一个Servlet实例,因此不建议使用类级别的变量(只使用局部变量最好),除非是只读的或者java.utilconcurrent.atomic包中的成员。  Servlet基础应用程序  现在来写一个Servlet应用程序,写起来很简单,只要创建一个目录,并将Servlet类放在指定目录中就可以了,同时,如果要运行这个应用程序,你还需要安装一个Servlet容器,如Tomcat或者Jetty(安装方法自行搜索)。  编写Servlet应用  以上为Servlet的目录结构,要编译servlet,类路径中还要有servletAPI,tomcat容器中已经自带了servlet-api.jar。另外珍爱生命,还是用IDE来创建吧,博主试过,自己去一步一步创建配置虽说也可以,但是确实会花费不少时间,如果你就是要自己一步一步创建,觉得这样能学到更多东西,我只能说加油骚年!  应用程序中一般会有JSP、HTML、图像等其他资源,这些都应该放在应用程序的目录下面,并且经常放在子目录下,如上图,html放在html文件下,jsp放在jsp目录下。放在应用程序目录下的任何资源,用户可以通过资源的URL直接访问(放在应用程序目录下当然要可以访问了),如果希望某个资源可以被Servlet访问,但不能被用户访问,那就应该放在WEB-INF目录下(是不是找到该目录的作用了)。importjava.io.IOException;importjava.io.PrintWriter;importjavax.servlet.Servlet;importjavax.servlet.ServletConfig; importjavax.servlet.ServletException;importjavax.servlet.ServletRequest;importjavax.servlet.ServletResponse;importjavax.servlet.annotation.WebServlet;//name可选,提供servlet名,关键urlPatterns指定匹配当前servlet的模式@WebServlet(name="/FirstServlet",urlPatterns={"/myapp"})publicclassFirstServletimplementsServlet{privatetransientServletConfigconfig;@Overridepublicvoidinit(ServletConfigconfig)throwsServletException{//将config给类变量,扩大使用范围this.config=config;}@OverridepublicServletConfiggetServletConfig(){returnconfig;}@OverridepublicStringgetServletInfo(){return"MyServlet";} @Overridepublicvoidservice(ServletRequestrequest,ServletResponseresponse)throwsServletException,IOException{StringservletName=config.getServletName();response.setContentType("text/html");PrintWriterpw=response.getWriter();pw.write("hellofrom"+servletName);}@Overridepublicvoiddestroy(){}}  以上程序部署完成,启动Servlet容器,就可以通过url在浏览器中访问了:  通过访问http://localhost:8080/App01/FirstServlet  ServletRequest&ServletResponse  对于每一个HTTP请求,servlet容器会创建一个封装了HTTP请求的ServletRequest实例传递给servlet的service方法,ServletResponse则表示一个Servlet响应,其影藏了将响应发给浏览器的复杂性。通过ServletRequest的方法你可以获取一些请求相关的参数,而ServletResponse则可以将设置一些返回参数信息,并且设置返回内容。返回内容之前一般会调用setContentType方法设置响应的内容类型,如果没有设置,大多数浏览器会默认以html的形式响应,不过为了避免出问题,我们一般都设置该项。   值得注意的是ServletResponse中定义的getWriter方法,它返回可以将文本传给客户端的java.io.PrintWriter。在默认的情况下,PrintWriter对象使用ISO-8859-1编码,这有可能引起乱码。  以下为ServletRequest和ServletResponse的大部分方法:   ServletConfig  ServletConfig封装可以通过@WebServlet或者web.xml传给一个Servlet的配置信息,以这种方式传递的每一条信息都称做初始化信息,初始化信息就是一个个K-V键值对。为了从一个Servlet内部获取某个初始参数的值,init方法中调用ServletConfig的getinitParameter方法或getinitParameterNames方法获取,除此之外,还可以通过getServletContext获取ServletContext对象。方法签名:  通过WebServlet传递配置信息示例:   ServletContext  ServletContext是代表了Servlet应用程序。每个Web应用程序只有一个context。在分布式环境中,一个应用程序同时部署到多个容器中,并且每台Java虚拟机都有一个ServletContext对象。有了ServletContext对象后,就可以共享能通过应用程序的所有资源访问的信息,促进Web对象的动态注册,共享的信息通过一个内部Map中的对象保存在ServiceContext中来实现。保存在ServletContext中的对象称作属性。操作属性的方法:  GenericServlet  前面编写的Servlet应用中通过实现Servlet接口来编写Servlet,但是我们每次都必须为Servlet中的所有方法都提供实现,还需要将ServletConfig对象保存到一个类级别的变量中,GenericServlet抽象类就是为了为我们省略一些模板代码,实现了Servlet和ServletConfig,完成了一下几个工作:  将init方法中的ServletConfig赋给一个类级变量,使的可以通过getServletConfig来获取。publicvoidinit(ServletConfigconfig)throwsServletException{this.config=config;this.init();}  同时为避免覆盖init方法后在子类中必须调用super.init(servletConfig),GenericServlet还提供了一个不带参数的init方法,当ServletConfig赋值完成就会被第带参数的init方法调用。这样就可以通过覆盖不带参数的init方法编写初始化代码,而ServletConfig实例依然得以保存(这难道不是适配器模式吗?)   为Servlet接口中的所有方法提供默认实现。  提供方法来包装ServletConfig中的方法。  用GenericServlet实现Servlet应用importjava.io.IOException;importjava.io.PrintWriter;importjavax.servlet.GenericServlet;importjavax.servlet.ServletConfig;importjavax.servlet.ServletException;importjavax.servlet.ServletRequest;importjavax.servlet.ServletResponse;importjavax.servlet.annotation.WebInitParam;importjavax.servlet.annotation.WebServlet;@WebServlet(name="SecondServlet",urlPatterns={"/generic"},initParams={@WebInitParam(name="user",value="xiaobai"),@WebInitParam(name="email",value="xiaobai@example.com")})publicclassSecondServletextendsGenericServlet{@Override publicvoidservice(ServletRequestrequest,ServletResponseresponse)throwsServletException,IOException{ServletConfigconfig=getServletConfig();Stringuser=config.getInitParameter("user");Stringemail=config.getInitParameter("email");response.setContentType("text/html");PrintWriterpw=response.getWriter();pw.write("User:"+user+"
email:"+email);}}  HTTPServlet  在编写Servlet应用程序时,大多数都要用到HTTP,也就是说可以利用HTTP提供的特性,javax.servlet.http包含了编写Servlet应用程序的类和接口,其中很多覆盖了javax.servlet中的类型,我们自己在编写应用时大多时候也是继承的HttpServlet,以下为其中的重要成员:   从上图看,HttpServlet继承了GenericServlet,HttpServletRequest/Response继承了覆盖了ServletRequest/Response,成为了新的Servlet请求和响应的代表。在HttpServlet中覆盖了GenericServlet的service方法,并用新的Servlet请求和响应代表作为参数添加了一个service方法://覆盖GenereicServlet中的servicepublicvoidservice(ServletRequestreq,ServletResponseres)throwsServletException,IOException{HttpServletRequestrequest;HttpServletResponseresponse;if(!(reqinstanceofHttpServletRequest&&resinstanceofHttpServletResponse)){thrownewServletException("non-HTTPrequestorresponse");}request=(HttpServletRequest)req;response=(HttpServletResponse)res;service(request,response);}}//新service方法签名protectedvoidservice(HttpServletRequestreq,HttpServletResponseresp)  原始的service方法将请求和响应进行向下转换,分别为HttpServletRequest和HttpServletResponse,并调用新的service方法。看了下2.5版本中的实现,发现没有加以上代码是中的instanceof判断,恩,看来2.5中直接向下转型确实暴力了点,考虑容器不一定总是把请求当做HTTP请求,这样做看起来稳妥了些。新的service方法会查寻HTTP请求的方法从而调用do{Method}来处理请求。  总之HttpServlet中有两项特性是GenericServlet中没有的:  不覆盖service方法,而是覆盖doGet、doPost等。  用HttpServletRequestResponse替代ServletRequestResponse  HttpServletRequest,HttpServletResponse由于带有了HTTP的特性,因此除了ServletRequest,ServletResponse中的方法之外还增加了几个可以获取HTTP特性信息的方法。//获取context的请求URI部分 java.lang.StringgetContextPath()//获取Cookie对象数组Cookie[]getCookies()//返回指定HTTP标头的值java.lang.StringgetHeader(java.lang.Stringname)//返回发出这条请求的HTTP方法的名称java.lang.StringgetMethod()//返回请求URL中的查询字符串java.lang.StringgetQueryString()//获取session对象,没找到就新创建HttpSessiongetSession()//返回与这个请求相关的session对象,如果没有,并且create参数为true,创建新的session对象//响应对象添加cookievoidaddCookie(Cookiecookie)//添加标头voidaddheader(Stringname,Stringvalue)//重定向voidsendRedirect(Stringlocation)  使用web.xml配置Servlet应用  在Servlet3.x中可以使用@WebServlet来部署应用,可以不必在WEB-INF目录下放一个web.xml配置文件,当然也可以同时使用,前者优先级更高,这是annotation为我们带来的好处,介于使用web.xml来配置Servlet也有其有点,就简单介绍下,使用web.xml配置优点:  不用更改代码,也就意味着不需要重新编译   可包含@WebServlet中没有的元素,如load-on-startup元素,init方法比较费时间这个就很有帮助了。SimpleServletapp01.SimpleServlet2SimpleServlet/simple  附  现在再来看下我们我们通常写的Servlet,看完上文的客官,看到下面Servlet是不是感觉自己看到了更多的东西呢?反正我是看到了。讲真,如果想要缕下Servlet的话,真的可以试一试下载Servlet-api的源码看看,结合本文,或许风味更佳哦!!importjava.io.IOException;importjavax.servlet.ServletException;importjavax.servlet.annotation.WebServlet;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;@WebServlet("/normal") publicclassNormalServletextendsHttpServlet{privatestaticfinallongserialVersionUID=1L;protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{response.getWriter().append("Servedat:").append(request.getContextPath());}protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{doGet(request,response);}}  小结  Servlet技术是JavaEE技术的重要组成,Servlet容器中运行的所有Servlet,以及容器与Servlet之间的约定,都采用了javax.servlet.Servlet接口的形式。javax.servlet包也提供了实现Servlet接口的GenericServlet抽象类。这是一个比较方便的类,可以通过扩展它来创建Servlet。但是大多数的现代Servlet都在HTTP环境中处理请求,因此提供了javax.servlet.http.HttpServlet来继承GenericServlet并且加入HTTP特性。

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
关闭