JavaWeb學習筆記三 Servlet


Servlet 是運行在服務端的Java小程序,是sun公司提供一套規范(接口),用來處理客戶端請求、響應給瀏覽器的動態資源。但servlet的實質就是java代碼,通過java的API,動態的向客戶端輸出內容。

servlet規范:包含三個技術點,它們是 servlet技術;filter(過濾器)技術;listener(監聽器)技術。

Servlet快速入門

實現步驟:

  1. 創建類實現Servlet接口
  2. 覆蓋尚未實現的方法---service方法
  3. 在web.xml進行servlet的配置

但在實際開發中,我們不會直接去實現Servlet接口,因為那樣需要覆蓋的方法太多, 我們一般創建類繼承HttpServlet。

實現步驟:

  1. 創建類繼承HttpServlet類
  2. 覆蓋doGet和doPost
  3. 在web.xml中進行servlet的配置

畫圖描述整個訪問過程:

 

 下面來看看Servlet長什么樣子

代碼演示:

public class AServlet extends HttpServlet { }

發現HttpServlet在IDEA中不能導包,百度了一下,IntelliJ IDEA 沒有導入 servlet-api.jar 這個jar包,需要你手動導入支持。具體導包過程如下:

點擊右上方那個藍色按鈕(project structure 項目結構)——>點擊Libraries——>點擊上面的加號——>點擊Java

然后再彈出框中找到Tomcat安裝路徑下的lib文件夾中的Servlet.api這個文件,添加就好了。

在Intellij idea中快速重寫HttpServlet

鼠標左擊以確定代碼插入的位置,使用快捷鍵CTRL+O,會彈出窗口讓選擇某個方法,我們選擇覆蓋doGet和doPost方法,然后輸出一句話。

package servletDemo; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * Created by Administrator on 2017/7/21. */
public class AServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("My First Servlet"); } }
AServlet

配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
    <servlet>
        <servlet-name>AServlet</servlet-name>
        <servlet-class>servletDemo.AServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>AServlet</servlet-name>
        <url-pattern>/AServlet</url-pattern>
    </servlet-mapping>
</web-app>
web.xml

運行報錯:Tomcat啟動服務報錯:Unknown version string [3.1]. Default version will be used.解決方式參考這里

然后運行,在瀏覽器輸入:http://localhost:8080/AServlet,界面出現:

My First Servlet

到此,我們的第一個Servlet就成功了。

 Servlet的API(生命周期)

Servlet接口中的方法

package servlet.demo; import javax.servlet.*; import java.io.IOException; /** * Created by yang on 2017/7/23. */
public class SecondServlet implements Servlet { @Override public void init(ServletConfig servletConfig) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }
SecondServlet .java
  • init(ServletConfig config):servlet對象創建的時候執行,ServletConfig 代表的是該servlet對象的配置信息
  • service(ServletRequest request,ServletResponse response):每次請求都會執行

ServletRequest :代表請求,ServletRequest 內部封裝的是 http請求的信息

ServletResponse :代表響應,封裝的是響應的信息

  • destroy():servlet銷毀的時候執行
  • getServletInfo: 獲得servlet的信息(版本,作者,版權..),沒什么用.
  • getServletConfig:返回servletConfig對象.

 HttpServlet類的方法

package servlet.demo; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Created by yang on 2017/7/23. */
public class ServletDemo03 extends HttpServlet{ @Override public void init(ServletConfig config) throws ServletException { super.init(config); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doGet(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } @Override public void destroy() { super.destroy(); } }
ServletDemo03
  • init()
  • doGet(HttpServletRequest request,HttpServletResponse response)
  • doPost(HttpServletRequest request,HttpServletResponse response)
  • destroy()

Servlet的生命周期

Servlet何時創建?默認第一次訪問servlet時創建該對象

Servlet何時銷毀?服務器關閉servlet就銷毀了

每次訪問必然執行的方法?service(ServletRequest req, ServletResponse res)方法

問題:對XXXServlet進行了10次訪問,init(),destory(),service(),doGet(),doPost() 一共執行力多少次?request對象創建幾個?response創建幾個?

答案:init(),1次;destory(),服務器沒有關閉, 不執行;service(),10次;request對象創建10個;response創建10個

Servlet的配置

基本配置

其中url-pattern的配置方式:

