一、ServletConfig講解
首先看ServletConfig API文檔
1.1、配置Servlet初始化參數
在Servlet的配置檔案web.xml中,可以使用一個或多個标簽為servlet配置一些初始化參數。
例如:
ServletConfigDemo1 gacl.servlet.study.ServletConfigDemo1 name gacl password 123 charset UTF-8 1.2、通過ServletConfig擷取Servlet的初始化參數 當servlet配置了初始化參數後,web容器在建立servlet執行個體對象時,會自動将這些初始化參數封裝到ServletConfig對象中,并在調用servlet的init方法時,将ServletConfig對象傳遞給servlet。進而,我們通過ServletConfig對象就可以得到目前servlet的初始化參數資訊。
例如:
package gacl.servlet.study;
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 ServletConfigDemo1 extends HttpServlet {
/**
* 定義ServletConfig對象來接收配置的初始化參數
*/
private ServletConfig config;
/**
* 當servlet配置了初始化參數後,web容器在建立servlet執行個體對象時,
* 會自動将這些初始化參數封裝到ServletConfig對象中,并在調用servlet的init方法時,
* 将ServletConfig對象傳遞給servlet。進而,程式員通過ServletConfig對象就可以
* 得到目前servlet的初始化參數資訊。
*/
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//擷取在web.xml中配置的初始化參數
String paramVal = this.config.getInitParameter("name");//擷取指定的初始化參數
response.getWriter().print(paramVal);
response.getWriter().print("<hr/>");
//擷取所有的初始化參數
Enumeration<String> e = config.getInitParameterNames();
while(e.hasMoreElements()){
String name = e.nextElement();
String value = config.getInitParameter(name);
response.getWriter().print(name + "=" + value + "");
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
運作結果如下:

二、ServletContext對象
WEB容器在啟動時,它會為每個WEB應用程式都建立一個對應的ServletContext對象,它代表目前web應用。
ServletConfig對象中維護了ServletContext對象的引用,開發人員在編寫servlet時,可以通過ServletConfig.getServletContext方法獲得ServletContext對象,但是還有更簡潔的this.getServletContext()方法;
由于一個WEB應用中的所有Servlet共享同一個ServletContext對象,是以Servlet對象之間可以通過ServletContext對象來實作通訊。ServletContext對象通常也被稱之為context域對象:1,是一個容器 2。作用範圍是應用程式範圍。
三、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
package gacl.servlet.study;
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 ServletContextDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "xdp_gacl";
/**
* ServletConfig對象中維護了ServletContext對象的引用,開發人員在編寫servlet時,
* 可以通過ServletConfig.getServletContext方法獲得ServletContext對象。
*/
ServletContext context = this.getServletConfig().getServletContext();//獲得ServletContext對象
context.setAttribute("data", data); //将data存儲到ServletContext對象中
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package gacl.servlet.study;
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 ServletContextDemo2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext context = this.getServletContext();
String data = (String) context.getAttribute("data");//從ServletContext對象中取出資料
response.getWriter().print("data="+data);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
先運作ServletContextDemo1,将資料data存儲到ServletContext對象中,然後運作ServletContextDemo2就可以從ServletContext對象中取出資料了,這樣就實作了資料共享,如下圖所示:
3.2、擷取WEB應用的初始化參數
如果想在所有的Servlet應用中都要配置并讀取初始化參數,則可以在web.xml檔案的中使用标簽配置WEB應用的初始化參數,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<web-app version=“3.0” 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_3_0.xsd">
<display-name></display-name>
<!-- 配置WEB應用的初始化參數 -->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/test</param-value>
</context-param>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
擷取Web應用的初始化參數,代碼如下:
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 gacl.servlet.study;
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 ServletContextDemo3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ServletContext context = this.getServletContext();
//擷取整個web站點的初始化參數
String contextInitParam = context.getInitParameter("url");
response.getWriter().print(contextInitParam);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
運作結果:
3.3、用servletContext實作請求轉發
實作Servlet的轉發。
ServletContextDemo4
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 gacl.servlet.study;
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 ServletContextDemo4 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "<h1><font color='red'>abcdefghjkl</font></h1>";
response.getOutputStream().write(data.getBytes());
ServletContext context = this.getServletContext();//擷取ServletContext對象
RequestDispatcher rd = context.getRequestDispatcher("/servlet/ServletContextDemo5");//擷取請求轉發對象(RequestDispatcher)
rd.forward(request, response);//調用forward方法實作請求轉發
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
ServletContextDemo5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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 ServletContextDemo5 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getOutputStream().write("servletDemo5".getBytes());
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
運作結果:
通路的是ServletContextDemo4,浏覽器顯示的卻是ServletContextDemo5的内容,這就是使用ServletContext實作了請求轉發
3.4、利用ServletContext對象讀取資源檔案
利用ServletContext對象讀取資源檔案,因為檔案的位置不同,所有讀取的方式也不同,一般來說分為兩種情況:
在Servlet的context域中讀取檔案,工程目錄下的src目錄釋出到伺服器中,會映射到“/WEB-INF/classes”檔案夾下。是以要一一對應。而且這個是相對目錄,相對于web伺服器的目錄。如果要用傳統的檔案讀取檔案,則要使用絕對路勁
PrintWriter out = response.getWriter();
ServletContext context = this.getServletContext();
String path = context.getRealPath("/WEB-INF/classes/itcast.properties");
InputStream in = new FileInputStream(path);
Properties pro = new Properties();
pro.load(in);
如果是非servlet中讀取配置檔案,則要使用類加載器去讀取。稍後講到
項目目錄結構如下:
代碼範例:使用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;
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);
}
}
運作結果如下:
使用類裝載器讀取資源檔案
我們在非servlet中讀取資源檔案時(比如在資料庫的dao層讀取配置檔案),采用類裝載器 classLoader,你可以先采用servlet服務先讀取,然後在把servlet傳遞給dao,這樣雖然可以實作,但是,這樣損壞了我們編代碼的設計原則,就是層之間不能有交織在一起的東西。
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;
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);
}
}
運作結果如下:
使用類裝載器讀取資源檔案,存在的問題是;類裝載器,每次隻會裝載一次。
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
//如果讀取資源檔案的程式不是servlet的話,
//就隻能通過類轉載器去讀了,檔案不能太大
//用傳遞參數方法不好,耦合性高
public class UserDao {
private static Properties dbconfig=new Properties();
static {
InputStream in=UserDao.class.getClassLoader().getResourceAsStream("db.properties");
try {
dbconfig.load(in);
} catch (IOException e) {
throw new ExceptionInInitializerError(e);
}
//上面代碼類裝載器隻裝載一次,下面代碼用類裝載方式得到檔案位置
URL url=UserDao.class.getClassLoader().getResource("db.properties");
String str=url.getPath();
//file:/C:/apache-tomcat-7.0.22/webapps/day05/WEB-INF/classes/db.properties
try {
InputStream in2=new FileInputStream(str);
try {
dbconfig.load(in2);
} catch (IOException e) {
throw new ExceptionInInitializerError(e);
}
} catch (FileNotFoundException e1) {
throw new ExceptionInInitializerError(e1);
}
}
public void update() {
System.out.println(dbconfig.get("url"));
}
}
四、在用戶端緩存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);
}
}感興趣的可以點選加扣群 854393687