1. 程式人生 > >servlet的介紹 & xml中配置 以及 & 三種實現方式(補充設定瀏覽器不快取的方法)

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的時候,此時Servlet誕生。

第二次訪問不建立,所以說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>