JavaWeb學習之Servlet(四)----ServletConfig獲取配置信息、ServletContext的應用

【聲明】html

歡迎轉載,但請保留文章原始出處→_→java

文章來源:http://www.cnblogs.com/smyhvae/p/4140877.html程序員

 

【正文】web

1、ServletConfig:表明當前Servlet在web.xml中的配置信息(用的很少數據庫

  • String getServletName()  -- 獲取當前Servlet在web.xml中配置的名字
  • String getInitParameter(String name) -- 獲取當前Servlet指定名稱的初始化參數的值
  • Enumeration getInitParameterNames()  -- 獲取當前Servlet全部初始化參數的名字組成的枚舉
  • ServletContext getServletContext()  -- 獲取表明當前web應用的ServletContext對象

在Servlet的配置文件中,可使用一個或多個<init-param>標籤爲servlet配置一些初始化參數。apache

當servlet配置了初始化參數後,web容器在建立servlet實例對象時,會自動將這些初始化參數封裝到ServletConfig對象中,並在調用servlet的init方法時,將ServletConfig對象傳遞給servlet。進而,程序員經過ServletConfig對象就能夠獲得當前servlet的初始化參數信息。瀏覽器

這樣作的好處是:若是將數據庫信息、編碼方式等配置信息放在web.xml中,若是之後數據庫的用戶名、密碼改變了,則直接很方便地修改web.xml就好了,避免了直接修改源代碼的麻煩tomcat

代碼舉例:服務器

新建一個名爲ServletConfigTest的Servlet,而後在web.xml中的<servlet>標籤下,經過<init-param>標籤爲這個servlet配置兩個初始化參數:app

    <servlet>
        <servlet-name>ServletConfigTest</servlet-name>
        <servlet-class>com.vae.servlet.ServletConfigTest</servlet-class>
        <init-param>
            <param-name>name1</param-name>
            <param-value>value1</param-value>
        </init-param>
        <init-param>
            <param-name>encode</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </servlet>

而後在代碼中獲取上面的兩個參數。代碼實現以下:

 1 package com.vae.servlet;
 2 
 3 import java.io.IOException;
 4 import java.util.Enumeration;
 5 
 6 import javax.servlet.ServletConfig;
 7 import javax.servlet.ServletException;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 
12 public class ServletConfigTest extends HttpServlet {
13 
14     public void doGet(HttpServletRequest request, HttpServletResponse response)
15             throws ServletException, IOException {
16 
17         ServletConfig config = this.getServletConfig();  //拿到init方法中的ServletConfig對象
18 
19         // --獲取當前Servlet 在web.xml中配置的名稱(用的很少)
20          String sName = config.getServletName();
21          System.out.println("當前Servlet 在web.xml中配置的名稱:"+sName);
22          
23         // --獲取當前Servlet中配置的初始化參數(只能獲取一個)常常用到
24         // String value = config.getInitParameter("name2");
25         // System.out.println(value);
26 
27         // --獲取當前Servlet中配置的初始化參數(所有獲取)常常用到
28          Enumeration enumration = config.getInitParameterNames();
29          while(enumration.hasMoreElements()){
30          String name = (String) enumration.nextElement();
31          String value = config.getInitParameter(name);
32          System.out.println(name+":"+value);
33          }
34     }
35 
36     public void doPost(HttpServletRequest request, HttpServletResponse response)
37             throws ServletException, IOException {
38         doGet(request, response);
39     }
40 }

核心代碼是第17行,經過this.getServletConfig()方法拿到init方法中的ServletConfig對象,而後獲取配置信息。

運行程序,後臺打印日誌以下:

0eef8b65-a880-4657-a3d6-37f026bdd9bc 

 

2、ServletContext:表明當前web應用(很是重要

WEB容器在啓動時,它會爲每一個WEB應用程序都建立一個對應的ServletContext對象,它表明當前web應用

ServletConfig對象中維護了ServletContext對象的引用,開發人員在編寫servlet時,能夠經過ServletConfig.getServletContext方法得到ServletContext對象。

因爲一個WEB應用中的全部Servlet共享同一個ServletContext對象,所以Servlet對象之間能夠經過ServletContext對象來實現通信。ServletContext對象一般也被稱之爲context域對象

ServletContext的應用:

1.作爲域對象能夠在整個web應用範圍內共享數據

這裏涉及到一些概念:

  • 域對象:在一個能夠被看見的範圍內共享數據用到對象
  • 做用範圍:整個web應用範圍內共享數據
  • 生命週期:當服務器啓動web應用加載後建立出ServletContext對象後,域產生。當web應用被移除出容器或服務器關閉,隨着web應用的銷燬域銷燬。

代碼舉例:

ServletTest01.java:

 1 package com.vae.servlet;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletContext;
 6 import javax.servlet.ServletException;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 public class ServletTest01 extends HttpServlet {
12 
13     public void doGet(HttpServletRequest request, HttpServletResponse response)
14             throws ServletException, IOException {
15         ServletContext context = this.getServletContext();
16         context.setAttribute("name", "smyhvae");
17     }
18 
19     public void doPost(HttpServletRequest request, HttpServletResponse response)
20             throws ServletException, IOException {
21         doGet(request, response);
22     }
23 
24 }

ServletTest02.java:

 1 package com.vae.servlet;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletContext;
 6 import javax.servlet.ServletException;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 public class ServletTest02 extends HttpServlet {
12 
13     public void doGet(HttpServletRequest request, HttpServletResponse response)
14             throws ServletException, IOException {
15         ServletContext context = this.getServletContext();
16         String myName = (String) context.getAttribute("name");
17         System.out.println(myName);
18     }
19 
20     public void doPost(HttpServletRequest request, HttpServletResponse response)
21             throws ServletException, IOException {
22         doGet(request, response);
23     }
24 
25 }

咱們在ServletTest01中給Context加一個參數name(16行),而後就能在ServletTest02中獲得這個參數了(16行)。

context中經常使用的方法有:

  • void setAttribute(String,Object);
  • Object getAttribute(String);
  • void removeAttribute(String);

 

二、獲取WEB應用的初始化參數

咱們在第一段中,經過<init-param>標籤爲某一個單獨的servlet加配置信息,這種配置信息在其餘的Servlet中是沒法訪問到的。可若是咱們使用<context-param>標籤(與Servlet標籤並列)爲整個Web應用配置屬性的話,那全部的Servlet就都能訪問裏面的參數了。例如:能夠把數據庫的配置信息放在這裏。

這裏涉及到一些概念不要混淆:

  • 請求參數 parameter --- 瀏覽器發送過來的請求中的參數信息
  • 初始化參數 initparameter --- 在web.xml中爲Servlet或ServletContext配置的初始化時帶有的基本參數
  • 域屬性 attribute --- 四大做用域中存取的鍵值對

代碼舉例:

在web.xml中爲整個web應用添加初始化參數:用戶名、密碼。代碼位置以下:

838c6a6c-2548-4497-8007-6d2b2235e894

而後接下來咱們在代碼中來獲取這些參數。代碼以下:

ServletTest03.java:

 1 package com.vae.servlet;
 2 
 3 import java.io.IOException;
 4 import java.util.Enumeration;
 5 
 6 import javax.servlet.ServletContext;
 7 import javax.servlet.ServletException;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 
12 public class ServletTest03 extends HttpServlet {
13 
14     public void doGet(HttpServletRequest request, HttpServletResponse response)
15             throws ServletException, IOException {
16         ServletContext context = this.getServletContext(); // 獲得上下文對象
17 
18         // 獲取單個的Context裏面的初始化參數
19         String value1 = context.getInitParameter("username"); 20         String value2 = context.getInitParameter("password"); 21         System.out.println(value1 + ";" + value2); 22  System.out.println(); 23 
24         // 一次性獲取Context裏全部的初始化參數
25         Enumeration enumeration = context.getInitParameterNames(); 26         while (enumeration.hasMoreElements()) { 27             String name = (String) enumeration.nextElement(); 28             String value = context.getInitParameter(name); 29             System.out.println(name + ";" + value); 30 
31         }
32 
33     }
34 
35     public void doPost(HttpServletRequest request, HttpServletResponse response)
36             throws ServletException, IOException {
37         doGet(request, response);
38     }
39 
40 }

上面的代碼能夠看到,咱們能夠經過context.getInitParameter()方法得到初始化參數。

運行效果以下:

ef89fc9b-727b-45dc-a8a6-e1c75f9d9df9 

 

三、實現Servlet的轉發

這裏涉及到一些概念要區分:

  • 請求重定向:302+Location(兩次請求兩次響應
  • 請求轉發:服務器內不進行資源流轉 (一次請求一次響應,來實現資源流轉)

注:上方括號中的內容是兩者的區別。打個比方,假如你找我借錢,若是是請求重定向的話,那你再去找別人借;若是是請求轉發的話,那我去找別人借,而後再借給你。

代碼舉例:

ServletTest04.java實現請求轉發:

 1 package com.vae.servlet;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.RequestDispatcher;
 6 import javax.servlet.ServletException;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 /**
12  * ServletContext實現請求轉發
13  */
14 public class ServletTest04 extends HttpServlet {
15 
16     public void doGet(HttpServletRequest request, HttpServletResponse response)
17             throws ServletException, IOException {
18         RequestDispatcher dispatcher = this.getServletContext()
19                 .getRequestDispatcher("/servlet/ServletTest05");// 參數中寫虛擬路徑
20         dispatcher.forward(request, response); // 執行完這一行代碼後,將會跳到ServletTest05中去執行。
21 
22     }
23 
24     public void doPost(HttpServletRequest request, HttpServletResponse response)
25             throws ServletException, IOException {
26         doGet(request, response);
27     }
28 
29 }

經過19行代碼拿到轉發器dispatcher,這個轉發器指向ServletTest05(參數中寫虛擬路徑),而後一旦執行完20行代碼,就會跳到ServletTest05中去執行。

那麼ServletTest05.java的代碼以下:

 1 package com.vae.servlet;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.HttpServlet;
 7 import javax.servlet.http.HttpServletRequest;
 8 import javax.servlet.http.HttpServletResponse;
 9 
10 /**
11  * ServletContext實現請求轉發
12  */
13 public class ServletTest05 extends HttpServlet {
14 
15     public void doGet(HttpServletRequest request, HttpServletResponse response)
16             throws ServletException, IOException {
17         response.getWriter().write("10000yuan");
18     }
19 
20     public void doPost(HttpServletRequest request, HttpServletResponse response)
21             throws ServletException, IOException {
22         doGet(request, response);
23     }
24 
25 }

在瀏覽器中輸入url,效果以下:

ff35b4b4-55e9-40b8-aa22-2a87d5a90ef6

4.加載資源文件:

咱們先在WebRoot的根目錄下新建一個資源文件config.properties,這裏有一個問題須要注意:

4.1在Servlet中讀取資源文件時:

若是寫相對路徑或絕對路徑,這個路徑指的是【當前程序啓動的目錄下裏面的路徑。因此,在web環境下,就是tomcat啓動的目錄即tomcat/bin,因此找不到資源。效果以下:

a4b43362-4d25-4154-a402-6726cbbe6e90

若是寫硬盤的路徑D:\\apache-tomcat-7.0.57\\webapps\\WebTest\\config.properties,能夠找到資源,可是隻要一換髮布環境,這個硬盤路徑極可能是錯誤的,一樣不行。

爲了解決這樣的問題,ServletContext提供了getRealPath方法,在這個方法中傳入一個路徑,這個方法的底層會在傳入的路徑的前面拼接當前web應用的硬盤路徑,從而獲得當前資源的硬盤路徑,這種方式即便換了發佈環境,方法的底層也能獲得正確的web應用的路徑從而永遠都是正確的資源的路徑。代碼以下:

this.getServletContext().getRealPath("config.properties")

代碼舉例:

先在WebRoot的根目錄下新建一個文件爲config.properties,裏面的參數以下:

config.properties:

username=smyhvae
password=007

緊接着,新建一個Servlet,代碼以下:

ServletTest06.java:

 1 package com.vae.servlet;
 2 
 3 import java.io.FileReader;
 4 import java.io.IOException;
 5 import java.util.Properties;
 6 
 7 import javax.servlet.ServletException;
 8 import javax.servlet.http.HttpServlet;
 9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11 
12 public class ServletTest06 extends HttpServlet {
13 
14     public void doGet(HttpServletRequest request, HttpServletResponse response)
15             throws ServletException, IOException {
16         Properties prop = new Properties(); // 注意導的包是import java.util.Properties;
17         prop.load(new FileReader(this.getServletContext().getRealPath("config.properties"))); 18 
19         System.out.println(prop.getProperty("username"));
20         System.out.println(prop.getProperty("password"));
21 
22     }
23 
24     public void doPost(HttpServletRequest request, HttpServletResponse response)
25             throws ServletException, IOException {
26         doGet(request, response);
27     }
28 
29 }

核心代碼是第17行中的this.getServletContext().getRealPath("config.properties")

運行效果以下:

2c5d2ca3-295d-4935-a632-b484f0bd07d2

 

4.2     在不少狀況下,Servlet中並不會處理大量的邏輯,而是直接調用其餘的java代碼,那就涉及到了下面的這個問題:

若是在非Servlet環境下要讀取資源文件時能夠採用類加載器加載文件的方式讀取資源:MyService.class.getClassLoader().getResource("../../../config.properties").getPath()

那如今getResource()裏面的路徑該怎麼寫呢?只要記住一句話:類加載器從哪裏加載類,就從哪裏加載資源。這句話有點抽象,咱們仍是經過代碼來看吧:

新建一個Servlet類:

ServletTest07.java:

 1 package com.vae.servlet;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.HttpServlet;
 7 import javax.servlet.http.HttpServletRequest;
 8 import javax.servlet.http.HttpServletResponse;
 9 
10 import com.vae.service.MyService;
11 
12 public class ServletTest07 extends HttpServlet {
13 
14     public void doGet(HttpServletRequest request, HttpServletResponse response)
15             throws ServletException, IOException {
16         MyService service = new MyService();
17         service.method();
18     }
19 
20     public void doPost(HttpServletRequest request, HttpServletResponse response)
21             throws ServletException, IOException {
22         doGet(request, response);
23     }
24 
25 }

在1六、17行代碼中,調用了MyService類中的方法。下面來定義MyService類,在裏面加載資源文件。

MyService.java:

 1 package com.vae.service;
 2 
 3 import java.io.FileNotFoundException;
 4 import java.io.FileReader;
 5 import java.io.IOException;
 6 import java.util.Properties;
 7 
 8 public class MyService {
 9 
10     public void method() throws FileNotFoundException, IOException{
11         //在沒有ServletContext的環境下,若是想要讀取資源,可使用類加載器以加載類的方式加載資源,
12         //這裏要注意,類加載器從哪一個目錄加載類,就從哪一個目錄加載資源,
13         //因此此處的路徑必定要給一個相對於類加載目錄的路徑
14         Properties prop = new Properties();
15         prop.load(new FileReader(MyService.class.getClassLoader().getResource("config.properties").getPath())); 16         System.out.println(prop.getProperty("username"));
17         System.out.println(prop.getProperty("password"));
18     }
19     
20 }

在瀏覽器輸入url後,後臺輸出以下:

09981fbc-a2e8-4b50-b89d-850efc3527de

【特別注意】第15行代碼中getResource()裏面的路徑。

類加載器從哪一個目錄加載類,就從哪一個目錄加載資源,因此此處的路徑必定要給一個相對於類加載目錄的路徑

咱們先看一下這個工程發佈到tomcat裏面的目錄:

3a15ec96-5408-4e70-8de1-3d7820f26281

進入WEB-INF目錄下,是下面的樣子:

c0ab3e4c-bd0f-44c2-9dc9-fd96583d05bd

上圖中的classes目錄和工程文件的src目錄等價。

(1)若是config.properties文件放在src目錄下,那路徑爲:getResource("config.properties")

(2)若是config.properties文件的位置以下:

c9430553-112f-4f2c-8210-fb885b15c2ba

那路徑和上面的代碼同樣:getResource("com/vae/servlet/config.properties")

(3)若是config.properties文件和MyService.java文件並列,那路徑爲:getResource("com/vae/service/config.properties")

(4)若是config.properties文件的位置以下:

18643334-db7c-4caf-ab6a-34446e95bc4f

此時config.properties文件和classes文件並列:

e084de16-dac7-4a86-a971-f7f9bd9a2c84

那路徑爲:getResource("../config.properties")   注:"../"表示上一級目錄。

(5)若是config.properties文件放在整個工程文件的根目錄下,是無效的,由於此時文件並無發佈到Tomcat。

 

【工程文件】

連接:http://pan.baidu.com/s/1ntBPHd3 
密碼:5qr2
相關文章
相關標籤/搜索