关于这块内容,主要就是玩一个接口:ServletConfig。先翻下API,了解一下。
定义:
public interface ServletConfig
这个接口定义了一个对象,通过这个对象,Servlet引擎配置一个Servlet并且允许Servlet获得一个有关它的ServletContext接口的说明。每一个ServletConfig对象对应着一个唯一的Servlet。
方法:
1、getInitParameter public String getInitParameter(String name);
这个方法返回一个包含Servlet指定的初始化参数的String。如果这个参数不存在,返加空值。
2、getInitParameterNames public Enumeration getInitParameterNames();
这个方法返回一个列表String对象,该对象包括Servlet的所有初始化参数名。如果Servlet没有初始化参数,getInitParameterNames返回一个空的列表。3、getServletContext public ServletContext getServletContext();
返回这个Servlet的ServletContext对象。
现在我们在看一下Tomcat中这个接口的实现,Tomcat使用了门面模式,也就是将ServletConfig封装一下,里面提供的各个方法就是ServletConfig这个对象的各个方法。下面贴出源码:
package org.apache.catalina.core; import java.util.Enumeration; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; public final class StandardWrapperFacade implements ServletConfig { private ServletConfig config = null; private ServletContext context = null; public StandardWrapperFacade(StandardWrapper config) { super(); this.config = (ServletConfig) config; } public String getServletName() { return config.getServletName(); } public ServletContext getServletContext() { if (context == null) { context = config.getServletContext(); if ((context != null) && (context instanceof ApplicationContext)) context = ((ApplicationContext) context).getFacade(); } return (context); } public String getInitParameter(String name) { return config.getInitParameter(name); } public Enumeration getInitParameterNames() { return config.getInitParameterNames(); } }
OK,现在言归正传细致的了解下这个接口。
Servlet在有些情况下可能需要访问Servlet容器或借助Servlet容器访问外部的资源,所以呢,Serlvet引擎需要将表示Servlet容器的对象传递给Servlet。另外,在web.xml文件中为某个Servlet设置的友好名称和初始化参数等信息也需要传递给该Servlet。
Servlet引擎将代表Servlet容器的对象(ServletContext)和Servlet的配置参数信息一并封装到一个称为ServletConfig的对象中,之后在初始化Servlet实例对象时传递给该Servlet。ServletConfig接口则用于定义ServletConfig对象需要对外提供的方法,以便在Servlet程序中可以调用这些方法来获取有关信息。Servlet引擎调用Servlet的实例对象的init(ServletConfig config)方法将ServletConfig对象传递给Servlet。Servlet.getServletConfig()方法必须返回init(ServletConfig
config)方法传递进来的这个ServletConfig对象的引用。
一定要注意这里封装着2个东西呢:一个是代表Servlet容器的对象,一个是Servlet的配置参数信息。如何区分这2个东西呢?
1,ServletConfig是servlet访问配置数据的一个对象,由容器创建,每个servlet独享。仅对本servlet有效,一个servlet的ServletConfig 对象不能被另一个 servlet 访问。主要用来读取 web.xml 中配置的Servlet初始信息,不能被其它 Servlet 共享。还可以用于访问 ServletContext。
2,ServletContext是多个Servlet共享数据的对象。对同一个Web应用中的任何servlet,在任何时间都有效。对应整个Web Application运行环境,可以用来读取 web.xml 中配置的应用初始信息,写日志,共享数据等。ServletContext被所有Servlet共享。可以理解为真正意义上的全局对象。具体的关于这对象,看下面的整理:
Servlet引擎为每个WEB应用程序都创建一个对应的ServletContext对象,ServletContext对象被包含在ServletConfig对象中,调用ServletConfig.getServletContext方法可以返回ServletContext对象的引用。由于一个WEB应用程序中的所有Servlet都共享同一个ServletContext对象,所以,ServletContext对象被称之为 application 对象(Web应用程序对象)。
功能:获取WEB应用程序的初始化参数,记录日志,application域范围的属性,访问资源文件,获取虚拟路径所映射的本地路径,WEB应用程序之间的访问,ServletContext的其他方法。
通过上面的了解,关于一些概念上的理解就不做赘述了,现在想说的就是为什么要玩这2个东西,为什么要去Servlet初始化的配置信息呢?为WEB应用程序设置初始化参数的好处在于不需要修改Servlet源程序,就可以改变一些参数信息。也就是说,防止硬编码,防止后续的维护去改代码。
OK,现在通过2个例子,现在写一个自己的Servlet实现Servlet接口,实现2个功能。
1,使用SerlvetConfig来获取Servlet的<init-param>,从而获得一个Servlet的初始化参数
package linkin; import java.io.IOException; import java.util.Enumeration; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class LinkinServlet implements Servlet { public LinkinServlet() { System.out.println("LinkinServlet..."); } @Override public void destroy() { System.out.println("destroy..."); } @Override public ServletConfig getServletConfig() { return null; } @Override public String getServletInfo() { return null; } @Override public void init(ServletConfig servletConfig) throws ServletException { String name = servletConfig.getInitParameter("name"); System.out.println(name); Enumeration<String> enumeration = servletConfig.getInitParameterNames();//name,yourName while (enumeration.hasMoreElements()) { String value = (String) enumeration.nextElement(); System.out.println(value + ":" + servletConfig.getInitParameter(value)); } } @Override public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException { System.out.println("service..."); } }
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>LinkinServlet</servlet-name> <servlet-class>linkin.LinkinServlet</servlet-class> <init-param> <param-name>name</param-name> <param-value>LinkinPark...</param-value> </init-param> <init-param> <param-name>yourName</param-name> <param-value>NightWish...</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>LinkinServlet</servlet-name> <url-pattern>/LinkinServlet</url-pattern> </servlet-mapping> </web-app>
这里有一个优化,现在这个ServletConfig对象是init()方法的一个参数,也就是说现在获取Servlet的初始化参数也只能在这个方法内,我要是想在别的方法里面获得相关的初始化参数怎么办呢?
很简单,扩大ServletConfig对象的作用域就好了。将ServletConfig对象定义成类成员变量,在init里面赋值就OK。GenericServlet其实就是这么做的,只不过它这个ServletConfig对象是用private修饰的。
2,使用ServletContext来获取<context-param>参数,从而获得整个web应用的初始化参数
package linkin; import java.io.IOException; import java.util.Enumeration; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class LinkinServlet implements Servlet { public LinkinServlet() { System.out.println("LinkinServlet..."); } @Override public void destroy() { System.out.println("destroy..."); } @Override public ServletConfig getServletConfig() { return null; } @Override public String getServletInfo() { return null; } @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println(servletConfig.getServletContext().getInitParameter("name")); Enumeration<String> enumeration = servletConfig.getServletContext().getInitParameterNames(); while (enumeration.hasMoreElements()) { String value = (String) enumeration.nextElement(); System.out.println(value + ":" + servletConfig.getServletContext().getInitParameter(value)); } } @Override public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException { System.out.println("service..."); } }
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param> <param-name>name</param-name> <param-value>LinkinPark...</param-value> </context-param> <context-param> <param-name>name1</param-name> <param-value>LinkinPark1...</param-value> </context-param> <servlet> <servlet-name>LinkinServlet</servlet-name> <servlet-class>linkin.LinkinServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LinkinServlet</servlet-name> <url-pattern>/LinkinServlet</url-pattern> </servlet-mapping> </web-app>