1. 程式人生 > >Servlet基礎知識,ServletContext,ServletConfig對象詳解

Servlet基礎知識,ServletContext,ServletConfig對象詳解

比較 下午 查詢 servlet對象 跳轉 目錄 有意 table err

Servlet的執行過程:

通過一個簡單的Servlet程序開發,來說明Servlet程序的開發步驟和執行流程

開發Servlet的步驟:

1.1 步驟:

1)編寫java類,繼承HttpServlet

2)重新doGetdoPost方法

3Servlet程序交給tomcat服務器運行

3.1 servlet程序的class碼拷貝到WEB-INF/classes目錄

3.2 web.xml文件中進行配置

Web.xml的配置一個Servlet的寫法

<!-- 配置一個servlet -->

<!-- servlet的配置 -->

<servlet>

<!-- servlet的內部名稱,自定義。盡量有意義 -->

<servlet-name>FirstServlet</servlet-name>

<!-- servlet的類全名: 包名+簡單類名 -->

<servlet-class>a_servlet.FirstServlet</servlet-class>

</servlet>

<!-- servlet的映射配置 -->

<servlet-mapping>

<!-- servlet

的內部名稱,一定要和上面的內部名稱保持一致!! -->

<servlet-name>FirstServlet</servlet-name>

<!-- servlet的映射路徑(訪問servlet的名稱) -->

<url-pattern>/first</url-pattern>

</servlet-mapping>

啟動Tomcat,在瀏覽器的地址欄中輸入http://localhost:8080/day10/first 就可以訪問first

這個Servlet

問題:在地址欄中輸入URLhttp://localhost:8080/day10/first ,是怎麽找到fisrt這個

Servlet ?

瀏覽器是如何找到資源詳解

前提: tomcat服務器啟動時,首先加載webapps目錄中的每個web應用的web.xml配置文件。

http://localhost:8080/day10/first詳解:

http://: http協議

localhost: 到本地的hosts文件中查找是否存在該域名對應的IP地址127.0.0.1,找到,直接訪問,找不到到DNS服務器上找

8080: 找到tomcat服務器監聽的端口號

/day10 在tomcatwebapps目錄下找 day10的目錄

/first 資源名稱。

1)在day10web.xml中查找是否有匹配的url-pattern的內容(/first

2)如果找到匹配的url-pattern,則使用當前servlet-name的名稱到web.xml文件中查詢是否相同名稱的servlet配置

3)如果找到,則取出對應的servlet配置信息中的servlet-class內容:

字符串: a_servlet.FirstServlet

通過反射:

a)構造FirstServlet的對象

b)然後調用FirstServlet裏面的方法

Servlet的映射路徑總結:

url-pattern 瀏覽器輸入

精確匹配 /first http://localhost:8080/day10/first

/itcast/demo1 http://localhost:8080/day10/itcast/demo1

模糊匹配 /* http://localhost:8080/day10/任意路徑

/itcast/* http://localhost:8080/day10/itcast/任意路徑

*.後綴名 http://localhost:8080/day10/任意路徑.do

*.do

*.action

*.html(偽靜態)

註意:

1url-pattern要麽以 / 開頭,要麽以*開頭。 例如, itcast是非法路徑。

2)不能同時使用兩種模糊匹配,例如 /itcast/*.do是非法路徑

3)當有輸入的URL有多個servlet同時被匹配的情況下:

3.1 精確匹配優先。(長的最像優先被匹配)

3.2 以後綴名結尾的模糊url-pattern優先級最低

Servlet的生命周期詳解

問題的引入:

servlet類對象什麽時候創建,什麽時候調用什麽方法,什麽時候銷毀。

以前的對象處理: new Student(); stu.study(); stu=null;

Servlet程序的運行在Tomcat上,生命周期由tomcat服務器控制

Servlet四個重要的方法來控制生命周期

構造方法: 創建servlet對象的時候調用。默認情況下,第一次訪問servlet的時候創建servlet對象

只調用1次。證明servlet對象在tomcat是單實例的。

init方法: 創建完servlet對象的時候調用。只調用1次。

service方法: 每次發出請求時調用。調用n次。

destroy方法: 銷毀servlet對象的時候調用。停止服務器或者重新部署web應用時銷毀servlet對象。

只調用1次。

代碼演示:

public class LifeDemo extends HttpServlet {

/**

* 1.構造方法

*/

