http協議以及Servlet

http協議以及Servlet

1.1 http協議

協議:是指雙方按照一定的規則進行某種行爲

http協議:(超文本傳輸協議)定義了瀏覽器域服務器之間的相互通信的規則

請求協議:瀏覽器端發送給服務器端

響應協議:服務器端發送給瀏覽器端


1.1.1 http之請求協議

請求格式如下,如果瀏覽器不按照這個格式服務器將無法識別

 

請求格式:

請求首行;

請求頭信息;

空行;

請求體;


GET /javaWEB1/index.jsp HTTP/1.1 //請求方式爲GET請求,路徑是javaWEB1/index.jsp 協議版本1.1

Accept: text/html, application/xhtml+xml, */* //接受參數類型*/*表示所有

Accept-Language: zh-CN  //接受語言是中文

User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)  //瀏覽器版本,操作系統類型

Accept-Encoding: gzip, deflate  //接受編碼,壓縮以及解壓縮

Host: localhost:8888   //主機名稱 

Connection: Keep-Alive //連接狀態  存活

Cookie: JSESSIONID=03A34AAB1E01103D443520A7F0B88DC5 //後面再講

//空格

 

1、GET/javaWEB1/index.jsp HTTP/1.1 //請求方式爲GET請求,路徑是javaWEB1/index.jsp 協議版本1.1

2、Host:localhost:8888   請求主機名爲localhost,端口號爲8888

3、User-Agent  發送一些關於瀏覽器的信息給服務器,例如瀏覽器版本,操作系統的版本等。



1.1.2 http之響應協議

響應協議格式如下:

響應首行;

響應頭信息;

空行;

    響應體。

 

在剛纔的JavaWEB中服務器響給瀏覽器的內容如下

HTTP/1.1 200 OK  //協議版本  狀態碼  狀態碼的解釋

Server: Apache-Coyote/1.1  //服務器名稱

Content-Type: text/html;charset=UTF-8 //文本類型以及編碼

Content-Length: 619  //文本大小

Date: Thu, 08 Jun 2017 02:58:18 GMT  //時間

//空格

 

 

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">//響應體

<html>

 ............響應具體內容........

</html>

1、HTTP/1.1 200OK:表示協議版本號爲1.1版本,狀態碼爲200,表示請求成功,OK是對狀態碼的解釋

2、Server:Apache-Coyote/1.1:服務器的名稱

3、Content-Type:text/html;charset=UTF-8:響應文本類型以及編碼格式

響應協議狀態碼所表示的含義:

200:表示請求成功

404:表示資源路徑沒有找到

405:請求的方式有問題(get、post等)

500:表示服務器的錯誤

302:表示重定向(服務器沒有資源,提供一個url地址給瀏覽器訪問)

 

 

1.2 Servlet組件

Servlet是我們JavaWeb三大組件之一,(Servlet和filter、listener),Servlet屬於動態資源,服務器將瀏覽器發出的請求交給servlet來處理。接收請求數據,處理請求信息,完成響應。




一句話總結:servlet處理瀏覽器的請求,並且處理請求然後完成對瀏覽器的響應

注意:

一個功能的Servlet只能被Tomcat創建一次,很多次訪問都是訪問同一個Servlet(線程不安全)

 

實現Servlet的三種方式:

1.實現Servlet接口

2.繼承GenericServlet類

3.繼承HttpServlet類(重點掌握,常用)



1.2.1 Servlet接口

1.2.1.1 Servlet的實現方法

我們在新建類時實現Servlet接口,將會在servlet中實現如下方法

 

@Override

   public void destroy() {

   }

 

   @Override

   public ServletConfig getServletConfig() {

      return null;

   }

 

   @Override

   public String getServletInfo() {

      return null;

   }

 

   @Override

   public void init(ServletConfig arg0) throws ServletException {

   }

 

   @Override

   public void service(ServletRequest arg0, ServletResponse arg1)

          throws ServletException, IOException {

   }

 

注意:

