1.什么是servlet
servlet是一個Java類,是用來專門處理請求和響應的,是部署在服務器上工作的小程序,之所以叫小程序,是因為它只要部署上去就自動運行工作了可以處理事情了。servlet 通常通過 HTTP(超文本傳輸協議)接收和響應來自 Web 客戶端的請求。
HTTP:
★ HTTP是HyperText Transfer Protocol(超文本傳輸協議)的簡寫,傳輸HTML文件。
★ 用于定義WEB瀏覽器與WEB服務器之間交換數據的過程及數據本身的格式。
2.操作步驟:
a.創建一個實現servlet接口的Java類(ServletDemo1)。
ServletDemo1爆紅是因為實現了Servlet接口就需要重寫里面的方法。實現接口所定義的方法。
在service方法里添加輸出語句
@Override
public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("執行Servlet里的方法");
}
b.在web.xml中配置servlet的信息。
我們的目的就是讓用戶通過url來訪問我們的剛剛實現了servlet接口的類,然后在這個類里面做一些處理。但是我們的類是寫在src中,然后編譯成字節碼.class文件是存放在WEB-INF中的,我們部署應用的時候就把WEB-INF的東西部署到服務器上,而WEB-INF文件中的東西是不允許外部訪問的,所以如果想要訪問的這個類(嚴格意義上說是這個類生成的字節碼文件),我們就需要通過一些配置來告訴服務器某個URL地址是用來訪問某個類的。這就是我們為什么要配置web.xml的原因。(服務器Tomcat啟動后加載項目最先掃描執行web.xml文件)
web.xml主要代碼:
<servlet>
<!-- 一般把類名首字母變小寫作為servlet-name-->
<servlet-name>ServelDemo1</servlet-name>
<servlet-class>com.szy.web.servlet.ServelDemo1</servlet-class>
</servlet>
這里的訪問邏輯是,我們在瀏覽器輸入localhost:8080/應用名/demo1后,它就會找到中相應的url(在中),然后根據這個url找到對應的叫servletDemo1,然后就在這個節點里再找到該對應的。至此,就自動找到這個類,去執行相應的任務了。
<servlet>
<servlet-name>servelDemo1</servlet-name>
<servlet-class>com.cms.Demo1.Service.ServelDemo1</servlet-class>
<!-- 2,填數字越小優先級越高,越先執行,讓該servlet在服務器啟動時就創建,不建議寫零 -->
<load-on-startup>2</load-on-startup>
</servlet>
<!-- 給Servlet映射一個可訪問的URI :http://localhost:8080/項目名/demo1即可通過servelDemo1映射到ServelDemo1訪問該類-->
<servlet-mapping>
<servlet-name>servelDemo1</servlet-name>
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
com.szy.web.servlet.ServelDemo1路徑的獲得操作如下圖:
執行結果:
瀏覽器顯示空白頁面但是控制臺輸出了ServletDemo1類里的執行結果。
3.Servlet的生命周期
此接口定義了初始化 servlet 的方法 init()、為請求提供服務的方法 service()和從服務器移除 servlet 的方法 destroy()。這些方法稱為生命周期方法,它們是按以下順序調用的:
a .初始化階段 :
構造 servlet,然后使用 init 方法將其初始化。
b.響應客戶請求階段:
處理來自客戶端的對 service 方法的所有調用。
c.終止階段:
從服務中取出 servlet,然后調用 destroy 方法銷毀它,最后進行垃圾回收并終止它。
除了生命周期方法之外,此接口還提供了 getServletConfig 方法和 getServletInfo 方法,servlet 可使用前一種方法獲得任何啟動信息,而后一種方法允許 servlet 返回有關其自身的基本信息,比如作者、版本和版權。
package com.szy.web.servlet;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class ServelDemo1 implements Servlet {
public ServelDemo1() {
// 實例化方法
}
@Override
public void init(ServletConfig arg0) throws ServletException {
// 初始化
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
// 服務
System.out.println("執行Servlet里的方法");
}
@Override
public void destroy() {
//銷毀
}
@Override
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getServletInfo() {
// TODO Auto-generated method stub
return null;
}
}
注意:
Servlet何時被創建:
★ 默認情況下,當WEB客戶第一次請求訪問某個Servlet的時候,WEB容器將創建這個Servlet的實例。
★ 當web.xml文件中如果<servlet>元素中指定了<load-on-startup>子元素時,Servlet容器在啟動web服務器時,將按照順序創建并初始化Servlet對象。
★ 在web.xml文件中,某些Servlet只有<serlvet>元素,沒有<servlet-mapping>元素,這樣我們無法通過url的方式訪問這些Servlet,這種Servlet通常會在<servlet>元素中配置一個<load-on-startup>子元素,讓容器在啟動的時候自動加載這些Servlet并調用init()方法,完成一些全局性的初始化工作。
4.servlet的三種創建方式
Servlet --> GenericServlet --> HttpServlet -->我們定義的繼承HttpServlet的類
曾祖父 爺爺 爸爸 孫子
方法如下:
a. 實現javax.servlet.Servlet接口(參見:編寫一個servlet程序)
要實現此接口,還可以編寫一個擴展 javax.servlet.GenericServlet 的一般 servlet,或者編寫一個擴展 javax.servlet.http.HttpServlet 的 HTTP servlet。
b. 繼承javax.servet.GenericServlet類(適配器模式)
只需重寫抽象 service 方法,因為它里面只有一個抽象方法。
c. 繼承javax.servlet.http.HttpServlet類(模板方法設計模式)
我們自己寫Servlet的時候,處理請求的時候實現Service()就好。不重寫Service()方法,而是重寫doGet和doPost2個方法,在HttpServlet抽象類中,已經實現了Service方法了,在有請求進來Servlet的時候首先從請求中獲取到請求提交的方式,所以我們直接重寫doGet和doPost方法就好。通常來說不確定是什么請求的情況下,默認是Get請求,在doGet和doPost中實現一個就夠了,如果方法的實現寫在
HTTP的請求方式包括DELETE,GET,OPTIONS,POST,PUT和TRACE,在HttpServlet類中分別提供了相應的服務方法,它們是,doDelete(),doGet(),doOptions(),doPost(), doPut()和doTrace().
項目開發一般都用這種方式創建Servlet;
第一步:創建Servlet類文件
Ctrl+N;輸入Servlet:
第二步:輸入類名
第三步:映射路徑的名字,默認為類名,可點擊Edit編輯
第三步:勾選需要重寫的方法:都默認勾選Doget和Dopost方法,點擊Finish:
繼承HttpServlet后不要重寫service的方法,因為service方法里包含調用doget跟dopost的方法,重寫了那兩方法不執行就作廢了
第五步:檢查生成的類和Web.xml的Servlet配置信息
package com.cms.Demo1.Service;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ServletDemo4
*/
public class ServletDemo4 extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public ServletDemo4() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
<servlet>
<display-name>ServletDemo4</display-name>
<servlet-name>ServletDemo4</servlet-name>
<servlet-class>com.cms.Demo1.Service.ServletDemo4</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo4</servlet-name>
<url-pattern>/ServletDemo4</url-pattern>
</servlet-mapping>
注意:查看GenericServlet 的源碼包導Tomcat的源碼包,apache-tomcat-7.0.81-src.zip。Outline的窗口帶三角的說明是繼承過來重寫的方法,沒有的才是自己本身的。
servet映射細節
通配符* 代表任意字符串
url-pattern: *.do 以.字符串的請求都可以訪問 注:不要加/
url-pattern: /* 任意字符串都可以訪問
url-pattern: /action/ 以/action開頭的請求都可以訪問
匹配規則:
優先級:從高到低
絕對匹配--> /開頭匹配 --> 擴展名方式匹配
如果url-pattern的值是/,表示執行默認映射。所有資源都是servlet
5. Servlet的線程安全
★ 單實例:每次訪問多線程
★ 解決線程安全問題的最佳辦法,不要寫全局變量,而寫局部變量。
★ Servlet的線程安全問題只有在大量的并發訪問時才會顯現出來,并且很難發現,因此在編寫Servlet程序時要特別注意。
★ servlet處于服務器進程中,它通過多線程方式運行其service方法,一個實例可以服務于多個請求,并且其實例一般不會銷毀,所以你的項目中如果只有一個servlet,那么web容器就只會創建一個實例。所以其默認非線程安全,如果需要線程安全需要指明。
6.ServletConfig
作用:
★ 可以獲取servlet配置信息
★ 可以獲得ServletContext對象
6.1Servlet配置信息的獲取:
當servlet配置了初始化參數后,web容器在創建servlet實例對象時,會自動將這些初始化參數封裝到ServletConfig對象中,并在調用servlet的init方法時,將ServletConfig對象傳遞給servlet。進而,程序員通過ServletConfig對象就可以得到當前servlet的初始化參數信息。
web.xml。只要有ServletConfig對象就能調用getInitParameter方法。
<servlet>
<display-name>servletDemo4</display-name>
<servlet-name>ServletDemo4</servlet-name>
<servlet-class>com.cms.Demo1.Service.ServletDemo4</servlet-class>
<!-- 初始化參數 -->
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</servlet>
獲取配置信息:GBK
package com.cms.Demo1.Service;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ServletDemo4
*/
public class ServletDemo4 extends HttpServlet {
private ServletConfig config;//config對象專門操作配置文件信息
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
this.config = config;
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String encoding = config.getInitParameter("encoding");//獲得配置文件中的信息
System.out.println(encoding);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
總結:
這樣做的好處是:如果將數據庫信息、編碼方式等配置信息放在web.xml中,如果以后數據庫的用戶名、密碼改變了,則直接很方便地修改web.xml就行了,避免了直接修改源代碼的麻煩。
獲取Servlet配置信息的方式(關鍵得到ServletConfig對象):
方式一:
方式二:
方式三:
7. ServletContext
ServletContext: 代表的是整個應用。一個應用只有一個ServletContext對象。單實例。
ServletContext與ServletConfig的區別:
作用:
a. 作為 域對象:在一定范圍內(當前應用),使多個Servlet共享數據。
★ 域對象:在一個可以被看見的范圍內共享數據用到對象
★ 作用范圍:整個web應用范圍內共享數據
★ 生命周期:當服務器啟動web應用加載后創建出ServletContext對象后,域產生。當web應用被移除出容器或服務器關閉,隨著web應用的銷毀域銷毀。
常用方法:
void setAttribute(String name,object value);//向ServletContext對象的map中添加數據
Object getAttribute(String name);//從ServletContext對象的map中取數據
void rmoveAttribute(String name);//根據name去移除數據
把數據添加到ServletContext的map里:
package com.cms.Demo1.Service;
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;
/**
* Servlet implementation class ServletDemo5
*/
public class ServletDemo5 extends HttpServlet {
/**
* @see HttpServoGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通過GenericServlet類 繼承的的getServletContext()方法得到ServletContext對象
ServletContext application = this.getServletContext();//輸完this.getServletContext() 后Ctrl+回車,對象ServletContext通常用application(應用)表示。
//向ServletContext添加一個鍵值對
application.setAttribute("name", "value");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
取出:
package com.cms.Demo1.Service;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ServletDemo6
*/
public class ServletDemo6 extends HttpServlet {
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = (String) this.getServletContext().getAttribute("name");
System.out.println(name);
if(name==null){
System.out.println("你無權訪問");
}
System.out.println();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
b. 獲取全局配置信息:
web.xml文件:
String類型--getInitParameter(String name) //根據配置文件中的key得到value
Java文件:
c.獲取資源路徑:
String getRealPath(String path);//根據資源名稱得到資源的絕對路徑.
可以得到當前應用任何位置的任何資源。
注意:
getRealPath的路徑是參考部署后(publish)的文件路徑
'/'代表當前項目部署后的根目錄:D:\apache-tomcat-7.0.52\webapps\webService
實現Servlet的轉發:
注意:
RequestDispatcher getRequestDispatcher(String path) ;//參數表示要跳轉到哪去