您的位置:首页 > 编程语言 > Java开发

servletconfig对象+servletcontext对象

2017-10-18 14:38 387 查看
HttpServletRequest:请求对象:获取请求信息

HttpServletResponse:响应对象:设置响应对象

ServletConfig对象:servlet配置对象

ServletContext对象:servlet的上下文对象


ServletConfig对象

作用:主要用于加载servlet的初始化参数,在一个web应用中可以存在多个ServletConfig对象(一个Servlet对应一个ServletConfig对象)

对象的创建和得到:

创建时机:在创建完servlet对象之后,在调用init方法之前创建

得到对象:直接从有参数的init方法中得到。

servlet的初始化参数配置

1 <servlet>
2     <servlet-name>Demo1</servlet-name>
3     <servlet-class>com.maodoer.test.Demo1</servlet-class>
4     <load-on-startup>1</load-on-startup>
5     <!-- 初始化参数,这些参数会在加载web应用的时候封装到ServletConfig对象中 -->
6     <init-param>
7         <param-name>path</param-name>
8         <param-value>c:/users/maodoer/desktop/a.txt</param-value>
9     </init-param>
10 </servlet>


1)tomcat服务器把<init-param>中的参数加载web应用的时候,封装到ServletConfig对象中

2)tomcat服务器调用init方法传入ServletConfig对象


servlet的初始化参数设置

注意:servlet的参数只能由当前的这个servlet获取

ServletConfig的api:

getInitParameter(String name);//根据参数名获取参数值

getInitParameterNames();//得到servlet初始化的所有参数

getServletContext();//得到servlet上下文对象

getServletName();//得到servlet的名称

1 public class Demo1 extends HttpServlet{
2     /**
3      * 以下注释代码GenericServlet已经帮开发者写好了,所以不需要再写了。
4      */
5     /*ServletConfig config=null;
6     @Override
7     public void init(ServletConfig config) throws ServletException {
8         this.config=config;
9     }*/
10     @Override
11     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
12         /**
13          * 读取servlet的初始参数
14          */
15         String path = this.getServletConfig().getInitParameter("path");
16         File file=new File(path);
17         //读取内容
18         BufferedReader br=new BufferedReader(new FileReader(file));
19         String str=null;
20         while((str=br.readLine())!=null){
21             System.out.println(str);
22         }
23         //查询当前servlet的所有初始化参数
24         Enumeration<String> enums = this.getServletConfig().getInitParameterNames();
25         while(enums.hasMoreElements()){
26             String paramName = enums.nextElement();
27             String paramValue = this.getServletConfig().getInitParameter(paramName);
28             System.out.println(paramName+"="+paramValue);
29         }
30         //得到servlet的名称
31         String servletName = this.getServletConfig().getServletName();
32         System.out.println(servletName);
33     }
34 }




ServletContext对象:

ServletConfig对象,叫做Servlet的上下文对象。表示一个当前的web应用环境。一个web应用中只有一个ServletContext对象。


对象创建和得到:

创建时间:加载web应用时创建ServletContext对象。

得到:从ServletConfig的getServletContext方法得到。

    sun公司设计:

     1)创建ServletContext对象  ServletContext context=new ServletContext();

     2)创建ServletConfig对象  ServletConfig config=new ServletConfig();

                    config.setServletContext(context);

    Class ServletConfig{

      ServletContext context;

      public ServletContext getServletContext(){

        return context;

      }

    }

    

    public void init(ServletConfig config){

      得到ServletConfig对象

      从ServletConfig对象中得到ServletContext对象

      ServletContext context=config.getServletContext();

    }


ServletContext核心api:

getContextPath();得到当前web应用的路径

getInit
24000
Parameter(String name);得到web应用的初始化参数

getInitParameterNames()

setAttribute(String name,Object object);和域对象有关的方法

getAttribute(String name);

removeAttribute(String name);

getRequestDispather(String path);转发(类似与重定向)

getRealPath(String path);得到web应用的资源文件

getResourceAsStream(String path);

ServletContext,是一个全局的储存信息的空间,服务器开始,其就存在,服务器关闭,其才释放。request,一个用户可有多个;session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。