public LifeDemo(){

System.out.println("1.servlet對象被創建了。");

}

/**

* 2.init方法

*/

@Override

public void init(ServletConfig config) throws ServletException {

System.out.println("2.init方法被調用");

}

/**

* 3.service方法

*/

@Override

public void service(ServletRequest req, ServletResponse res)

throws ServletException, IOException {

System.out.println("3.service方法被調用");

}

/**

* 4.destroy方法

*/

@Override

public void destroy() {

System.out.println("4.servlet對象銷毀了");

}

}

訪問URL:

http://localhost:8080/day10/LifeDemo

然後重新加載項目

運行的結果:

1.servlet對象被創建了。

2.init方法被調用

3.service方法被調用

九月 20, 2017 7:47:55 下午 org.apache.catalina.core.StandardContext reload

信息: Reloading Context with name [/day10] has started

4.servlet對象銷毀了

偽代碼方式描述Tomcat控制Servlet的生命周期

Tomtcat內部代碼運行:

1)通過映射找到到servlet-class的內容,字符串: .a_servlet.FirstServlet

2)通過反射構造FirstServlet對象

2.1 得到字節碼對象

Class clazz = class.forName("a_servlet.FirstServlet");

2.2 調用無參數的構造方法來構造對象

Object obj = clazz.newInstance(); ---1.servlet的構造方法被調用

3)創建ServletConfig對象,通過反射調用init方法

3.1 得到方法對象

Method m = clazz.getDeclareMethod("init",ServletConfig.class);

3.2 調用方法

m.invoke(obj,config); --2.servlet的init方法被調用

4)創建request,response對象,通過反射調用service方法

4.1 得到方法對象

Methodm m =clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServletResponse.class);

4.2 調用方法

m.invoke(obj,request,response); --3.servlet的service方法被調用

5)當tomcat服務器停止或web應用重新部署,通過反射調用destroy方法

5.1 得到方法對象

Method m = clazz.getDeclareMethod("destroy",null);

5.2 調用方法

m.invoke(obj,null); --4.servlet的destroy方法被調用

Servlet的自動加載:

自動加載的背景:

默認情況下,第一次訪問servlet的時候創建servlet對象。如果servlet的構造方法或init方法中執行了比較多的邏輯代碼,那麽導致用戶第一次訪問sevrlet的時候比較慢,用戶體驗感覺不好。

解決辦法:

改變servlet創建對象的時機: 提前到 加載web應用的時候!!!

<servlet>

<servlet-name>LifeDemo</servlet-name>

<servlet-class>gz.itcast.c_life.LifeDemo</servlet-class>

<!-- servlet對象自動加載 -->

<load-on-startup>1</load-on-startup> 註意: 整數值越大,創建優先級越低!!

</servlet>

改變web.xml配置文件後啟動Tomcat服務器:

技術分享

Servlet的多線程引發的問題

servlet對象在tomcat服務器是單實例多線程的。(一個對象,多個線程訪問)

因為servlet是多線程的,所以當多個servlet的線程同時訪問了servlet的共享數據,如成員變量,可能會引發線程安全問題。

解決辦法:

1)把使用到共享數據的代碼塊進行同步(使用synchronized關鍵字進行同步)

2)建議在servlet類中盡量不要使用成員變量。如果確實要使用成員,必須同步。而且盡量縮小同步代碼塊的範圍。(哪裏使用到了成員變量,就同步哪裏!!),以避免因為同步而導致並發效率降低。

代碼:

public class TheradDemo extends HttpServlet {

int count = 1;

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html;charset=utf-8");

synchronized (TheradDemo.class) {//鎖對象必須唯一。建議使用類對象

response.getWriter().write("你現在是當前網站的第"+count+"個訪客"); //線程1執行完 , 線程2執行

count++;

}

}

}

ServletConfig對象

作用:

ServletConfig對象: 主要是用於加載servlet 一些 初始化參數。在一個web應用可以存在多個ServletConfig對象(一個Servlet對應一個ServletConfig對象)

創建和得到SevletConfig對象

創建時機: 在創建完servlet對象之後,在調用init方法之前創建。

得到對象: 直接從有參數的init方法中得到!!!

完整的例子:

ConfigDemo.java

public class ConfigDemo extends HttpServlet {

/**

* 1)tomcat服務器把這些參數會在加載web應用的時候,封裝到ServletConfig對象中

* 2)tomcat服務器調用init方法傳入ServletConfig對象

*/

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

/**

* 讀取servlet的初始參數

*/

String path = this.getServletConfig().getInitParameter("path");

File file = new File(path);

//讀取內容

BufferedReader br = new BufferedReader(new FileReader(file));

String str = null;

while( (str=br.readLine())!=null ){

System.out.println(str);

}

//查詢當前servlet的所有初始化參數

Enumeration<String> enums = this.getServletConfig().getInitParameterNames();

while(enums.hasMoreElements()){

String paramName = enums.nextElement();

String paramValue = this.getServletConfig().getInitParameter(paramName);

System.out.println(paramName+"="+paramValue);

}

//得到servlet的名稱

String servletName = this.getServletConfig().getServletName();

System.out.println(servletName);

}

}

Web.xml配置文件:

<servlet>

<servlet-name>ConfigDemo</servlet-name>

<servlet-class>gz.itcast.f_config.ConfigDemo</servlet-class>

<init-param>

<param-name>path</param-name>

<param-value>d:/b.txt</param-value>

</init-param>

<init-param>

<param-name>BBB</param-name>

<param-value>BBB‘s value</param-value>

</init-param>

<init-param>

<param-name>CCCC</param-name>

<param-value>CCCC‘s value</param-value>

</init-param>

</servlet>

打印出的結果:

技術分享

註意: servlet的參數只能由當前的這個sevlet獲取!!!!

ServletContext對象也是不能獲取的

ServletConfig對象API總結:

ServletConfigAPI

java.lang.String getInitParameter(java.lang.String name) 根據參數名獲取參數值

java.util.Enumeration getInitParameterNames() 獲取所有參數

ServletContext getServletContext() 得到servlet上下文對象

java.lang.String getServletName() 得到servlet的名稱

ServletContext對象

概念:

ServletContext對象 ,叫做Servlet的上下文對象。表示一個當前的web應用環境。一個 web應用中只有一個ServletContext對象。

對象的創建和獲取方法:

創建時機:加載web應用時創建ServletContext對象。

得到對象: 從ServletConfig對象的getServletContext方法得到

獲取ServletConfig對象和當前項目名:

API介紹:java.lang.String getContextPath() --得到項目名 用在請求重定向的資源名稱中

Java代碼:

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//1.得到ServletContext對象

//ServletContext context = this.getServletConfig().getServletContext();

ServletContext context = this.getServletContext(); //(推薦使用)

System.out.println(context);

//2.得到web應用路徑 /day10

/**

* web應用路徑:部署到tomcat服務器上運行的web應用名稱

*/

String contextPath = context.getContextPath();

System.out.println(contextPath);

/**

* 案例:應用到請求重定向

*/

response.sendRedirect(contextPath+"/index.html");

}

獲取web.xml的公共參數值:

java.lang.String getInitParameter(java.lang.String name) -