在servlet大部分的方法都是由服務器,即tomcat來調用,並且方法中的類類型參數,也就是對象也是由服務器來創建,服務器已經將固化代碼寫入,我們只需寫其中的邏輯實現,直接使用即可。


1.2.1.1.1 Servlet中的生命週期

Method Summary

 void

destroy()  ---銷燬,服務器關閉時調用此方法
          由servlet容器調用,以指示servlet被停用的servlet。

 ServletConfig

getServletConfig()
          返回一個ServletConfig對象,該對象包含該servlet的初始化和啓動參數。

String

getServletInfo()
          返回有關servlet的信息,如作者、版本和版權。

 void

init(ServletConfig config)  ---初始化,瀏覽器第一次訪問servlet時調用
          由servlet容器調用,以指示servlet被放置到服務中的servlet。

 void

service(ServletRequest req,ServletResponse res)
          由servlet容器調用,以允許servlet響應請求。

 

void init(ServletConfig config) 在Servlet被創建後,服務器會馬上調用Servlet的void init(ServletConfig)方法。 Servlet出生後馬上就會調用init()方法,而且一個Servlet的一生。這個方法只會被調用一次。(該方法裏面會放一些初始化的參數)

服務器會在servlet第一次被調用時來創建servlet對象,並且一個servlet只被創建一個對象

 

 

void service(ServletRequest req,ServletResponse res) 用於處理瀏覽器請求的,服務器接受一次請求就會調用一次service();--每次訪問都會調用一次

 

void destroy() :在服務器關閉時Servlet纔會離去!在服務器被關閉時,服務器會去銷燬Servlet,在銷燬Servlet之前服務器會先去調用Servlet的destroy()方法。(釋放一些非內存資源,比如IO流的關閉,但是通常不會將其放在這個方法中)



1.2.1.1.2 Servlet中的參數

1、ServletConfig一個ServletConfig對應一段web.xml文件中的<servlet>元素每個servlet都有自己的ServletConfig

ServletConfig對象對應web.xml文件中的<servlet>元素。例如你想獲取當前Servlet在web.xml文件中的配置名,那麼可以使用servletConfig.getServletName()方法獲取!

ServletConfig本身來講是一個接口,具體的實現類是由tomcat來完成的,這並不是我們所關心的問題

ServletConfig中提供方法有

Method Summary

String

getInitParameter(java.lang.String name)
          獲取帶有給定名稱的初始化參數的值。

Enumeration<java.lang.String>

getInitParameterNames()
         返回servlet初始化參數的名稱作爲字符串對象的枚舉,或者如果servlet沒有初始化參數,則返回空的枚舉。

 ServletContext

getServletContext()
          返回調用者正在執行的ServletContext的引用。

String

getServletName()
          返回該servlet實例的名稱。

 

1.getInitParameter( String name) 可以獲取初始化參數值

2.getInitParameterNames() 獲得一個存有所有param-name值的枚舉集合

3.getServletContext() 獲取上下文

4.getServletName() 獲取servlet名稱(不用)



web.xml文件配置:

  <servlet>

    <servlet-name>BServlet</servlet-name> //表示給該servlet一個名字用於標識

    <servlet-class>com.edu118.servlet.BServlet</servlet-class> //servlet所在的路徑

    <init-param>

      <param-name>p1</param-name>

      <param-value>v1</param-value>

    </init-param>

    <init-param>

      <param-name>p2</param-name>

      <param-value>v2</param-value>

    </init-param>

  </servlet>

  <servlet-mapping>

    <servlet-name>BServlet</servlet-name>

    <url-pattern>/BServlet</url-pattern> //映射一個URL地址讓瀏覽器訪問,必須以“/”開始對命名規範沒有要求

 

  </servlet-mapping>

 

<!--瀏覽器訪問地址:http://localhost:8080/day02/BServlet -->

 

public void init(ServletConfig config)throws ServletException {

      String parameter = config.getInitParameter("p1");

      System.out.println(parameter);

      System.out.println("---------------");

     

      Enumeration<String> parameterNames =config.getInitParameterNames();

      //迭代器遍歷

      while(parameterNames.hasMoreElements()){

         System.out.println(config.getInitParameter(parameterNames.nextElement()));

      }

   }

