1. 程式人生 > >JavaWeb之Servlet一

JavaWeb之Servlet一

nco throw paths nts 執行 有一個 相關 自動調用 ssi

作者:劉婧怡

時間:2019.03.27

主機環境:MacBookPro


Servlet

1. Servlet簡介

  • Servlet是JavaWeb的三大組件之一,屬於動態資源

  • Servlet的功能

    • 接受請求數據

    • 處理請求:每個Servlet都是唯一的,能處理的請求都是不同的

    • 完成響應

  • Servlet需要我們自己編寫

2. 實現Servlet的方式(三種)

  • 實現javax.servlet.Servlet接口

  • 繼承javax.servlet.GenericServlet類

  • 繼承javax.servlet.http.HttpServlet類,它是GenericServlet的子類

3. Servlet接口

  • 接口中的方法,生命周期方法是Tomcat自動調用的方法

publicclassMyServletimplementsServlet{
   
   //是生命周期方法
   //會在Servlet對象被創建後馬上執行,並只執行一次
   publicvoidinit(ServletConfigservletConfig) throwsServletException;
   
   //可以用來獲取Servlet的配置信息
   publicServletConfiggetServletConfig();
?
   //是生命周期方法
   
//會被調用多次 //每次處理請求都會被調用 publicvoidservice(ServletRequestservletRequest, ServletResponseservletResponse) throwsServletException, IOException; //可以獲取Servlet的信息 publicStringgetServletInfo(); //是生命周期方法 //會在Servlet被銷毀之前調用,並且只會被調用一次 //該方法不能銷毀Servlet publicvoiddestroy(); } ?
  • 在web.xml文件中配置Servlet

<servlet>
       <!--xxx可以隨便寫-->
       <servlet-name>xxx</servlet-name>
       <servlet-class>servlet.MyServlet</servlet-class>
</servlet>
?
<servlet-mapping>
       <servlet-name>xxx</servlet-name>
       <!--必須以/開頭,後面隨便寫-->
    <url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
  • ServletConfig接口 

    • 一個ServletConfig對象對應一段web.xml中的Servlet配置信息

    • API:

      • String getServletName():獲取<servlet.name>的內容

      • ServletContext getServletContext():獲取Servlet上下文的對象

      • String getInitParament():通過名稱獲取指定初始化參數的值

      • Enumeration getInitParamentName():獲取所有初始化參數的名稱

<servlet>
   <servlet-name>One</servlet-name>
   <servlet-class>cn.itcast.servlet.OneServlet</servlet-class>
   <init-param>
    <param-name>paramName1</param-name>
     <param-value>paramValue1</param-value>
   </init-param>
   <init-param>
     <param-name>paramName2</param-name>
     <param-value>paramValue2</param-value>
   </init-param>
 </servlet>

4. GenericServlet類

  • GenericServlet是Servlet接口的實現類,我們可以通過繼承GenericServlet來編寫自己的Servlet。

    下面是GenericServlet類的源代碼

public abstract class GenericServlet implements Servlet, ServletConfig,
        java.io.Serializable 
{
    private static final long serialVersionUID = 1L;
    
    private transient ServletConfig config;
    
    public GenericServlet() {}
    
    @Override
    public void destroy() {}
    
    @Override
    public String getInitParameter(String name) {
        return getServletConfig().getInitParameter(name);
    }
    
    @Override
    public Enumeration<String> getInitParameterNames() {
        return getServletConfig().getInitParameterNames();
    }
    
    @Override
    public ServletConfig getServletConfig() {
        return config;
    }
    
    @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 {}
    
    public void log(String msg) {
        getServletContext().log(getServletName() + ": " + msg);
    }
    
    public void log(String message, Throwable t) {
        getServletContext().log(getServletName() + ": " + message, t);
    }
    
    @Override
    public abstract void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException;
            
    @Override
    public String getServletName() {
        return config.getServletName();
    }
}
  • init()方法

    • init()方法是用來在繼承GenericServlet類時,解決想要覆蓋init(ServletConfig config)方法忘記給config賦值的問題。此時,只需要覆蓋init()方法即可。

    • init()方法不是生命周期方法,但想要在構造Servlet時讓Tomcat調用該方法,需要在init(ServletConfig config)中調用init()方法

  • GenericServlet實現了所有ServletConfig的方法。

5. HttpServlet類

  • HttpServlet是GenericServlet的子類,它提供了對HTTP請求的特殊支持,所以通常我們都會通過繼承HttpServlet來完成自定義的Servlet。

  • HttpServlet覆蓋了service()方法

    • HttpServlet中有兩個service()方法,一個service(ServletRequest,ServletResponse),另一個為service(HttpServletRequest,HttpServletResponse),前者為覆蓋,後者不是覆蓋。

    • service(ServletRequest,ServletResponse)是生命周期方法,由Tomcat自動調用,在該方法中

      • 首先對兩個參數強制轉換,將類型轉換為Http協議相關的類型,

      • 再調用service(HttpServletRequest,HttpServletResponse)方法,

      • 該方法會通過request得到當前請求的請求方式(GET或POST),

      • 再根據請求方式調用相應的doGet()和doPost()方法。

    • 所以,不用重寫service()方法只需要重寫doGet()和doPost()方法如果沒有覆蓋doGet()和doPost()方法,並且被調用了,會出現405。

6. Servlet細節

  • Servlet只有一個實例對象,就有可能會現時出一個Servlet同時處理多個請求

    Servlet不是線程安全的。這說明Servlet的工作效率很高,但也存在線程安全問題!所以我們不應該在Servlet中隨便創建成員變量,因為可能會存在一個線程對這個成員變量進行寫操作,另一個線程對這個成員變量進行讀操作。

    做到以下幾點:

    • 不要在Servlet中創建成員,創建局部變量即可

    • 可以創建無狀態成員,即只聲明

    • 可以創建有狀態的成員,但狀態必須為只讀的

  • 默認情況下,服務器會在某個Servlet第一次收到請求時創建它。也可以在web.xml中對Servlet進行配置,使服務器啟動時就創建Servlet。

<servlet>
<servlet-name>hello1</servlet-name>
<servlet-class>cn.itcast.servlet.Hello1Servlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello1</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
?
<servlet>
<servlet-name>hello2</servlet-name>
<servlet-class>cn.itcast.servlet.Hello2Servlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>

  <load-on-startup>中,給出一個非負整數。值小的先被創建,即hello1先創建,hello2後創建。

  • <url-pattern>

    • 用來指定Servlet的訪問路徑,可以在<servlet-maping>中有多個

    • 可以使用通配符*,通配符要麽為前綴,要麽為後綴,不能出現在URL中間位置,也不能只有通配符

      路徑匹配:<url-pattern>/servlet/*</url-pattern>,可以匹配/servlet/a、/servlet/b等

      擴展名匹配:<url-pattern>*.do</url-pattern>,可以匹配/abc/def/ghi.do、/a.do等

      啥都匹配:<url-pattern>/*</url-pattern>,可以匹配所有url

  • web.xml文件的“繼承”

    • 每一個JavaWeb應用都有一個web.xml,都“繼承”conf/web.xml

<?xmlversion="1.0" encoding="ISO-8859-1"?>
?
<web-appxmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                     http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
 version="3.0">
    <servlet>
       <servlet-name>default</servlet-name><!--他的優先級最低,如果請求沒人處理,那麽它就會來處理,顯示404-->
       <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
       <init-param>
           <param-name>debug</param-name>
           <param-value>0</param-value>
       </init-param>
       <init-param>
           <param-name>listings</param-name>
           <param-value>false</param-value>
       </init-param>
       <load-on-startup>1</load-on-startup>
</servlet>
?
   <servlet>
       <servlet-name>jsp</servlet-name>
       <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
       <init-param>
           <param-name>fork</param-name>
           <param-value>false</param-value>
       </init-param>
       <init-param>
           <param-name>xpoweredBy</param-name>
           <param-value>false</param-value>
       </init-param>
       <load-on-startup>3</load-on-startup>
   </servlet>
?
   <servlet-mapping>
       <servlet-name>default</servlet-name>
       <url-pattern>/</url-pattern>  <!--沒有url能匹配上,就會匹配這個-->
   </servlet-mapping>
?
   <servlet-mapping>
       <servlet-name>jsp</servlet-name>
       <url-pattern>*.jsp</url-pattern>
       <url-pattern>*.jspx</url-pattern>
   </servlet-mapping>
?
   <session-config>  <!--session的過期時間為30分鐘-->
       <session-timeout>30</session-timeout>
   </session-config>
?
<!-- 這裏省略了大概4000多行的MIME類型的定義,這裏只給出兩種MIME類型的定義 -->
   <mime-mapping>
       <extension>bmp</extension>
       <mime-type>image/bmp</mime-type>
   </mime-mapping>
   <mime-mapping>
       <extension>htm</extension>
       <mime-type>text/html</mime-type>
   </mime-mapping>
?
   <welcome-file-list>
       <welcome-file>index.html</welcome-file>
       <welcome-file>index.htm</welcome-file>
       <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>
</web-app>
 

7. ServletContext

  • 概述

    • 一個項目只有一個ServletContext對象,我們可以在很多個Servlet中來獲取這個唯一的對象,使用它可以給Servlet傳遞數據,完成共享數據。

    • ServletContext對象在Tomcat啟動時創建,在Tomcat關閉時銷毀

  • 獲取ServletContext

    在Servlet接口中,init(ServletConfig config)方法可以獲取ServletConfig對象,該對象有getServletContext()方法可以獲取ServletContext對象

public class MyServlet implements Servlet {
    public void init(ServletConfig config) {    
        ServletContext context = config.getServletContext();
    }
    …
}    
  在GenericServlet類中,有成員變量ServletConfig,有getServletContext()方法可以獲取ServletContext對象
public class MyServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
    ServletContext context = this.getServletContext();
  }
}
  • 域對象的功能

    • 域對象是用來在多個Servlet中傳遞數據,所以域對象必須要有存和取數據的功能。JavaWeb中包含四個域對象,分別是ServletContext、PageContext、HttpSession、ServletRequest

    • ServletContext對象用來操作數據的方法

      • void setAttribute(String name, Object value):用來存儲一個對象,相當於在ServletContext中有一個Map對象,所以在存儲時name值不能相同

      • Object getAttribute(String name):用來獲取數據,因為返回值為Object對象,需要強制轉換

      • void removeAttribute(String name):刪除一個對象

      • Enumeration getAttributeNames():獲取所有域屬性的名稱

  • 獲取初始化參數

    • Servlet也可以獲取初始化參數,但它只能獲取局部的初始化參數,即只能獲取自己的初始化參數

    • 使用ServletContext可以配置公共的初始化參數

<web-app...>
...
 <context-param>
<param-name>paramName1</param-name>
<param-value>paramValue1</param-value>
 </context-param>
 <context-param>
<param-name>paramName2</param-name>
<param-value>paramValue2</param-value>
 </context-param>
</web-app>
ServletContext context = this.getServletContext();
String value1 = context.getInitParameter("paramName1");
String value2 = context.getInitParameter("paramName2");
System.out.println(value1 + ", " + value2);
  • 獲取相關資源的方法

    • 獲取真實路徑

      • 獲取a.txt的真實路徑String realPath = this.getServletContext.getRealPath("/a.txt");

      • windows系統下這種方法獲取的路徑是代盤符的

    • 獲取資源流

      • 獲取a.txt的t資源流:InputStream in = this.getServletContext.getResourceAsStream("/a.txt");

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

      • 獲取/WEB-INF下所有資源的路徑:Set set = this.getServletContext.getResourcePaths("/WEB-INF");

JavaWeb之Servlet一