servletServletConfigAndServletContext

来源:互联网 发布:上帝在掷骰子吗 知乎 编辑:程序博客网 时间:2024/06/05 16:20

一、   Servlet

Servlet开启了java的web系统开发的大门,它是在服务器上运行的小程序。Web的本质是数据,数据的意义在于连接和交互。Web系统不外乎两方,数据的使用方和数据的提供方或者托管方。使用方通过browser或者client请求数据,提供方或者托管方通过server响应来自使用方的数据请求提供服务。即,专业上称之为B/S结构和C/S结构。

作为提供方或者托管方,以下称之为服务方,首先本身需要一个存储数据的地方,使用数据库是一个好方法。显然,当使用方,以下称之为用户,有需求时,服务方不方便直接将数据库呈现给用户,让用户自己取用数据,这将是低效、不安全的。举一个例子,读者到图书馆借书,在读者不借助电脑查询设备的情况下,作为图书馆管理员,可以让读者直接进入图书室查找需要的书。假设如果图书室很庞大,那么读者查找图书将需要一定的时间,再假设,原本图书馆规定只能借一本书,但是读者突然很想多借几本,这时,他在图书室又没有人监督,可能出现一些意想不到的情况。那么,如果图书室管理员,对借用的过程加以控制,将实现读者需求的过程由内部人员,图书查找员实现,这将是高效和相对安全的。所以,控制实现请求的理念很容易就可以被构想和应用到web提供方的处理逻辑中。显然,在服务方需要一个控制的过程。而为了提高对数据库的操作效率,又需要一个可以装载数据库多个字段的东西。数据库由仓储库组成,每个仓储库由若干表组成,每个表由若干字段组成。比如,当客户需要所有商品信息时,从数据库取得某个商品表中所有字段的信息,然后直接每类字段每个数据提供给用户,实现起来将是不容易和不高效的。好比,码头上有一堆货物,其中有鞋,裤子,玩具,食物等等,而运输的船一次只能装一个东西,如果目的地的用户,需要一个鞋,一个裤子,一个玩具飞机,显然一次一次的送过去没有问题,但是,现实中一般会使用集装箱或者一个包装。虽然,在web服务端,数据的传输是很快的,但是如果数据量异常庞大、数据请求异常繁杂,那么,提高效率就必不可免,所以,对于数据库字段的处理或者对于用户的数据请求,可以采用类似现实中集装箱的方案加以优化,实际上,也是这样处理的,专业上称之为模型,一批一批的数据请求或者数据结果可以放到某种模型中传输处理。对于数据的请求和请求的数据的处理都做了优化,难免就产生了控制和模型的概念。最后,服务方还需要将处理的结果反馈给客户,显然直接赤裸裸的将数据展示给用户是不形象不美观的,于是需要使用某种视图展示。于是就有了对于数据的视图处理。模型(Model)、视图(View)、控制器(Controller)的概念形成了经典的MVC框架模式或者设计模式。

这种模式可以广泛应用于各种编程语言中,或者说很多编程语言可以实现这种模式。在java中,jsp、servlet、javabean分别对应实现View、Controller、Model的功能。Javabean实际上就是一个无参且使用标准私有属性封装的类,就是那个集装箱,这是java原本就有的特质。jsp,使用java语言的服务器页面,是一种拥有java特性的页面。这两样基本都是java原有特质的应用,而servlet则贯穿这个过程,促成了java的web开发的实现。当然,三者相辅相成,缺一不可实现好的效果。

在web中,数据的传输遵循着一定的协议,一般是http协议。也有通过socket交互的。http协议,大概讲的是客户端和服务器的应答标准。客户端的软件,如浏览器或者QQ这样的网络应用程序或网游程序等,浏览器也是一种应用程序,大都需要实现这个协议。那么在服务端,我们有数据库,MVC的一些东西,似乎没有涉及到这个http协议的东西,显然需要一个东西来遵循这个协议,以实现与客户端的连接。当然,强大的编程软件自身可以考虑自给自足,创建一个实现这个协议的接口或者模块,然而,这样做是不专业、不高效、不安全的,不安全性上,可能将源码暴露在网际。所以,需要一个专业的东西,来遵循这个协议,并将服务端的业务和数据交互推向web。服务器应运而生,这个服务器不是指服务器硬件,服务器将服务端的资源运行起来,并遵循协议实现与web的连接,与客户端的交互。web服务器有tomcat,weblogic,websphere等。

