参考:http://www.cnblogs.com/xdp-gacl/p/3763559.html
http://blog.csdn.net/zhouguosen_always/article/details/10740017/
一.ServletConfig
1.配置servlet初始化参数
可以在web.xml中,使用<init-param>
标签,来配置servlet的初始化参数。每对标签初始化一个参数。
如:
<servlet>
<servlet-name>AutoServlet</servlet-name>
<servlet-class>com.test1.AutoServlet</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>TestServlet</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</init-param>
<init-param>
<param-name>charset</param-name>
<param-value>UTF-8</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
当servlet配置了初始化参数后,web容器在实例化servlet对象时,会将参数封装到ServletConfig中,并在调用servlet实例的init()方法时,将ServletConfig对象传递过去。因此,可以通过ServletConfig对象获取当前servle实例的初始化参数。
package com.test1;
import java.io.IOException;
import java.io.PrintWriter;
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;
import com.sun.org.apache.xml.internal.security.Init;
public class AutoServlet extends HttpServlet {
//创建一个ServletConfig对象
private ServletConfig config;
//重写init()方法
public void init(ServletConfig config) throws ServletException{
this.config = config;
}
//从ServletConfig对象中获取初始化参数
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException{
//根据参数名称获取参数
String param1 = this.config.getInitParameter("name");//根据名称获取初始化信息的值
response.getWriter().write(param1);
response.getWriter().write("<hr/>");//打印一条分割线
//获取所有初始化参数
Enumeration <String> e = this.config.getInitParameterNames();//获取所有初始化信息的名称
while(e.hasMoreElements()) {
String name = e.nextElement();
String value = this.config.getInitParameter(name);
response.getWriter().print(name + "=" + value + "<br/>");
}
}
public void doPost (HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException{
this.doGet(request, response);
}
}
在ie中打开,显示的是理想的效果:
但是,在360浏览器(IE以及Chrome双内核)中打开时,<hr>
和<br/>
标签都没有起到预期的效果,显示的结果为:
二.ServletContext
这部分的详细内容,参考:
http://blog.csdn.net/lvzhiyuan/article/details/4664624
ServletContext是一个全局的存储信息的空间,用于存储一些重要的、所有用户共享的、线程安全的信息,作为Web应用程序的上下文,被所有的用户所共享,一直到服务器关闭,它才会被释放。
安装在一个服务器中的一个特定URL名字空间(比如,/myapplication)下的所有Servlet,JSP,JavaBean等Web部件的集合构成了一个Web的应用,每一个Web应用(同一JVM),容器都会有一个背景对象,而javax.servlet.ServletContext接口就提供了访问这个背景对象的途径。
也就是说,在整个web应用中,只有一个ServletContext,WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
1.多个servlet通过ServletContext实现数据共享
如:
package com.test1;
import java.io.IOException;
import java.io.PrintWriter;
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 Test1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/*由于在ServletConfig中维护了对于ServletContext的引用
* 所以,在开发过程中,可以通过config找到对应的context
*/
ServletContext context = this.getServletConfig().getServletContext();
//将数据写入到ServletContext对象中
String data = "some message";
context.setAttribute("data", data);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
package com.test1;
import java.io.IOException;
import java.io.PrintWriter;
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 Test2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//直接获取对应的context实例
ServletContext context = this.getServletContext();
//从context中取出数据
String data = (String) context.getAttribute("data");
response.getWriter().write("data = " + data);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
先运行Test1,将data写入到ServletContext中,然后运行Test2,就能够将写入的data读出来。
因为Test1和Test2位于同一个web容器以及同一个JVM中,它们对应同一个上下文,所以,可以通过ServletContext实现数据的共享。
2.获取web应用的初始化参数
与配置servlet的初始化参数相类似,可以在web.xml中,使用<context-param></context-param>
标签来配置web应用的初始化参数。
如:
<context-param>
<param-name>name</param-name>
<param-value>webApplication</param-value>
</context-param>
那么,可以在servlet中,通过ServletContext来获取这些初始化参数。
package com.test1;
import java.io.IOException;
import java.io.PrintWriter;
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 Test2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//直接获取对应的context实例
ServletContext context = this.getServletContext();
//获取整个web应用的初始化参数
String data = context.getInitParameter("name");
response.getWriter().write("data = " + data);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
3.实现请求的转发
如:
package com.test1;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
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 Test1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "Test-1";
response.getWriter().write(data);;
ServletContext context = this.getServletContext();
//设置请求转发对象:当test1被请求时,将秦秋转发到test2
RequestDispatcher rd = context.getRequestDispatcher("/servlet/Test2");//地址写Test2的url-pattern
rd.forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
package com.test1;
import java.io.IOException;
import java.io.PrintWriter;
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 Test2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "Test-2";
response.getWriter().write("data = " + data);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
那么,在浏览器中访问Test1,请求将会被转发到Test2
4.读取资源的配置文件
如:项目目录如下:
要读取其中的两个资源配置文件:
package com.test1;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.org.apache.xml.internal.security.Init;
public class AutoServlet extends HttpServlet {
//利用ServletContext读取资源配置文件
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException{
/*等价于:response.setContentType("text/html;charset=UTF-8")
* 将内容的字符集设为UTF-8,防止出现中文乱码
*/
response.setHeader("content-type", "text/html;charset=UTF-8");
//读取WebRoot文件夹下的db.properties文件
readProFile(response, "/db.properties"); //路径中,/*指的是web根目录
//读取src.com.test1.db2.properties
//对于一个普通web项目,properties文件可以放在src目录下,经过编译器编译之后目录变为WEB-INF/classes目录。
readProFile(response, "/WEB-INF/classes/com/test1/db2.properties");
}
//读取特定目录下的资源配置文件
private void readProFile(HttpServletResponse response, String url)
throws IOException {
ServletContext context = this.getServletContext();
InputStream is = context.getResourceAsStream(url);
Properties prop = new Properties();
prop.load(is);
//根据key读出value
String name = prop.getProperty("name");
String user = prop.getProperty("user");
String password = prop.getProperty("password");
//输出
//这里相当于直接在html页面写代码,所以使用println时不换行,需要加上<br/>
response.getWriter().println("读取资源配置文件:" + url + "<br/>");
//使用MessageFormat.format方法,格式化输出
response.getWriter().println(
MessageFormat.format("name={0},user={1},password={2}",
name,user,password)
+ "<hr/>"
);
}
public void doPost (HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException{
this.doGet(request, response);
}
}
那么,在浏览器中访问该servlet:
此外,还可以使用类装载器来读取资源的配置文件
注意,这种方法不适合用来装载大文件,否则可能会造成JVM内存溢出。
例子如下(使用和上一个例子相同的目录)
package com.test1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.org.apache.xml.internal.security.Init;
public class AutoServlet extends HttpServlet {
//利用类装载器读取资源配置文件
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException{
/*等价于:response.setContentType("text/html;charset=UTF-8")
* 将内容的字符集设为UTF-8,防止出现中文乱码
*/
response.setHeader("content-type", "text/html;charset=UTF-8");
//读取src.com.test1.db2.properties
readProFile(response, "com/test1/db2.properties");
//读取WebRoot文件夹下的db.properties文件
readProFile(response, "db.properties");
}
//读取特定目录下的资源配置文件
private void readProFile(HttpServletResponse response, String url) throws IOException
{
//获取类装载器
ClassLoader loader = AutoServlet.class.getClassLoader();
InputStream is = loader.getResourceAsStream(url);
//按字节读出资源配置文件中的内容
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] by = new byte[1024];
int len = 0;
try {
while((len = is.read(by))!= -1){
baos.write(by, 0, len);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String content = new String(baos.toByteArray());
response.getWriter().write("使用类装载器读取文件:" + url + "<br/>");
response.getWriter().write(content + "<hr/>");
}
public void doPost (HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException{
this.doGet(request, response);
}
}
浏览器访问的结果为:
从图中可以看到,读取WEB-ROOT目录下的db.properties文件时,并没有成功地将内容读出来,后台报了一个空指针错误。
这是因为,类加载器是加载类路径下的文件,因此,配置的url路径与直接使用ServletContext读取配置文件时有所不同。此时,需要将配置文件放在src目录下,写路径时从包名开始写,前面不加正斜杠(/)
6.在客户端缓存servlet的输出
对于不常变化的数据,可以在servlet中设置一定缓存时间值,已避免浏览器频繁地像服务器发送请求,已提高服务器的性能。
如:
package com.test1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Properties;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.org.apache.xml.internal.security.Init;
public class AutoServlet extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException{
/*设置合理的缓存时间,避免浏览器频繁向服务器发送请求
* 这里将时间设为1天
*/
String data = "This is some data";
response.setDateHeader("expires", System.currentTimeMillis()+24*3600*1000);
response.getOutputStream().write(data.getBytes());
}
public void doPost (HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException{
this.doGet(request, response);
}
}
从ie浏览器的“Internet选项-浏览历史记录-设置”位置,找到当前浏览器的缓存存放位置,但是,本机上查看时,并未找到对应名称的缓存文件,因此,此处持保留意见,有待后续补充。