結果:

v1

---------------

v1

v2

 

2、ServletRequestServletResponse是Servlet#service() 方法的兩個參數,一個是請求對象,一個是響應對象,可以從ServletRequest對象中獲取請求數據,可以使用ServletResponse對象完成響應。你以後會發現,這兩個對象就像是一對恩愛的夫妻,永遠不分離,總是成對出現

 

Request

a)       String s = httprquest.getLocalAddr();  --獲取瀏覽器訪問服務器的ip地址

b)      String name = httprquest.getMethod(); --獲取訪問的方式(get或post等)

 

Response

a)    getWriter():獲取字符響應流,使用該流可以向客戶端輸出響應信息。例如response.getWriter().print(“<h1>HelloJavaWeb!</h1>”);

b)    void setCharacterEncoding(String encoding):用來設置字符響應流的編碼


1.2.2 GenericServlet類

源碼

 

public abstract class GenericServlet implements Servlet, ServletConfig,

        java.io.Serializable {

 

    private static final long serialVersionUID = 1L;

 

private transient ServletConfig config;

 

    public GenericServlet() {

        // NOOP

    }

    @Override

    public void destroy() {

        // NOOP by default

    }

    @Override

    public String getInitParameter(Stringname) {

        return getServletConfig().getInitParameter(name);

}

 

    @Override

    public Enumeration<String> getInitParameterNames() {

        return getServletConfig().getInitParameterNames();

    }

    @Override

    public ServletConfig getServletConfig() {

        returnconfig;

    }

    @Override

    public ServletContext getServletContext() {

        return getServletConfig().getServletContext();

    }

 

 

 

    @Override

    public String getServletInfo() {

        return"";

}

 

    @Override

    public void init(ServletConfig config)throws ServletException {

        this.config =config;

        this.init();

    }

 

    public void init() throws ServletException {

        // NOOP by default

    }

 

 

    public void log(String msg) {

        getServletContext().log(getServletName() + ": " + msg);

    }

    public void log(String message, Throwablet) {

        getServletContext().log(getServletName() + ": " + message, t);

    }

 

 

    @Override

    public abstract void service(ServletRequestreq, ServletResponse res)

            throws ServletException, IOException;

 

    @Override

    public String getServletName() {

        returnconfig.getServletName();

    }

}

 

模擬GenericServlet類

public class EServlet implements Servlet {

   //定義一個全局變量,使繼承EServlet的類都可以使用

   private ServletConfigconfig;

   //初始化

   public void init(ServletConfig config)throws ServletException {

      this.config =config;

      /*

       * init初始化進行補充,讓繼承EServlet的類可以再次實現對servlet的初始化

       * 並且不影響config這個變量

       */

      init();

   }

  

   public void init() {

 

   }

   //重寫ServletConfig接口中的方法

   //對接口中的方法進行實現

   public Enumeration<String> getInitParameterNames() {

      return getServletConfig().getInitParameterNames();

     

   }

  

   public String getInitParametername(Stringname){

      return getServletConfig().getInitParameter(name);

   }

  

   public ServletContext getServletContext(){

      return getServletConfig().getServletContext();

     

   }

  

   public String getServletName(){

      return getServletConfig().getServletName();

   }

   public ServletConfig getServletConfig() {

      // TODO Auto-generated method stub

      return null;

   }

 

   public void service(ServletRequest req, ServletResponseres) throws ServletException, IOException {

      // TODO Auto-generated method stub

     

   }

 

   public String getServletInfo() {

      // TODO Auto-generated method stub

      return null;

   }

 

   public void destroy() {

      // TODO Auto-generated method stub

     

   }

  

}


1.2.3 HttpServlet類

HttpServlet是對GenericServlet的一個繼承,它除了有GenericServlet的service(ServletRequest,ServletResponse)方法之外,還有自身的service(HttpServletRequest,HttpServletResponse)來對Http協議的支持。

 

protected  void

