在编写了一个Servlet之后,通常要在web.xml中或者通过注解进行相关配置,这样Tomcat服务器(或者其他Web容器)才能正确读取到Servlet的配置信息。
在前文中,Tomcat服务器可以根据“URL请求”去web.xml中寻找相应的类执行,那么有没有什么方法能够实现在服务器一启动、在某个Servlet类执行前就获取某些参数、实现某些功能呢?
ServletConfig接口
核心特性:
- ServletConfig类代表当前Servlet在web.xml中的配置信息,或者说直接代表着”web.xml”文件;
- javax.servlet.ServletConfig接口
拥有ServletConfig的好处是:
- 将数据库信息、编码方式等配置信息放在web.xml中;
- 如果以后数据库的用户名、密码改变了;
- 则直接很方便地修改web.xml就行了,避免了直接修改源代码的麻烦。
例如:
- 我们要实现读取服务器上的一个文件并显示给用户的浏览器;
- 但是我们开发者并不能确定是哪个文件,故在Java代码里我们不能直接写打开哪个文件,而是将改文件名写成参数的方式;
- 我们把要打开的文件,通过配置于web.xml文件中,以ServletConfig类读取web.xml中的配置文件(以确定是要打开哪个文件),实现不改变代码而随意读取某个文件;
ServletConfig对象创建时机: 在创建完servlet对象之后,在调用init方法之前创建。
ServletConfig对象得到对象: 直接从有参数的init方法中得到!!!
加载web.xml中的初始化参数
在Servlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数。
- 当servlet配置了初始化参数后,web容器在创建servlet实例对象时;
- 会自动将这些初始化参数封装到ServletConfig对象中;
- 并在调用servlet的init方法时,将ServletConfig对象传递给servlet。
- 进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。
ServletConfig的作用:就是加载xml中的<init-param>标签中的数据,并封装成ServletConfig对象;
实现的方法:
- java.lang.String getServletName() -- 获取当前Servlet在web.xml中配置的名字
- java.lang.String getInitParameter(String name) -- 获取当前Servlet指定名称的初始化参数的值
- java.util.Enumeration getInitParameterNames() -- 获取当前Servlet所有初始化参数的名字组成的枚举
- ServletContext getServletContext() -- 获取代表当前web应用的ServletContext对象
实例-ServletConfig读取web.xml中的参数
---------------web.xml---------------
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<servlet>
<description></description>
<display-name>HelloServlet</display-name>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>net.hackyle.HelloServlet</servlet-class>
<!-- 初始化参数,由ServletConfig控制 注意参数的放置位置-->
<init-param> 第一个键值对
<param-name>name</param-name>
<param-value>kyle</param-value>
</init-param>
<init-param> 第二个键值对
<param-name>age</param-name>
<param-value>18</param-value>
</init-param>
<init-param> 第三个键值对
<param-name>address</param-name>
<param-value>bejing...</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
</web-app>
---------------HelloServlet.java---------------
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1. 得到servlet配置对象 专门用于在配置servlet的信息
ServletConfig config = getServletConfig();
// 获取到的是配置servlet里面servlet-name 的文本内容
String servletName = config.getServletName();
System.out.println("servletName=" + servletName);
// 2. 可以获取具体的某一个参数。
String address = config.getInitParameter("address");
System.out.println("address=" + address);
// 3. 获取所有的参数键值对
Enumeration<String> names = config.getInitParameterNames();
// 遍历取出所有的参数名称
while (names.hasMoreElements()) {
String key = (String) names.nextElement();
String value = config.getInitParameter(key);
System.out.println("key===" + key + " value=" + value);
}
}
}
特性:
- 在一个web应用可以存在多个ServletConfig对象;
- 一个Servlet对应一个ServletConfig对象;
- 因为一个web应用可以有多个xml配置文件,即多个ServletConfig对象,而一个Servlet类只有一个xml配置文件,即仅一个ServletConfig对象。
加载注入的初始化参数
从Servlet3.0开始,可以使用注入的方式配置Servlet,而不是在web.xml文件中配置。
一个经典的Servlet在web.xml中的配置:
注入参数:
- initParams={}:等价于<init-param>标签
- @WebInitParam(name=”键”,value=”值”):其中的name等价于<param-name>标签,其中的value等价于<param-value>标签
第一个注解实现的ServletConfig
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(
name="HelloServletConfig",
urlPatterns= {"/config/helloconfig/","/helloconfig"},
initParams= {
@WebInitParam(name="name",value="kyle"),
@WebInitParam(name="age",value="23"),
@WebInitParam(name="address",value="Shanghai")
}
)
public class HelloServletConfig extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1. 得到Servlet的配置对象,专门用于在获取配置参数
ServletConfig config = getServletConfig();
//2. 获取所有参数的键值对
Enumeration<String> kv = config.getInitParameterNames();
while(kv.hasMoreElements()) {
String key = (String)kv.nextElement();
String value = config.getInitParameter(key); //3.根据键获取某个具体参数的值
System.out.println("参数键:"+key+",值:"+value);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
请求URL:http://localhost:8080/K-Servlet/helloconfig
ServletContext类
概念:
- ServletContext对象,叫做Servlet的上下文对象。当服务器启动时,Web容器为该Web项目创建一个唯一的ServletContext对象,其内的所有Servlet共享一个ServletContext对象。
- 表示一个当前的web应用环境,表示当前整个web项目。
- 一个web应用中只有一个ServletContext对象。
- ServletContext是一个全局的储存信息的空间,服务器开启就存在,服务器关闭才释放。
- request,一个浏览器可有多个;session,一个浏览器一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。
ServletContext类创建时机:加载web应用时创建ServletContext对象。
ServletContext类得到对象:从ServletConfig对象的getServletContext方法得到
获得web.xml全局初始化参数
获得web.xml中的全局化初始参数:
- java.lang.String getContextPath() 得到当前web应用的路径
- java.lang.String getInitParameter(java.lang.String name):根据参数名,在web.xml中获取与之对应的参数。
- java.util.Enumeration getInitParameterNames():得到所有初始化参数返回一个集合
第一步:web.xml中配置初始化参数
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<!-- 配置全局的初始化参数 -->
<context-param>
<param-name>name</param-name>
<param-value>KYLE SHAWE</param-value>
</context-param>
<servlet>
<display-name>HelloServlet</display-name>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>net.hackyle.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
</web-app>
第二步:通过ServletContext对象获得参数:
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
GetContextParam();
}
public void GetContextParam() {
//1、获取ServletContext对象
ServletContext context = getServletContext();
//2、根据键去获取初始化参数的值
String address = context.getInitParameter("name");
System.out.println("Key:name,value:"+address);
}
}
获得注入的全局初始化参数
一个经典的全局参数在web.xml中的配置:
注入参数:
- initParams={}:相当于全局参数标签<context-param>标签、<init-param>标签
- @WebInitParam(name=”键”,value=”值”):其中的name等价于<param-name>标签,其中的value等价于<param-value>标签
- 和ServletConfig接口中注入得方式是一样的
注入方式获取项目初始化参数
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(
name="HelloServletContext",
urlPatterns= {"/context/hello","/hellocontext"},
initParams= {
@WebInitParam(name="name(Context)",value="kyle-shawe"),
@WebInitParam(name="address(Context)",value="Shang-Hai")
}
)
public class HelloServletContext extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1. 获取ServletContext对象
ServletContext context = getServletContext();
//2. 获取web.xml中的<context-init>标签中的键值对,或者注解中的initParams中的键值对
Enumeration<String> contexts = context.getInitParameterNames();
while(contexts.hasMoreElements()) {
String contextKey = contexts.nextElement();
String contextValue = context.getInitParameter(contextKey); //根据键获取值
System.out.println("contextKey: "+contextKey+", contextValue: "+contextValue);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
请求URL:http://localhost:8080/K-Servlet/hellocontext
获得项目中任何资源的绝对路径
获得项目资源的方法:
- java.lang.String getRealPath(java.lang.String path) 得到web应用的资源文件的绝对路径,其中的参数是相对于该Web应用的相对地址
- java.io.InputStream getResourceAsStream(java.lang.String path) 获取该文件的字节输入流
- 注意:因为最终这个Servlet是Tomcat服务器运行,故在写路径的时候是站在Tomcat服务器路径中去考虑的!
请求转发:
- RequestDispatcher getRequestDispatcher(java.lang.String path) 请求转发
理解ServletContext获得项目中的任何资源
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(
name="HelloServletContext",
urlPatterns= {"/context/hello","/hellocontext"}
)
public class HelloServletContext extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1. 获取ServletContext对象
ServletContext context = getServletContext();
//2. 调用方法,获取资源文件的路径地址
/*获取根目录下的文件*/
String webRoot = context.getRealPath("index.jsp");
System.out.println("返回根目录的文件绝对路径:"+webRoot);
/*获取受保护的WEB-INF目录下的文件*/
String web_infPath = context.getRealPath("WEB-INF/web.xml");
System.out.println("返回WEB-INF下的文件的绝对路径:"+web_infPath);
/*获取WEB-FIN/lib目录下的文件*/
String web_libPath = context.getRealPath("WEB-INF/lib/Hi.txt");
System.out.println("返回WEB-INF/lib下的文件绝对路径:"+web_libPath);
// 注意:在开发中,Tomcat服务器只能获取Eclipse中的WebContent目录下的内容,其他的都不能获取到!
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
请求URL:http://localhost:8080/K-Servlet/hellocontext
域对象
ServletContext就是一个域对象!!!!作用范围在整个web应用中有效!!!
域对象:
- 作用是用于保存数据,获取数据。
- 可以在不同的动态资源之间共享数据。
- 可以共享任何类型的数据,例如对象。
域对象标准操作:
- 保存数据:void setAttribute(java.lang.String name, java.lang.Object object)
- 获取数据: java.lang.Object getAttribute(java.lang.String name)
- 删除数据: void removeAttribute(java.lang.String name)