换一种方式说吧,运行在JAVA虚拟机中的每一个Web应用程序都有一个与之相关的Servlet上下文。ServletContext对象是Web服务器中的一个已知路径的根,Servlet上下文被定位于http://localhost:8080/项目名.以
/项目名 请求路径(称为上下文路径)开始的所有请求被发送到与此ServletContext关联的Web应用程序。一个ServletContext对象表示了一个Web应用程序的上下文。

Servlet上下文:Servlet上下文提供对应用程序中所有Servlet所共有的各种资源和功能的访问。Servlet上下文API用于设置应用程序中所有Servlet共有的信息。Servlet可能需要共享他们之间的共有信息。运行于同一服务器的Servlet有时会共享资源,如JSP页面、文件和其他Servlet。

举例:

如,做一个购物类的网站,要从数据库中提取物品信息,如果用session保存这些物品信息,每个用户都访问一便数据库,效率就太低了;所以要用来Servlet上下文来保存,在服务器开始时,就访问数据库,将物品信息存入Servlet上下文中,这样,每个用户只用从上下文中读入物品信息就行了。

3.1 ServletContext接口简介

ServletContext接口定义了运行servlet的web应用的servlet视图。容器供应商负责提供servlet容器内ServletContext接口的实现。使用ServletContext对象,servlet可以记录事件日志,获取资源的URL地址,并且设置和保存上下文内可以访问的其他servlet的属性。

ServletContext以web的已知路径为根路径。比如,假定一个servlet上下文位于http://www.mycorp.com/catalog。以/catalog请求路径开头的所有请求,已知为上下文路径,被路由到和该ServletContext关联的web应用。

3.2 ServletContext接口作用域

容器中部署的每一个web应用都有一个ServletContext接口的实例对象与之关联。如果容器被分布在多个虚拟机上,一个web应用将在每一个VM中有一个ServletContext实例。

不作为web应用一部分部署的容器中的servlet默认是“默认”web应用的一部分,有一个默认的ServletContext。在分布式容器中。默认ServletContext是非分布式的,并且必须只存在于一个VM中。

3.3 初始化参数

ServletContext接口的初始化参数允许servlet访问与web应用相关的上下文初始化参数,这些由应用开发人员在部署描述符中指定:

getInitParameter

getInitParameterNames

应用开发人员利用初始化参数传送配置信息。典型的例子是web管理员的e-mail地址或者一个持有关键数据的系统名称。

3.4 上下文属性

servlet可以通过名称将对象属性绑定到上下文。任何绑定到上下文的属性可以被同一个web应用的其他servlet使用。ServletContext接口的下列方法允许访问这种功能:

setAttribute

getAttribute

getAttributeNames

removeAttribute

3.4.1 分布式容器中的上下文属性

上下文属性对于创建它们的VM来说是本地的。这防止ServletContext属性存储于分布式容器的共享内存中。当信息需要在运行于分布式环境中的servlet之间共享时,信息被放入会话中(参见第7章“会话”),存储于数据库中,或者存储于EJB组件中。

3.5 资源

ServletContext接口通过下列方法提供对web应用组成的静态内容文档层级的直接访问,包括HTML,GIF和JPEG文件:

getResource

getResourceAsStream

getResource和getResourceAsStream方法以“/”开头的字符串为参数,它指定上下文根路径的资源相对路径。文档的层级可能存在于服务器的文件系统,war文件,远程服务器或者在一些其它位置中。

这些方法不用来获取动态内容。比如,在一个支持JSP规范1的容器中,getResource("/index.jsp")这种形式的方法调用将返回JSP源代码,而不是处理后的输出。关于访问动态内容的更多信息参见第8章“转发请求”。

Web应用资源的完整列表可以使用getResourcePaths(String path)方法访问。该方法语义的完整信息可以在本规范的API文档中找到。

3.6 多个主机和ServletContext

Web服务器可能支持一个服务器上多个逻辑主机共享一个IP地址。这功能有时被称为“虚拟主机”。这种情况下,每一个逻辑主机必须有它自己的servlet上下文或者servlet上下文组。Servlet上下文不可以被多个虚拟主机共享。

3.7 重载考虑

尽管容器供应商因为对于易于开发而实现的类加载不做要求,但是任何那样的实现必须确保所有它们可能使用2的所有servlet和类,被加载在单个类加载器作用域内。必须保证应用应该如开发人员预想的那样运转。作为开发辅助,绑定监听器的会话通知的完整语义应当由容器支持,在类加载上会话终止的监听上使用。

