JavaWeb学习总结(六)--Servlet开发(二)

[TOC]

一、ServletConfig讲解

1.1、通过ServletConfig获取Servlet的初始化参数

  当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,我们通过ServletConfig对象就可以得到当前servlet的初始化参数信息。

​ 例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package org.wuqinghua.java.ch01;
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;
import java.io.IOException;
import java.util.Enumeration;
/**
* Created by wuqinghua on 17/6/30.
*/
@WebServlet(name = "servletConfigDemo01",urlPatterns = {"/servletConfigDemo01"},initParams
={@WebInitParam(name = "name",value = "gacl"),@WebInitParam(name = "password",value =
"123"),@WebInitParam(name = "charset",value = "UTF-8")} )
public class ServletConfigDemo01 extends HttpServlet {
//定义ServletConfig对象来接受配置的初始化参数
private ServletConfig servletConfig;
/**
*当servlet配置了初始化参数后,web容器在创建servlet实例对象时,
* 会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,
* 将servletConfig对象传递给servlet。进而,通过ServletConfig对象就可以得到初始化数据
*/
@Override
public void init(ServletConfig config) throws ServletException {
this.servletConfig = config;
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取配置的参数
String paramVal = this.servletConfig.getInitParameter("name");
resp.getWriter().print(paramVal);
resp.getWriter().print("<hr />");
//获取所有初始化参数
Enumeration<String> e = this.servletConfig.getInitParameterNames();
while (e.hasMoreElements()){
String name = e.nextElement();
String value = this.servletConfig.getInitParameter(name);
resp.getWriter().print(name+"-"+value+"<br />");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}

运行结果如下:

  img

二、ServletContext对象

  WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。
  ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象。
  由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象。

三、ServletContext的应用

  3.1、多个Servlet通过ServletContext对象实现数据共享

  范例:ServletContextDemo1和ServletContextDemo2通过ServletContext对象实现数据共享

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package org.wuqinghua.java.ch01;
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;
import java.io.IOException;
/**
* Created by wuqinghua on 17/6/30.
*/
@WebServlet(urlPatterns = "/servletContextDemo01",initParams = @WebInitParam(name = "name",value
= "hello"))
public class ServletContextDemo01 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String data = "xdp_gacl";
/**
* 获取ServletContext
*/
ServletContext servletContext =
this.getServletConfig().getServletContext();
ServletContext servletContext1 = this.getServletContext();
System.out.println(servletContext == servletContext1);
System.out.println(this.getServletConfig().getInitParameter("name"));
servletContext.setAttribute("data", data);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.wuqinghua.java.ch01;
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;
import java.io.IOException;
/**
* Created by wuqinghua on 17/6/30.
*/
@WebServlet(urlPatterns = "/servletContextDemo02")
public class ServletContextDemo02 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String data = (String) servletContext.getAttribute("data");
resp.getWriter().print("data="+data);
}
}

先运行ServletContextDemo1,将数据data存储到ServletContext对象中,然后运行ServletContextDemo2就可以从ServletContext对象中取出数据了,这样就实现了数据共享,如下图所示:

  img

  3.2、获取WEB应用的初始化参数

  在web.xml文件中使用标签配置WEB应用的初始化参数,如下所示:

1
2
3
4
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/test</param-value>
</context-param>

获取参数代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package org.wuqinghua.java.ch01;
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;
import java.io.IOException;
/**
* Created by wuqinghua on 17/6/30.
*/
@WebServlet("/servletContextDemo03")
public class ServletContextDemo03 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取servletContext
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
resp.getWriter().print(url);
}
}

运行结果:

  img

  3.3、用servletContext实现请求转发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package org.wuqinghua.java.ch01;
import javax.servlet.RequestDispatcher;
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;
import java.io.IOException;
/**
* Created by wuqinghua on 17/6/30.
*/
@WebServlet(urlPatterns = {"/servletContextDemo04"})
public class ServletContextDemo04 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String data = "<h1><font color='red'>abcdefghijkl</font></h1>";
resp.getOutputStream().write(data.getBytes());
ServletContext servletContext = this.getServletContext();
RequestDispatcher rd = servletContext.getRequestDispatcher("/servletContextDemo05");
rd.forward(req,resp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package org.wuqinghua.java.ch01;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by wuqinghua on 17/6/30.
*/
@WebServlet(urlPatterns = "/servletContextDemo05")
public class ServletContextDemo05 extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getOutputStream().write("servletContextDemo05".getBytes());
}
}

运行结果:

  img

  访问的是ServletContextDemo4,浏览器显示的却是ServletContextDemo5的内容,这就是使用ServletContext实现了请求转发

  3.4、利用ServletContext对象读取资源文件

项目目录结构如下:

  img