service(HttpServletRequest req,HttpServletResponse resp)
          Receives standard HTTP requests from the public service method and dispatches them to thedoXXX methods defined in this class.

 void

service(ServletRequest req,ServletResponse res)
          Dispatches client requests to the protected service method.

 

 

Httpservlet的工作流程如下:

1.瀏覽器發出請求,服務器首先會運行生命週期方法service

2.然後將service(ServletRequest,ServletResponse)強轉爲支持http的servlet

3.獲取請求方法,根據請求方式來調用doGet還是doPost方法(這兩個方法是由我們自己來覆蓋的,需要注意的是當請求方式在servlet沒有對應的方法複寫會出現405錯誤)



1.3 ServletContext域

ServletContext是JavaWeb四大域之一,每一個項目都有且只有一個ServletContext,作用範圍是整個web項目用於不同的servlet之間進行通信的。可以在不同的servlet中來獲取這個ServletContext從而到達共享數據的目的,在服務器啓動的時候被創建,在服務器關閉的時候被銷燬。




1.3.1 ServletContext域對象的獲取

因爲我們新建的servlet類都是繼承自HttpServlet類,而HttpServlet類繼承自GnericServlet類,GenericServlet類中有getServletContext()的方法來獲取ServletContext對象。所以可以直接使用this.getServletContext()獲取


1.3.2 ServletContext的域功能

四個功能方法:

 

1、voidsetAttribute(String name,Object value):

void setAttribute(String name,Object value):存儲數據

設置域屬性以及域屬性的值。域屬性的名稱爲name,域屬性的值爲value。如果多次調用該方法設置相同的name域屬性名稱,那麼會覆蓋上一次設置的值。

 

2、ObjectgetAttribute(String name):

Object getAttribute(String name):獲取數據

    通過域屬性的名稱name獲取對應的域屬性值value,如果域對象中沒有該域屬性,會自動幫你創建該域屬性。-->String value =(String)ServletContext.getAttribute(name);

 

3、voidremoveAttribute(String name):

void removeAttribute(String name):用來移除ServletContext對象中的域屬性

 

4、Enumeration<String>getAttributeNames():

Enumeration<String> getAttributeNames():獲取所有域屬性的名稱。

    返回的是一個枚舉集合,通過迭代器進行迭代。使用方法與Vector的迭代方式一樣。




1.3.3 ServletContext獲取資源的相關路徑

1.3.3.1 獲取真實路徑

String getRealPath(): 獲取與給定的虛擬路徑相對應的真實路徑。

 

獲取a.txt的真實路徑:

String realPath= servletContext.getRealPath(“/a.txt”);

(realPath的值爲a.txt文件的絕對路徑:F:\tomcat6\webapps\hello\a.txt;)



1.3.3.2 獲取資源流

獲取a.txt資源流:

InputStream in =servletContext.getResourceAsStream(“/a.txt”);

 

獲取b.txt資源流:

InputStream in =servletContext.getResourceAsStream(“/WEB-INF/b.txt”);

 

獲取指定目錄下所有資源路徑:

Set set =context.getResourcePaths("/WEB-INF");

       System.out.println(set);

 

注意本方法必須以“/”開頭!!!

 

訪問網站統計訪問量的小案例:

@Override

   protected void doGet(HttpServletRequest req, HttpServletResponseresp) throws ServletException, IOException {

      // 獲得ServletContext域對象

      ServletContext context =this.getServletContext();

      // 獲得一個屬性,如果這個屬性沒有就自動幫你創建

      Integer countNum = (Integer)context.getAttribute("count");

      // 判斷是否是第一次訪問網站

      if (countNum ==null) {

          //設置屬性值

          context.setAttribute("count", 1);

//        count = (Integer)context.getAttribute("count");

      } else {

          context.setAttribute("count",countNum++);

      }

      //更新了屬性值然後重新賦值

      countNum = (Integer)context.getAttribute("count");

      // 輸出一下

      System.out.println(countNum);

      PrintWriter writer = resp.getWriter();

      writer.println("<h1>" +countNum + "</h1>");

   }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章