客户端通过客户端应用程序进入web,web通过tomcat等服务器连入服务端,服务端通过servlet控制业务流程,并与web交互。在传统的服务端设计中,C部分,也就是servlet实现控制的部分,一般采用三层的框架。这实际上是进一步降低了程序的耦合性,提高了内聚性。这三层分别是web,service和dao层。Web层即servlet直接处理请求和响应的一层,它直接与视图部分交互,将请求传达给具体实现请求的service层,并将servcie层的反馈结果响应给视图部分。Service层,一般也称为业务层,即根据请求形成具体的业务内容,如用户的删除商品信息的请求,它根据用户的请求形成相应的删除业务,然后将删除的实施工作交给dao层处理。用户的请求几乎就是对数据的某种需求,在三层中,dao层就专门与数据库打交道,在java,是通过java的jdbc操作数据库资源。如上述,删除某商品的信息,在dao层,通过执行相应的sql语句最终完成用户的请求。然后,再逆流反馈给servlet,最终响应给客户端。在企业级开发中,一般会采用框架技术实现这样的业务逻辑,目的当然是低耦合,高内聚,简开发,易维护。

(一)           Introduction

javax.servlet
Interface Servlet

All Known Subinterfaces:

HttpJspPage,JspPage

All Known Implementing Classes:

FacesServlet,GenericServlet, HttpServlet

public interface Servlet

Implemented by: FacesServlet,GenericServlet,JspPage
定义所有 servlet 都必须实现的方法。

servlet 是运行在 Web 服务器中的小型 Java 程序。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。

要实现此接口,可以编写一个扩展 javax.servlet.GenericServlet 的一般 servlet,或者编写一个扩展 javax.servlet.http.HttpServlet的 HTTP servlet。

此接口定义了初始化 servlet 的方法、为请求提供服务的方法和从服务器移除 servlet 的方法。这些方法称为生命周期方法,它们是按以下顺序调用的:

1.构造 servlet,然后使用init 方法将其初始化。

2.处理来自客户端的对 service方法的所有调用。

3.从服务中取出 servlet,然后使用destroy 方法销毁它,最后进行垃圾回收并终止它。

除了生命周期方法之外,此接口还提供了 getServletConfig 方法和 getServletInfo 方法,servlet 可使用前一种方法获得任何启动信息,而后一种方法允许 servlet 返回有关其自身的基本信息,比如作者、版本和版权。

 

英文文档:

Defines methods that all servlets must implement.

A servlet is a small Java program that runs within a Webserver. Servlets receive and respond to requests from Web clients, usuallyacross HTTP, the HyperText Transfer Protocol.

To implement this interface, you can write a genericservlet that extends javax.servlet.GenericServlet or an HTTP servlet that extendsjavax.servlet.http.HttpServlet.

This interface defines methods to initialize a servlet,to service requests, and to remove a servlet from the server. These are knownas life-cycle methods and are called in the following sequence:

1. The servlet isconstructed, then initialized with the init method.

2. Any calls fromclients to the service method are handled.

3. The servlet istaken out of service, then destroyed with the destroy method, then garbagecollected and finalized.

In addition to the life-cycle methods, this interfaceprovides the getServletConfig method, which the servlet can use to get anystartup information, and the getServletInfo method, which allows the servlet toreturn basic information about itself, such as author, version, and copyright.

Author:

Various

See Also:

GenericServlet,HttpServlet

Method Summary

 void

destroy()
        Called by the servlet container to indicate to a servlet that the servlet is being taken out of service.

 ServletConfig

getServletConfig()
        Returns a ServletConfig object, which contains initialization and startup parameters for this servlet.

 String

getServletInfo()
        Returns information about the servlet, such as author, version, and copyright.

 void

init(ServletConfig config)
        Called by the servlet container to indicate to a servlet that the servlet is being placed into service.

 void

service(ServletRequest req,ServletResponse res)
        Called by the servlet container to allow the servlet to respond to a request.

(二)           Servlet的创建及其生命周期

1.       创建一个servlet

在myeclipse或者eclipse中创建一个servlet,前提是在web工程下,且选择了创建web.xml的选项,那么在web根目录,在myeclipse中是webroot文件夹的web-inf的文件夹下的web.xml文件中会自动建立servlet的映射。在eclipse中,自从servlet3.0之后,新建servlet是通过注解的方式建立url路径映射,如果要在web.xml中配置servlet,请手动或者加插件。

Web.xml中的servlet的映射

  <servlet>

    <servlet-name>TestServlet</servlet-name>

    <servlet-class>com.servlet.test.TestServlet</servlet-class>

  </servlet>

  <servlet-mapping>

    <servlet-name>TestServlet </servlet-name>

    <url-pattern>/testServlet</url-pattern>

  </servlet-mapping>

2.  Servlet的生命周期

程序是动态存在的,一般都有个生命周期。作为小程序的servlet,也是。宏观上讲,一个对象从创建到销毁的整个过程,就是它的生命周期。

Servlet的生命周期:

1)       创建时间:当这个Servlet程序被外界第一次访问的时候tomcat服务器内部会自动的创建这个Servlet对象,并调用init方法对这个Servlet进行初始化