-得到web應用的初始化參數(這些參數是Servlet的初始參數是有差別的,可以看出是全局變量和局部變量的關系

java.util.Enumeration getInitParameterNames() --獲取所有的初始參數值

ServletContext對象獲取初始化參數:

web應用參數可以讓當前web應用的所有servlet獲取!!!

API介紹:

java.lang.String getInitParameter(java.lang.String name) -

-得到web應用的初始化參數(這些參數是Servlet的初始參數是有差別的,可以看出是全局變量和局部變量的關系

java.util.Enumeration getInitParameterNames() --獲取所有的初始參數值

Java代碼:

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//得到SErvletContext對象

ServletContext context = this.getServletContext();

System.out.println("參數"+context.getInitParameter("AAA"));

Enumeration<String> enums = context.getInitParameterNames();

while(enums.hasMoreElements()){

String paramName = enums.nextElement();

String paramValue =context.getInitParameter(paramName);

System.out.println(paramName+"="+paramValue);

}

//嘗試得到ConfigDemo中的servlet參數

//結果證明,獲取失敗,因為它要獲取的是Servlet的初始化參數,

//Servlet的初始化參數只能是由那一個ServletConfig對象

String path = this.getServletConfig().getInitParameter("path");

System.out.println("path="+path);

}

web.xml:

技術分享

打印的結果:

參數AAA‘s value

AAA=AAA‘s value

CCC=CCC‘s value

BBB=BBB‘s value

path=null

ServletConfig對象數據的共享

概念: 域對象:作用是用於保存數據,獲取數據。可以在不同的動態資源之間共享數據。

ServletContext域對象:作用範圍在整個web應用中有效!!!

所有的域對象:

HttpServletRequet 域對象

ServletContext域對象

HttpSession 域對象

PageContext域對象

聲明:現在只介紹ServletContext對象

API介紹:

保存數據:void setAttribute(java.lang.String name, java.lang.Object object)

獲取數據: java.lang.Object getAttribute(java.lang.String name)

刪除數據: void removeAttribute(java.lang.String name)

例子:ContextDemo3.java代碼:

/**

* 保存數據

*

*/

public class ContextDemo3 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//1.得到域對象

ServletContext context = this.getServletContext();

//2.把數據保存到域對象中

//context.setAttribute("name", "eric");

context.setAttribute("student", new Student("jacky",20));

System.out.println("保存成功");

}

}

class Student{

private String name;

private int age;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public Student(String name, int age) {

super();

this.name = name;

this.age = age;

}

@Override

public String toString() {

return "Student [age=" + age + ", name=" + name + "]";

}

}

ServletContext4.java代碼:

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

//1.得到域對象

ServletContext context = this.getServletContext();

//2.從域對象中取出數據

//String name = (String)context.getAttribute("name");

Student student = (Student)context.getAttribute("student");

//System.out.println("name="+name);

System.out.println(student);

}

轉發和重定向的區別:

RequestDispatcher getRequestDispatcher(java.lang.String path)

1)轉發

a)地址欄不會改變

b)轉發只能轉發到當前web應用內的資源

c)可以在轉發過程中,可以把數據保存到request域對象中

2)重定向

a)地址欄會改變,變成重定向到地址。

b)重定向可以跳轉到當前web應用,或其他web應用,甚至是外部域名網站。

c)不能再重定向的過程,把數據保存到request中。

結論: 如果要使用request域對象進行數據共享,只能用轉發技術!!!

ServletContext對象API總結:

java.lang.String getContextPath() --得到項目名

java.lang.String getInitParameter(java.lang.String name) -

-得到web應用的初始化參數(這些參數是Servlet的初始參數是有差別的,可以看出是全局變量和局部變量的關系

java.util.Enumeration getInitParameterNames() --獲取所有的初始參數值

保存數據:void setAttribute(java.lang.String name, java.lang.Object object)

獲取數據: java.lang.Object getAttribute(java.lang.String name)

刪除數據: void removeAttribute(java.lang.String name)

java.lang.String getRealPath(java.lang.String path) --得到web應用的資源文件

java.io.InputStream getResourceAsStream(java.lang.String path)

Servlet基礎知識,ServletContext,ServletConfig對象詳解