上一代的容器创建新的类加载器以加载servlet,这和用来加载servlet上下文中使用的其他servlet或者类的类加载器不同。这可能造成servlet上下文内的对象引用指向一个意想不到的类或对象,造成意想不到的行为。需要阻止由新一代类加载器所引发的问题。

3.7.1 临时工作目录

每一个servlet上下文都需要一个临时存储目录。Servlet容器必须为每一个servlet上下文提供一个私有的临时目录,并且使它可以通过javax.servlet.context.tempdir上下文属性可用。这些属性关联的对象必须是java.io.File类型。

这项需求认可了很多servlet引擎实现中提供的常见便利。容器不需要在servlet重启时维持临时目录的内容,但是需要确保一个servlet上下文的临时目录的内容对于该servlet容器上运行的其他web应用的servlet上下文不可见。

●Servlet一些细节问题

(一)于客户端是通过URL地址访问web服务器中的资源,所以Servlet程序若想被外界访问,必须把Servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用<servlet>元素和<servlet-mapping>元素完成

(二)<servlet>元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name>和<servlet-class>,分别用于设置Servlet的注册名称和Servlet的完整类名。

(三)一个<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name>和<url-pattern>,分别用于指定Servlet的注册名称和Servlet的对外访问路径。

★这里需要注意的是,一个servlet可以被多次映射,也即一个Servlet可以有多个<servlet-mapping>,对外提供多个访问路径。举例如下:

[html] view
plain copy

<servlet>

<servlet-name>MyServlet1</servlet-name>

<servlet-class>com.gavin.servlet.MyServlet1</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>MyServlet1</servlet-name>

<url-pattern>/MyServlet1</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>MyServlet1</servlet-name>

<url-pattern>/Gavin.html</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>MyServlet1</servlet-name>

<url-pattern>/servlet/Gavin.html</url-pattern>

</servlet-mapping>

这里可以看到,我们将MyServlet1映射成了一个名字为MyServlet1,另一个名字为Gavin.html,还有一个名字为/servlet/Gavin.html。这里也得出结论:

★后缀名为html的资源不一定真的就是html。

★映射的名字可以有多级,有多个斜杠。