2)       服务的时间:当Servlet创建初始化完成之后,就开始一直在提供服务,用户通过浏览器只要访问这个Servlet程序,那么就一定会调用这个Servlet的service方法。每次访问都会调用service方法。Servlet中的service方法是专门提供出来给用户服务的。

3)       销毁的时间:当这个Servlet从项目中被移除,或者tomcat服务器正常关闭(需要手动的去使用stoptomcat),才会调用。

   public voiddestroy() {

      super.destroy();

      System.out.println("销毁了。");

   }

   public voiddoGet(HttpServletRequest request, HttpServletResponseresponse) throwsServletException, IOException {

   }

   public voiddoPost(HttpServletRequest request, HttpServletResponseresponse) throwsServletException, IOException {

      doGet(request, response);

   }

   public voidinit() throwsServletException {

      System.out.println("初始化了。");

   }

3.  Servlet的url映射的三种格式

url根据书写的位置,分为服务器端和客户端两种情况。

一般书写在服务器端的url不需要加项目名。

如<url-pattern>/testServlet</url-pattern>,中/就表示http://127.0.0.1::8080/项目名/

而书写在客户端的url需要加项目名,目的是防止转发,重定向过程中路径错乱。

如在jsp页面中,一般配置<c:setvar=”root” value=”${pageContext.request.contextPath}”></c:set>作为项目路径使用。

然后在a连接或者form表单中,href=,或者action=,“${root}/testServlet”

回到servlet中url的3种格式:

1)  全路径/,/就表示了当前项目下

如,/servlet;/ttt/servlet

2)  路径通配符*,匹配任意

*可以匹配任意的url路径,前提是满足*之前的路径

