servlet的介紹 & xml中配置 以及 & 三種實現方式(補充設定瀏覽器不快取的方法)
開始時間:2018年10月13日20:53:30 | 2018年10月14日16:10:56
結束時間:2018年10月13日21:53:30 | 2018年10月14日17:02:23
累計時間:2小時
備註:幾乎每一句話都很有收穫,複習的時候務必要仔細一點
Servlet 簡單介紹:
Servlet 伺服器端的一個小程式: 執行在伺服器上。 能夠接收客戶端請求,並且給客戶端做出相應。
* 實現方式: 三種:
(1)實現Servlet 介面:
(2)繼承GenericServlet:類。
(3)繼承HttpServlet:
* Servlet 當中設定的方法:
初始化的方法; init();
接收客戶端的請求,Service();
銷燬Servlet: destroy();
* Servlet 的生命週期:
和Servlet 宣告週期相關的方法:
init(ServletConfig config); Servlet建立之後,自動執行。
service(ServletRequest request, ServletResponse response); 當客戶端瀏覽器發出請求的時候 service方法被呼叫。
destroy() 伺服器關閉的時候,當前的應用稱web伺服器上解除安裝的時候。
生命週期---(面試問題)
誕生: 當客戶端瀏覽器 第一次
第二次訪問不建立,所以說servlet是單例
自動會呼叫init方法,執行一個初始化操作。
服務: 當客戶端瀏覽器每次發出請求,service方法都會被執行。
銷燬: 伺服器關閉的時候,當前的應用稱web伺服器上解除安裝的時候。
* 訪問方式
不能被瀏覽器直接訪問, 需要在當前應用的核心配置當中 對 當前servlet進行配置
配置方法如下:
1 開啟webinfo檔案 下面的web.xml (是web應用的核心配置檔案)
<!--註冊Servlet: -->
<servlet>//需要有兩個子標籤 第一個放檔名 第二個放你的檔案所在的全路徑名
(如果是eclipse的話 可以快速copy全路徑 如圖 點選 copy qualified name即可)
<servlet-name>FirstServlet</servlet-name>
<servlet-class>web.servlet.FirstServlet</servlet-class>
</servlet>
<!-- 對映 -->(本質上是一個圖結構)
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name> 和上面註冊一樣
<url-pattern>/xxx</url-pattern> /表示相對當前路徑 對映上面那個class 自己命名的值會顯示在URL欄
</servlet-mapping>
servlet訪問原理
- url-pattern繫結 路徑。訪問的是xxx ,通過name 獲得當前全路徑名稱
- 底層通過反射,建立了例項
補充一個Servlet 簡單案例:
重點是瀏覽器設定不快取
下面程式碼設定了瀏覽器不快取,避免出現 修改伺服器端給瀏覽器的響應 而瀏覽器顯示不改變 的情況!
如果已經出現的話,清空瀏覽器快取,或者重啟。
package com.yidongxueyuan.web.servlet;
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 AServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("yyy");
//設定瀏覽器不快取:
// 同時出現,設定瀏覽器的不快取:
response.setHeader("expires", "-1");
response.setHeader("Pragma", "no-cache");// http10.0
response.setHeader("Cache-Control", "no-cache");// http1.1
}
}
response.setHeader("expires", "-1"); 中的 第二個引數 不一定非得是-1,只要小於當前時間的毫秒值,即可。一般是-1或0
重點介紹三種實現方式
方式一: 實現步驟
(1) 建立一個類: 類實現implements Servlet
(2) 重寫Servlet當中的方法:
(3) 訪問》 通過瀏覽器訪問:
下面程式中: servlet例項被建立的時候,自動執行init方法。
繼承之後要重寫的五個方法中,三個是servlet生命週期的方法
package com.yidongxueyuan.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 FirstServlet implements Servlet {
//第一步: 建立一個Servlet 例項:
public FirstServlet(){
System.out.println("servlet 被建立了");
}
//初始化方法: 對當前的Servlet 進行初始化操作:
@Override
public void init(ServletConfig paramServletConfig) throws ServletException {
System.out.println("init方法被執行了,完成了一個初始化操作。 ");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
//service 方法: 對客戶端的請求 進行相關的處理:
@Override
public void service(ServletRequest request,
ServletResponse paramServletResponse) throws ServletException,
IOException {
System.out.println("serice方法被執行了。。。。。。");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("destroy方法被執行了。 此時Servlet被銷燬。 ");
}
}
方式二:繼承GenericServlet:類。
- servlet是單例的,如果定義全域性變數 的話,當多執行緒併發訪問時候,會出現資料 安全問題。(儘量不要使用單例)
第二種方式用了config物件作為全域性變數,所以不太好。
關於這個類,手寫如下:
package com.yidongxueyuan.web.servlet;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/*
* 自定義的GenericServlet:
*/
public class MyGenericServlet implements Servlet {//Servlet 單例: 定義的全域性變數 會引發資料安全問題。 儘量不要使用全域性變數。
//提供一個了一個全域性的config物件:
private ServletConfig config;
//不是一個生命週期方法:
public void init(){
}
//生命週期方法:
@Override
public void init(ServletConfig config) throws ServletException {
this.config=config;
init();
}
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public void service(ServletRequest paramServletRequest,
ServletResponse paramServletResponse) throws ServletException,
IOException {
}
@Override
public String getServletInfo() {
return "這是一個快樂的Servlet ";
}
@Override
public void destroy() {
}
//提供一個方法; 獲得servlet 的名稱:
public String getServletName(){
String servletName = config.getServletName();
return servletName;
}
//提供一個方法:獲得初始化引數的值:
public String getInitParameter(String key){
String value = config.getInitParameter(key);
return value;
}
//獲得初始化引數的名稱;
public Enumeration getInitParamNames(){
return config.getInitParameterNames();
}
//獲得上下文環境物件:
public ServletContext getServletContext(){
return config.getServletContext();
}
}
深入這個類的目的:是為了讓別的類去繼承,那麼現在手寫一個類去繼承
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
public class BServlet extends MyGenericServlet {
//一堆: 實現Servlet的方式二:
//這是一個生命週期方法: 原因: 覆寫了父類的生命週期方法; 那麼父類的init方法單中所有的操作被覆蓋了。 引發了其他的方法不能被使用。
/*@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("xxxx");
}*/
@Override
public void init() {
// .....
}
}
如果重寫init方法的話:
這是一個生命週期方法: 原因-- 覆寫了父類的宣告週期方法; 那麼父類的init方法單中所有的操作被覆蓋了。 引發了其他的方法不能被使用。
那麼該如何解決呢?
在被繼承的父類Generic中寫一個過載的方法
//不是一個生命週期方法:
public void init(){
}
//生命週期方法:
@Override
public void init(ServletConfig config) throws ServletException {
this.config=config;
init();
}
這樣的話,子類再去繼承的時候,重寫無參的方法即可
方式三:繼承HttpServlet:
重點!!!!!! 與第二種實現方式的關係如下:
API文件中提到:必須去複寫其中一個方法
HttpServlet類:詳解:
HttpServlet類提供的自定義的方法: 不是生命週期的方法:
service(HttpServletReuqest request, HttpServletResponse response); //提供的方法:
在該方法當中, 可以獲得客戶端的請求方式, 根據不同的請求方式,做了具體的派發。
例如: get請求 : 呼叫doGet方法:
post請求: doPost方法:
原有的生命週期的方法; service(ServletRequest req, ServletResponse res)
在生命週期方法當中, 將req 強制轉換成了其子類物件, 呼叫了service方法(該類原始碼):
{
HttpServletRequest request;
HttpServletResponse response;
try
{
request = (HttpServletRequest)req;
response = (HttpServletResponse)res;
}
catch (ClassCastException e)
{
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
* 很多人在繼承這個類之後重寫方法的時候直接重寫的是service方法,既可以處理post,又可以處理get,但是壞處在於:父類已經給你給你完成的 (針對不同請求分類的派發操作) 會被複寫掉,不建議但是可以。
實現具體步驟如下:
(1)類 繼承HttpServlet。
(2)重寫doGet方法或者是doPost方法即可。
(3)配置: web.xml
補充 web.xml檔案中配置<context-param>和<init-param>的區別
{
<context-param>和<init-param>都是上下文引數,但它們的範圍和使用方式不同。
<context-param>是application範圍內的初始化引數,用於向servlet-context提供鍵值對,即應用程式的上下文資訊,listener、filter等初始化時會用到這些資訊
<init-param>是servlet範圍內的引數,只能在servlet類的init()方法中取得
來源:CSDN
原文:https://blog.csdn.net/blacktal/article/details/72843737?utm_source=copy
}
1 註冊 先寫class裡面的全路徑名稱 然後寫上面的 name 理論上任意,但規範是類名
2 寫下面的對映(以前寫過)
(4)訪問: \
程式碼如下:
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
* 實現三:
1)類 繼承HttpServlet。
(2)重寫doGet方法或者是doPost方法即可。
(3)配置: web.xml
(4)訪問: http://localhost:8080/javaEE-04/servlet/AServlet
*/
public class AServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("AServlet被建立了 並且完成了初始化");
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//獲得一個引數的值:
String value= this.getServletConfig().getInitParameter("username");
System.out.println(value);
System.out.println("============");
//獲得引數的名稱:
Enumeration<String> enumeration = this.getServletConfig().getInitParameterNames();
while(enumeration.hasMoreElements()){
String nextElement = enumeration.nextElement();// 引數的名稱:
String val = this.getServletConfig().getInitParameter(nextElement);
System.out.println(nextElement+" "+val);
}
System.out.println("============");
//獲得servlet的名稱:
String servletName = this.getServletConfig().getServletName();
System.out.println("servletName"+servletName);
//獲得上下文物件:
ServletContext servletContext = getServletConfig().getServletContext();
System.out.println("servletContext"+servletContext);
System.out.println("doget方法被執行了");
}
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("dopost方法被執行了");
}
}
注:以後凡是說servlet的都是指第三種實現方式的servlet。
Servlet的補充:
1: web的三大元件:
Servlet: 動態資源(作用是處理請求)
Filter : 過濾器
Listener: 監聽器
2:作用:
接收請求:
處理請求:
完成響應:
3: 初始化的方法,init service的方法, 引數都是來源於Tomcat伺服器。
Tomcat伺服器幫忙建立的。
4 :config 物件
config物件: 型別ServletConfig 介面
config 物件當中的方法:
java.lang.String getInitParameter(java.lang.String name)
Gets the value of the initialization parameter with the given name.
java.util.Enumeration<java.lang.String> getInitParameterNames()
Returns the names of the servlet's initialization parameters as an Enumeration of String objects, or an empty Enumeration if the servlet has no initialization parameters.
ServletContext getServletContext()
Returns a reference to the ServletContext in which the caller is executing.
java.lang.String getServletName()
Returns the name of this servlet instance.
Servlet的配置資訊都儲存在當前的物件中 具體哪些資訊如下:
ServletConfig 物件 : 對應Servlet的配置資訊------------
<servlet>
<servlet-name>FirstServlet</servlet-name>
<servlet-class>com.yidongxueyuan.web.servlet.FirstServlet</servlet-class>
<!-- 給出一些配置的引數 ,給出的初始化引數只能在當前的Servlet當中有效: -->
<init-param>
<param-name>encoding</param-name>
<param-value>gbk</param-value>
</init-param>
<init-param>
<param-name>encoding1</param-name>
<param-value>utf-8</param-value>
</init-param>
</servlet>
<!-- 對映 -->
<servlet-mapping>
<servlet-name>FirstServlet</servlet-name>
<url-pattern>/FirstServlet</url-pattern>
</servlet-mapping>
</web-app>