每一个Servlet都必须由web容器读取了该Servlet的配置信息(web部署描述符中或@WebServlet中配置的信息)并初始化,才算是一个Servlet。
对于每个Servlet的配置信息,web容器都会为其生成一个ServletConfig对象,你可以从ServletConfig对象中取得Servlet的初始参数以及代表整个web应用程序的ServletContext对象
GenericServlet
在Servlet接口中,定义了init()、service()、destroy()管理Servlet生命周期的方法
1. web容器启动后,会读取Servlet配置信息,将Servlet加载并实例化,为每一个Servlet生成一个对应的ServletConfig对象,用于维护对应Servlet的初始化参数
2. 调用init()方法,将ServletConfig对象传入,这一步由GenericServlet帮我们实现了,GenericServlet主要的作用就是封装ServletConfig对象,GenericServlet中init()方法如下:
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
public void init() throws ServletException {
}
3. GenericServlet在实现顶层接口Servlet的init()方法,还调用了一个无参的init()方法;在编写Servlet时候,如果有一些在初始化需要额外运行的动作,可以重新定义这个无参数的init()方法,而不是直接重新定义带参数的init()方法
4. 有一点需要注意,一般对象想在初始化的时候就定义额外运行的动作,会在构造器中进行,而在Servlet却不行,因为Servlet在初始化的时候还没有调用init()方法,所以定义Servlet构造器是获取不到ServletConfig对象,只能重新定义init()方法
5. GenericServlet中也有一些操作ServletConfig对象的方法,如下:
public String getInitParameter(String name) {
return this.getServletConfig().getInitParameter(name);
}
public Enumeration<String> getInitParameterNames() {
return this.getServletConfig().getInitParameterNames();
}
public ServletConfig getServletConfig() {
return this.config;
}
public String getServletName() {
return this.config.getServletName();
}
public ServletContext getServletContext() {
return this.getServletConfig().getServletContext();
}
6. GenericServlet还定义一些log方法,用于打印日志,一般很少用这些方法,因为功能简单
使用ServletConfig
/**
* 每个Servlet对象都会有对应的ServletConfig对象,
* 该对象维护了每个Servlet的初始化参数信息和表示整个web容器环境的ServletContext
*/
@WebServlet(name = "ServletConfigServlet",
urlPatterns = "/useServletConfig",
initParams = {
@WebInitParam(name = "key", value = "每个Servlet的初始参数"),
@WebInitParam(name = "say", value = "我是一个没什么卵用的初始化参数")
})
public class ServletConfigServlet extends HttpServlet {
/**
* 自定义init()初始化方法,用于操作ServletConfig对象
*/
public void init() throws ServletException {
// 在Servlet实例化后调用初始化方法,维护ServletConfig信息,此时需要注意的就是引用需要定义成全局变量
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1、获取ServletConfig对象
ServletConfig config = getServletConfig();
// 2、获取自身Servlet的初始化参数
Enumeration<String> initParams = config.getInitParameterNames();
// 3、获取具体的初始化参数,值:我是一个没什么卵用的初始化参数
String initValue = config.getInitParameter("say");
// 4、获取当前Servlet的名称,值:ServletConfigServlet
String servletName = config.getServletName();
// 5、获取表示整个web容器的ServletContext
ServletContext context = config.getServletContext();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
可以在Servlet初始化的时候就获取初始化参数,不过需要自定义init()方法,也可以直接获取ServletConfig对象,GenericServlet已经帮我们初始化了ServletConfig对象;自定义init()比较麻烦但十分灵活
初始化参数也可以在web部署描述符中定义,如下:
<servlet>
<servlet-name>ServletConfigServlet</servlet-name>
<servlet-class>ServletConfigServlet</servlet-class>
<init-param>
<param-name>key</param-name>
<param-value>每个Servlet的初始参数</param-value>
</init-param>
<init-param>
<param-name>say</param-name>
<param-value>我是一个没什么卵用的初始化参数</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ServletConfigServlet</servlet-name>
<url-pattern>/useServletConfig</url-pattern>
</servlet-mapping>
使用ServletContext
ServletContext维护了web容器环境的数据,web容器每次启动只会实例化一个ServletContext对象,ServletConfig提供了获取ServletContext示例的接口方法,由GenericServlet实现了。
/**
* ServletContext中的一些方法
*/
@WebServlet(name = "ServletContextServlet", urlPatterns = "/context")
public class ServletContextServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1、获取ServletContext实例
ServletContext context = getServletContext();
// 2、获取RequestDispatcher示例,此时的URL的开头必须包含ContextPath,
// 如果没有设置ContextPath就是“/”,此时的ContextPath为“/web”
// 以“/”开头的URL称为环境相对路径,context.getRequestDispatcher()通过环境实例获取
// 没有则称为请求相对路径,request.getRequestDispatcher()通过请求实例获取
context.getRequestDispatcher("/web/xxx");
// 3、获取应用程序中某个目录中的资源文件,可以使用getResourcePaths()
// 此时获取WEB-INF目录中所有资源路径的路径
Set<String> ress = context.getResourcePaths("/WEB-INF");
ress.forEach(System.out::println);
// 4、如果想在应用程序中读取某个文件的内容,则可以使用getResourceAsStream()方法,
// 使用时必须以ContextPath开头,或者相对/WEB-INF目录的路径
InputStream in = context.getResourceAsStream("/WEB-INF/pdf/dsaj.pdf");
}
}
网友评论