如,/ttt/*,表示/ttt/路径下所有的servlet都可以访问到。

3)  扩展名匹配*.aaa(aaa的内容按需)

匹配任意aaa扩展名的url路径

如果使用*.aaa,则不能使用/,这样会导致xml解析为/*然后出现冲突报错。

3种格式的优先级:全路径》高于》/*》高于》*.aaa,就是说在能够匹配到高的优先级的路径时,就不再往下尝试匹配。

另外,以/开头是绝对路径,开头没有/是相对路径。相对的一般是当前的项目,具体到页面还要具体区别。

二、   ServletConfig

Servlet也可以作为容器使用,所以,在servlet中可以存放一些配置信息,每个servlet都可以有自己的配置信息,存放一些数据。这个配置在web.xml中实现。

(一)           introduction

javax.servlet
Interface ServletConfig

All Known Implementing Classes:

GenericServlet,HttpServlet

public interface ServletConfig

Implemented by: GenericServlet
servlet 容器使用的 servlet 配置对象,该对象在初始化期间将信息传递给 servlet。

英文文档:

A servlet configuration object used by a servlet container to passinformation to a servlet during initialization.

Method Summary

 String

getInitParameter(String name)
        Returns a String containing the value of the named initialization parameter, or null if the parameter does not exist.

 Enumeration

getInitParameterNames()
        Returns the names of the servlet's initialization parameters as an Enumeration of String objects, or an empty Enumeration if the servlet has no initialization parameters.

 ServletContext

getServletContext()
        Returns a reference to the ServletContext in which the caller is executing.

 String

getServletName()
        Returns the name of this servlet instance.

 

(二)           Example

<context-param>

  <param-name>地址</param-name>

  <param-value>上海</param-value>

  </context-param>

  <servlet>

    <description>This is the description of my J2EE component</description>

    <display-name>This is the display name of my J2EE component</display-name>

    <servlet-name>Servlet1</servlet-name>

    <servlet-class>com.edu.servlet.Servlet1</servlet-class>

    <init-param>

       <param-name>城市</param-name>

       <param-value>上海</param-value>

    </init-param>

    <init-param>

       <param-name>城市2</param-name>

       <param-value>北京</param-value>

    </init-param>

    <init-param>

       <param-name>城市3</param-name>

       <param-value>天津</param-value>

    </init-param>

  </servlet>

  <servlet-mapping>

    <servlet-name>Servlet1</servlet-name>

    <url-pattern>/servlet1</url-pattern>

  </servlet-mapping>

 

public voiddoGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {

      //获得当前servlet的配置参数对象

      ServletConfig servletConfig=this.getServletConfig();

      String servletName=servletconfig.getServletName();

      System.out.println(servletName);

      //根据servlet配置参数的键获得对应的值

      String initParameter=servletconfig.getInitParameter("城市");

      System.out.println(initParameter);

      //获得servlet所有的配置参数的枚举

      Enumeration<String> parameterNames=servletconfig.getInitParameterNames();

      while(parameterNames.hasMoreElements()){

         String key=parameterNames.nextElement();

         Stringvalue=this.getInitParameter(key);

         System.out.println(key+"---"+value);

      }

      //获得当前项目的servletContext

      ServletContextservletcontext=servletconfig.getServletContext();

      System.out.println(servletcontext);

   }

三、   ServletContext

服务器与servlet直接交接,当项目发布到服务器,服务器就会为servlet配置一个共享的上下文对象。ServletContext存放了当前项目的配置信息,也可以作为项目下servlet所共享的一个数据容器。这个配置在web.xml中实现。

(一)           Introduction

javax.servlet
Interface ServletContext

public interface ServletContext
定义一组方法,servlet 使用这些方法与其 servlet 容器进行通信,例如,获取文件的 MIME 类型、分发请求或写入日志文件。

每个 Java 虚拟机的每个“Web 应用程序”都有一个上下文。(“Web 应用程序”是 servlet 和内容的 Collection,这些 servlet 和内容安装在服务器的 URL 名称空间(比如 /catalog)的特定子集下,并且可能通过 .war 文件安装。)

如果 Web 应用程序在其部署描述符中标记为"distributed",那么每个虚拟机都将有一个上下文实例。在这种情况下,不能将上下文用作共享全局信息的位置(因为该信息不会是真正全局共享的)。请使用外部资源(如数据库)替代。

ServletContext 对象包含在 ServletConfig对象中,ServletConfig对象在初始化 servlet 时由 Web 服务器提供给 servlet。

 

英文文档:

Defines a set of methods that a servlet uses tocommunicate with its servlet container, for example, to get the MIME type of afile, dispatch requests, or write to a log file.

There is one context per "web application" perJava Virtual Machine. (A "web application" is a collection ofservlets and content installed under a specific subset of the server's URLnamespace such as /catalog and possibly installed via a .war file.)

In the case of a web application marked"distributed" in its deployment descriptor, there will be one contextinstance for each virtual machine. In this situation, the context cannot beused as a location to share global information (because the information won'tbe truly global). Use an external resource like a database instead.

The ServletContext object is contained within the ServletConfig object, which the Webserver provides the servlet when the servlet is initialized.

Author:

Various

See Also:

Servlet.getServletConfig(),ServletConfig.getServletContext()

Method Summary 见API

(二)           Example

<display-name>servlet1</display-name>

  <context-param>

  <param-name>地址</param-name>

  <param-value>上海</param-value>

  </context-param>

1. 获取servletContext中的数据

public voiddoGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {

      //创建servlet的上下文对象

      ServletContextservletContext=this.getServletContext();

      //根据上下文参数的键获得对应的值

      Stringvalue=servletContext.getInitParameter("地址");

      System.out.println(value); 

   }

2. Servlet共享servletContext中的数据

//servlet共享servletContext中的数据

public voiddoGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {

      System.out.println("-----------开始servletContext存储-------------");

      ServletContextservletContext=this.getServletContext();

      servletContext.setAttribute("时间", "2017");

      System.out.println("--------------servletContext存储数据成功-------------");

   }

 

public voiddoGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {

      System.out.println("-----------调用servletContext存储-------------");

      ServletContextservletContext=this.getServletContext();

      String time=(String)servletContext.getAttribute("时间");

      System.out.println(time);

      System.out.println("--------------调用servletContext存储数据成功-------------");

   }

 

3. Servlet读取web工程下的文件

public voiddoGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {

      ServletContextservletContext=this.getServletContext();

      StringrealPath=servletContext.getRealPath("WEB-INF/classes/webfile.txt");

      //获得文件的硬盘路径

      System.out.println(realPath);

      FileReader fr=new FileReader(realPath);

      char[] but=new char[1024];

      int len;

      while((len=fr.read(but))!=-1){

         System.out.println(newString(but,0,len));

      }

      fr.close();

      //根据文件的file路径获得文件的mime类型

      StringmimeType=servletContext.getMimeType(realPath);

      System.out.println(mimeType);

   }

 

public voiddoGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {

      ServletContextservletContext=this.getServletContext();

      StringcontextPath=servletContext.getContextPath();

      System.out.println(contextPath);

      StringserverInfo=servletContext.getServerInfo();

      System.out.println(serverInfo);

      StringservletContextName=servletContext.getServletContextName();

      System.out.println(servletContextName);

      //不支持的方法

      @SuppressWarnings("deprecation")

      Enumeration<String> servletNames=servletContext.getServletNames();

      while(servletNames.hasMoreElements()){

         System.out.println(servletNames.nextElement());

      }

      //不支持的方法

      @SuppressWarnings("deprecation")

      Enumeration<Servlet>servlets=servletContext.getServlets();

      while(servlets.hasMoreElements()){

         System.out.println(servlets.nextElement());

      }

   }