代码范例:使用servletContext读取资源文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package gacl.servlet.study;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 使用servletContext读取资源文件
*
* @author gacl
*
*/
public class ServletContextDemo6 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");
readSrcDirPropCfgFile(response);//读取src目录下的properties配置文件
response.getWriter().println("<hr/>");
readWebRootDirPropCfgFile(response);//读取WebRoot目录下的properties配置文件
response.getWriter().println("<hr/>");
readPropCfgFile(response);//读取src目录下的db.config包中的db3.properties配置文件
response.getWriter().println("<hr/>");
readPropCfgFile2(response);//读取src目录下的gacl.servlet.study包中的db4.properties配置文件
}
/**
* 读取src目录下的gacl.servlet.study包中的db4.properties配置文件
* @param response
* @throws IOException
*/
private void readPropCfgFile2(HttpServletResponse response)
throws IOException {
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/gacl/servlet/study/db4.properties");
Properties prop = new Properties();
prop.load(in);
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
response.getWriter().println("读取src目录下的gacl.servlet.study包中的db4.properties配置文件:");
response.getWriter().println(
MessageFormat.format(
"driver={0},url={1},username={2},password={3}",
driver,url, username, password));
}
/**
* 读取src目录下的db.config包中的db3.properties配置文件
* @param response
* @throws FileNotFoundException
* @throws IOException
*/
private void readPropCfgFile(HttpServletResponse response)
throws FileNotFoundException, IOException {
//通过ServletContext获取web资源的绝对路径
String path = this.getServletContext().getRealPath("/WEB-INF/classes/db/config/db3.properties");
InputStream in = new FileInputStream(path);
Properties prop = new Properties();
prop.load(in);
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
response.getWriter().println("读取src目录下的db.config包中的db3.properties配置文件:");
response.getWriter().println(
MessageFormat.format(
"driver={0},url={1},username={2},password={3}",
driver,url, username, password));
}
/**
* 通过ServletContext对象读取WebRoot目录下的properties配置文件
* @param response
* @throws IOException
*/
private void readWebRootDirPropCfgFile(HttpServletResponse response)
throws IOException {
/**
* 通过ServletContext对象读取WebRoot目录下的properties配置文件
* “/”代表的是项目根目录
*/
InputStream in = this.getServletContext().getResourceAsStream("/db2.properties");
Properties prop = new Properties();
prop.load(in);
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
response.getWriter().println("读取WebRoot目录下的db2.properties配置文件:");
response.getWriter().print(
MessageFormat.format(
"driver={0},url={1},username={2},password={3}",
driver,url, username, password));
}
/**
* 通过ServletContext对象读取src目录下的properties配置文件
* @param response
* @throws IOException
*/
private void readSrcDirPropCfgFile(HttpServletResponse response) throws IOException {
/**
* 通过ServletContext对象读取src目录下的db1.properties配置文件
*/
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db1.properties");
Properties prop = new Properties();
prop.load(in);
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
response.getWriter().println("读取src目录下的db1.properties配置文件:");
response.getWriter().println(
MessageFormat.format(
"driver={0},url={1},username={2},password={3}",
driver,url, username, password));
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}

运行结果如下:

  img

代码范例:使用类装载器读取资源文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package gacl.servlet.study;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 用类装载器读取资源文件
* 通过类装载器读取资源文件的注意事项:不适合装载大文件,否则会导致jvm内存溢出
* @author gacl
*
*/
public class ServletContextDemo7 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");
test1(response);
response.getWriter().println("<hr/>");
test2(response);
response.getWriter().println("<hr/>");
//test3();
test4();
}
/**
* 读取类路径下的资源文件
* @param response
* @throws IOException
*/
private void test1(HttpServletResponse response) throws IOException {
//获取到装载当前类的类装载器
ClassLoader loader = ServletContextDemo7.class.getClassLoader();
//用类装载器读取src目录下的db1.properties配置文件
InputStream in = loader.getResourceAsStream("db1.properties");
Properties prop = new Properties();
prop.load(in);
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
response.getWriter().println("用类装载器读取src目录下的db1.properties配置文件:");
response.getWriter().println(
MessageFormat.format(
"driver={0},url={1},username={2},password={3}",
driver,url, username, password));
}
/**
* 读取类路径下面、包下面的资源文件
* @param response
* @throws IOException
*/
private void test2(HttpServletResponse response) throws IOException {
//获取到装载当前类的类装载器
ClassLoader loader = ServletContextDemo7.class.getClassLoader();
//用类装载器读取src目录下的gacl.servlet.study包中的db4.properties配置文件
InputStream in = loader.getResourceAsStream("gacl/servlet/study/db4.properties");
Properties prop = new Properties();
prop.load(in);
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
response.getWriter().println("用类装载器读取src目录下的gacl.servlet.study包中的db4.properties配置文件:");
response.getWriter().println(
MessageFormat.format(
"driver={0},url={1},username={2},password={3}",
driver,url, username, password));
}
/**
* 通过类装载器读取资源文件的注意事项:不适合装载大文件,否则会导致jvm内存溢出
*/
public void test3() {
/**
* 01.avi是一个150多M的文件,使用类加载器去读取这个大文件时会导致内存溢出:
* java.lang.OutOfMemoryError: Java heap space
*/
InputStream in = ServletContextDemo7.class.getClassLoader().getResourceAsStream("01.avi");
System.out.println(in);
}
/**
* 读取01.avi,并拷贝到e:\根目录下
* 01.avi文件太大,只能用servletContext去读取
* @throws IOException
*/
public void test4() throws IOException {
// path=G:\Java学习视频\JavaWeb学习视频\JavaWeb\day05视频\01.avi
// path=01.avi
String path = this.getServletContext().getRealPath("/WEB-INF/classes/01.avi");
/**
* path.lastIndexOf("\\") + 1是一个非常绝妙的写法
*/
String filename = path.substring(path.lastIndexOf("\\") + 1);//获取文件名
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/01.avi");
byte buffer[] = new byte[1024];
int len = 0;
OutputStream out = new FileOutputStream("e:\\" + filename);
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.close();
in.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}

 运行结果如下:

  img

四、在客户端缓存Servlet的输出

  对于不经常变化的数据,在servlet中可以为其设置合理的缓存时间值,以避免浏览器频繁向服务器发送请求,提升服务器的性能。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package gacl.servlet.study;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo5 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "abcddfwerwesfasfsadf";
/**
* 设置数据合理的缓存时间值,以避免浏览器频繁向服务器发送请求,提升服务器的性能
* 这里是将数据的缓存时间设置为1天
*/
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);
}
}