★在Servlet映射到的URL中也可以用*通配符,但只能有两种固定的格式,一种格式是“*.扩展名”,另一种是以正斜杠(/)开头并以”/*”结尾。

[html] view
plain copy

<servlet-mapping>

<servlet-name>AnyName</servlet-name>

<url-pattern>/*</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>AnyName</servlet-name>

<url-pattern>/news/*</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>AnyName</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

则第一种可以匹配任何名字的servlet,第二种可以匹配前面有一层为news的servlet,这种方法可以应用在:比如一个网站要对新闻版块进行整改,则可以用这种方法将新闻版块的请求指向其他地方,将其暂时关闭。第三种匹配后缀为do的servlet。

匹配原则:在匹配的时候,(1)看谁的匹配度高,谁就被选中;(2)【*.后缀名】的优先级最低,实在没有匹配项的时候才匹配这个。

看一个面试题:

对于如下的一些映射关系:

Servlet1映射到/abc/*

Servlet2映射到/*

Servlet3映射到/abc

Servlet映射到*.do

当请求URL为“/abc/a.html”,“/abc/*”和”/*”都匹配,哪个Servlet响应?

答案:Servlet1

当请求URL为“/abc”时,”/abc/*”、”/abc”和”/*”都匹配,哪个Servlet响应?

答案:Servlet3

当请求URL为“/abc/a.do”,“/abc/*”和”
*.do”都匹配,哪个Servlet响应?

答案:Servlet1

当请求URL为“/a.do”,“/*”和”*.do”都匹配,哪个Servlet响应?

答案:Servlet2à【*.后缀名】的优先级最低

5、当请求URL为“/xxx/yyy/a.do”,“/*”和”
*.do”都匹配,哪个Servlet响应?

答案:Servlet2à还是【*.后缀名】的优先级最低

通配符的价值在于可以在网站某版块或者整个网站进行维护时,进行暂时的关闭版块或网站。

(四)Servlet是一个供其他java程序(Servlet引擎)调用的java类,它不能独立运行,它的运行完全由Servlet引擎来控制和调度

(五)针对客户端的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,(单例模式)也就是说Servlet实例一旦创建,它就会驻留在内存中,为后续的其他请求服务,直至web容器退出/或者reload该web运用,servlet实例对象才会销毁。

★Servlet单例模式存在线程安全问题,要注意并发处理,比如买票系统,票是所有客户端共享的,那么售票的代码应该使用同步机制。

synchronized(this){

}

如果一个变量不是共享的,就不需要设置为成员变量,只需要在doGet或者doPost方法中定义为局部变量即可。

(六)在Servlet的整个生命周期内,Servlet的init方法只被调用一次。而对一个Servlet的每次访问请求都导致Servlet引擎调用一次servlet的service方法。对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,service方法再根据请求方式分别调用doXXX方法。

(七)★如果在<servlet>元素中配置了一个<load-on-startup>元素,那么web应用程序启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。

用途:为web应用写一个InitServlet,这个Servlet配置为启动时装载,为整个web应用创建必要的数据库表和数据。或者是启动一个后台线程,定时去完成某些工作(比如每隔10秒发一封电子邮件)

举例:

新建Servlet为InitServlet,其代码如下:

[java] view
plain copy

package com.gavin.servlet;

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class InitServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

this.doGet(request, response);

}

//初始化函数

public void init() throws ServletException {

System.out.println("InitServlet的init函数被调用...");

System.out.println("创建库、表...或者定时任务...");

}

}

其中只写了init函数的代码。在web.xml部署如下,其不用<servlet-mapping>映射,因为它只要在启动web应用时调用,而不需要外部访问。

[html] view
plain copy

<servlet>

<servlet-name>InitServlet</servlet-name>

<servlet-class>com.gavin.servlet.InitServlet</servlet-class>

<!-- 这里的1表示所有自启动的servlet的启动顺序,可以用1、2、3... -->

<load-on-startup>1</load-on-startup>

</servlet>

这里的1表示所有自启动的servlet的启动顺序,可以用1、2、3...

启动Tomcat服务器,可以看到:



启动Tomcat服务器的同时,这个Servlet已经被装载到内存了。

这里我们来模拟一个定时发送电子邮件的功能,实现思路:

这里当用户设定了一个定时发送邮件的任务后,数据库里肯定存在一张表,大概如下:

Id
Content
sendTime
1
Hello
2014-5-18 00:00
2
Happy Birthday
2014-5-20 13:14
这里只是做一个简单的模拟,新建一个sendMainThread线程类

[java] view
plain copy

package com.gavin.model;

public class SendMailThread extends Thread {

public void run() {

int i = 0;

while (true) {

try {

// 每休眠一分钟,就去扫表sendmail,看看哪些信件应当发送

Thread.sleep(1000 * 10);

System.out.println("发出 第" + (++i) + "封信件");

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

在InitServlet中创建该线程,并启动即可

[java] view
plain copy

public void init() throws ServletException {

System.out.println("InitServlet的init函数被调用...");

System.out.println("创建库、表...或者定时任务...");

//创建一个线程

SendMailThread sendMailThread = new SendMailThread();

sendMailThread.start();

}

效果:



当然真实的情况应该是要比对数据库中的时间的。

大型的网站会有多个自启动的Servlet,这里要用1、2、3….表示启动的顺序。前面也提到了!

●ServletConfig对象

◆在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数。

◆当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。

如下:

[html] view
plain copy

<servlet>

<servlet-name>MyServlet1</servlet-name>

<servlet-class>com.gavin.servlet.MyServlet1</servlet-class>

<!-- 这里可以给servlet配置信息,这里的配置信息,只能被该servlet读取 -->

<init-param>

<param-name>encoding</param-name>

<param-value>utf-8</param-value>

</init-param>

</servlet>

说明:这里的配置参数方法,只能被该servlet读取,而不能被其他servlet使用

在Servlet程序中,可以读取出设置参数,如下:

[java] view
plain copy

response.setCharacterEncoding(this.getInitParameter("encoding"));



如果有多个参数,可以使用getInitParameterNames()方法,该方法返回枚举类型Enumeration,可以通过for循环拿到对应的参数名称,然后通过参数名称再通过上述方法拿到参数,当然也可以一个个拿到。

◆当然,还有一种全局的参数设置,<context-param>节点也可以配置初始化参数,并且可以被所有servlet读取。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  servlet java javaEE