  • 完全匹配 訪問的資源與配置的資源完全相同才能訪問到

  • 目錄匹配 格式:/虛擬的目錄../* ,*代表任意

  • 擴展名匹配 格式:*.擴展名

注意:1、關於路徑,配置的路徑匹配范圍越大優先級越低;2、目錄匹配與擴展名匹配不要混用,比如: /aaa/bbb/*.abcd(這是錯誤的)

ServletConfig對象

ServletConfig封裝了servletweb.xml中的配置.

比如web.xml參數配置如下:

<init-param>
    <param-name>name</param-name>
    <param-value>tom</param-value>
</init-param>

方法:

//獲得servlet的name(獲得配置文件中<servlet-name>元素的內容) String servletName =getServletConfig().getServletName(); //獲取init-param中的所有參數(返回所有<param-name> ) Enumeration<String> en = getServletConfig().getInitParameterNames(); while(en.hasMoreElements()){   String key = en.nextElement();   //根據鍵獲取值(根據<init-param>中的<param-name>獲得</param-value>
  String value = getServletConfig().getInitParameter(key);)   res.getWriter().print(key+"==>"+value+"<br/>"); }

服務器啟動實例化Servlet配置

Servlet何時創建:默認第一次訪問時創建。為什么是默認?當在servlet的配置時,加上一個配置 <load-on-startup> ,servlet對象在服務器啟動時就創建。

 <servlet>
    <servlet-name>abc</servlet-name>
    <servlet-class>com.itheima.servlet.QuickStratServlet</servlet-class>
    <init-param>
      <param-name>url</param-name>
      <param-value>jdbc:mysql:///mydb</param-value>
    </init-param>
  <load-on-startup>3</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>abc</servlet-name>
    <url-pattern>/quickStratServlet</url-pattern>
  </servlet-mapping>

1、load-on-startup元素標記容器是否在啟動的時候就加載這個servlet(實例化並調用其init()方法)。

2、它的值必須是一個整數,表示servlet應該被載入的順序

3、當值為0或者大於0時,表示容器在應用啟動時就加載並初始化這個servlet;

4、當值小於0或者沒有指定時,則表示容器在該servlet被選擇時才會去加載。

5、正數的值越小,該servlet的優先級越高,應用啟動時就越先加載。

6、當值相同時,容器就會自己選擇順序來加載。

所以,<load-on-startup>x</load-on-startup>,中x的取值1,2,3,4,5代表的是優先級,而非啟動延遲時間。欲知更多請參考這里

缺省Servlet

可以將url-pattern配置一個/,代表該servlet是缺省的servlet。什么是缺省的servlet?當你訪問資源地址所有的servlet都不匹配時 , 缺省的servlet負責處理。其實,web應用中所有的資源的響應都是servlet負責,包括靜態資源。

歡迎頁面

 

ServletContext對象

ServletContext代表的是一個web應用的環境(上下文)對象,ServletContext對象內部封裝是該web應用的信息,ServletContext對象一個web應用只有一個。那么一個web應用有幾個servlet對象?很多個。

ServletContext對象的生命周期

創建:該web應用被加載(服務器啟動或發布web應用(前提,服務器為啟動狀態))

銷毀:web應用被卸載(服務器關閉,移除該web應用)

獲得ServletContext對象

1、ServletContext servletContext = config.getServletContext();

2、ServletContext servletContext = this.getServletContext();

ServletContext的作用

1、獲得web應用全局的初始化參數,方法:

getInitParameterNames();  ==> 獲得所有鍵 getInitParameter(key); ==> 根據鍵獲得對應的值

比如:web.xml中配置初始化參數

 <!--配置全局的初始化參數-->
    <context-param>
        <param-name>driver</param-name>
        <param-value>com.mysql.jdbc.Driver</param-value>
    </context-param>

則可以通過context對象獲得參數 

ServletContext context= getServletContext(); String initValue= context.getInitParameter("driver"); resp.getWriter().print(initValue);//com.mysql.jdbc.Driver

2、獲得web應用中任何資源的絕對路徑,此功能很重要。方法:

getRealPath  ==> 通過相對路徑獲得絕對路徑 getResourceAsStream ==> 根據相對路徑獲得指定資源流

context.getRealPath(相對於該web應用的相對地址);

ServletContext sc = getServletContext(); //getResourceAsStream ==> 填寫相對路徑即可, 相對的是webRoot下
InputStream is = sc.getResourceAsStream("/WEB-INF/students.xml"); System.out.println(is);//java.io.ByteArrayInputStream@2d83e895
 String path = sc.getRealPath("/WEB-INF/students.xml"); System.out.println(path);
//F:\編程語言\Java\Project\Tools\apache-tomcat-7.0.52\webapps\Day07-servlet\WEB-INF\students.xml Set set = sc.getResourcePaths("/"); for(Object obj : set){ System.out.println(obj); } // /index.jsp // /WEB-INF/ // /MyHtml.html // /META-INF/

String path2= sc.getResource("/WEB-INF/students.xml").getPath(); System.out.println(path2); //  /localhost/Day07-servlet/WEB-INF/students.xml
//獲得lib目錄下的資源
getServletContext().getRealPath("/WEB-INF/lib/students.xml"); //獲得src下的資源==> 獲得classes目錄下的資源
getServletContext().getRealPath("/WEB-INF/classes/students.xml"); //獲得cn.itcast.servlet.servlet_context包下的資源
getServletContext().getRealPath("/WEB-INF/classes/cn/itcast/servlet/servlet_context/students.xml"); //--------------------------------------------------------------------------- //如果獲得的是包下的,那么使用上面的方式太麻煩了.可以使用以下方式: //一:使用getClass().getResourceAsStream方法,相對路徑分為兩種情況 //1: 加"/" ==> 相對的是classes目錄 //2: 不加"/" ==>相對的是本類當前目錄
InputStream is = this.getClass().getResourceAsStream("students.xml"); System.out.println(is); 
//二:使用this.getClass().getClassLoader().getResourceAsStream("");獲得 //只有一個相對路徑 ==> 就是相對於 classes目錄 InputStream is2 = this.getClass().getClassLoader().getResourceAsStream("students.xml"); System.out.println(is2); //注意:
//1、使用類和類加載器加載資源文件時,
jvm運行期間只加載一次.一旦加載完畢后,就會存放在虛擬機內存中,直到虛擬機關閉,所以文件路徑更改,也還是之前的路徑,可以使用下面的代碼可以解決這個問題. String path = this.getClass().getClassLoader().getResource("students.xml").getPath(); File file = new File(path.substring(1, path.length())); System.out.println(path); //getClassLoader()原本是用來加載.class文件的, 所以緩存設計的很小.不要用他加載一些別較大的資源.

3、ServletContext是一個域對象,此功能很重要。

什么是域對象?什么是域?存儲數據的區域就是域對象。

ServletContext域對象的作用范圍是整個web應用(所有的web資源都可以隨意向 servletcontext域中存取數據,數據可以共享)

域對象的通用的方法

放入鍵值對 setAttribute(key,value)
通過鍵取值 getAttribute(key)
通過鍵刪除 removeAttribute(key)
遍歷所有鍵 getAttributeNames()
//通過servletContext設置值
sc.setAttribute("bag", "Calvin Klein"); sc.setAttribute("car", "BMW"); sc.setAttribute("passport", "HAWAII"); //通過servletContext取值
String bag = (String) sc.getAttribute("bag"); //不喜歡,扔掉(刪除)
sc.removeAttribute("bag"); //遍歷
Enumeration<String> en = sc.getAttributeNames(); while(en.hasMoreElements()){ String key = en.nextElement(); Object value = sc.getAttribute(key); System.out.println(key +"==>"+value); } 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM