日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jsp调用servlet_宇宙最全Servlet详解!!

發布時間:2023/12/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jsp调用servlet_宇宙最全Servlet详解!! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第五章:Servlet

定義:

Servlet簡介:

  Servlet是sun公司提供的一門用于開發動態web資源的技術。

  Sun公司在其API中提供了一個servlet接口,用戶若想用發一個動態web資源(即開發一個Java程序向瀏覽器輸出數據),需要完成以下2個步驟:  1、編寫一個Java類,實現servlet接口?! ?、把開發好的Java類部署到web服務器中。

按照一種約定俗成的稱呼習慣,通常我們也把實現了servlet接口的java程序,稱之為Servlet。

總的來講:運行在Servlet容器中的Java類,可以接受請求并產生響應,是MVC思想的控制層=

那Servlet和我們之前編寫的do_XXX.jsp有啥區別?

如Test.jsp在運行時首先解析成一個Java類Test_jsp.java,而這個Test_jsp.java繼承于org.apache.jasper.runtime.HttpJspBase類,而HttpJspBase又是繼承自HttpServlet的類,由此可以得出一個結論,就是JSP在運行時會被Web容器翻譯為一個Servlet

也可以打開Servlet源碼來查看一下基礎關系圖:

[面試題]:

jsp和Servlet有啥區別?

jsp頁面繼承于org.apache.jasper.runtime.HttpJspBase類,而HttpJspBase又是繼承自HttpServlet的類,由此可以得出一個結論,就是JSP在運行時會被Web容器翻譯為一個Servlet,他們本質上都是同一個東西,只不過jsp注重頁面的顯示,Servlet更注重流程的控制。

servlet體系結構:

servlet的生命周期:

![](images\servlet2.png)

Servlet運行過程圖:

servlet接口里面的方法:

servlet的生命周期:

servlet體系結構:

![](images\servlet5.png)

其中,init( ),service( ),destroy( )是Servlet生命周期的方法。代表了Servlet從“出生”到“工作”再到“死亡 ”的過程。Servlet容器(例如TomCat)會根據下面的規則來調用這三個方法:

1.init( ),當Servlet第一次被請求時,Servlet容器就會開始調用這個方法來初始化一個Servlet對象出來,但是這個方法在后續請求中不會在被Servlet容器調用,就像人只能“出生”一次一樣。我們可以利用init( )方法來執行相應的初始化工作。調用這個方法時,Servlet容器會傳入一個ServletConfig對象進來從而對Servlet對象進行初始化。

2.service( )方法,每當請求Servlet時,Servlet容器就會調用這個方法。就像人一樣,需要不停的接受老板的指令并且“工作”。第一次請求時,Servlet容器會先調用init( )方法初始化一個Servlet對象出來,然后會調用它的service( )方法進行工作,但在后續的請求中,Servlet容器只會調用service方法了。

3.destory,當要銷毀Servlet時,Servlet容器就會調用這個方法,就如人一樣,到時期了就得死亡。在卸載應用程序或者關閉Servlet容器時,就會發生這種情況,一般在這個方法中會寫一些清除代碼。

public class MyFirstServlrt implements Servlet { ? ?@Override ? ?public void init(ServletConfig servletConfig) throws ServletException { ? ? ? ?System.out.println("Servlet正在初始化"); ? } ? ?@Override ? ?public ServletConfig getServletConfig() { ? ? ? ?return null; ? } ? ?@Override ? ?public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { ? ? ? ?//專門向客服端提供響應的方法 ? ? ? ?System.out.println("Servlet正在提供服務"); ? } ? ?@Override ? ?public String getServletInfo() { ? ? ? ?return null; ? } ? ?@Override ? ?public void destroy() { ? ? ? ?System.out.println("Servlet正在銷毀"); ? }} ? ? ?

然后在xml中配置正確的映射關系,在瀏覽器中訪問Servlet,第一次訪問時,控制臺輸出了如下信息:

然后,我們在瀏覽器中刷新3遍:

控制臺輸出的信息變成了下面這樣:

接下來,我們關閉Servlet容器:

控制臺輸出了Servlet的銷毀信息,這就是一個Servlet的完整生命周期。

Servlet 的其它兩個方法

?getServletInfo( ),這個方法會返回Servlet的一段描述,可以返回一段字符串。

?getServletConfig( ),這個方法會返回由Servlet容器傳給init( )方法的ServletConfig對象。

相關其他接口:

GenericServlet抽象類

前面我們編寫Servlet一直是通過實現Servlet接口來編寫的,但是,使用這種方法,則必須要實現Servlet接口中定義的所有的方法,即使有一些方法中沒有任何東西也要去實現,并且還需要自己手動的維護ServletConfig這個對象的引用。因此,這樣去實現Servlet是比較麻煩的。幸好,GenericServlet抽象類的出現很好的解決了這個問題。本著盡可能使代碼簡潔的原則,GenericServlet實現了Servlet和ServletConfig接口。

其中,GenericServlet抽象類相比于直接實現Servlet接口,有以下幾個好處:

1.為Servlet接口中的所有方法提供了默認的實現,則程序員需要什么就直接改什么,不再需要把所有的方法都自己實現了。2.提供方法,包圍ServletConfig對象中的方法。

HttpServlet抽象類

HttpServlet抽象類是繼承于GenericServlet抽象類而來的。使用HttpServlet抽象類時,還需要借助分別代表Servlet請求和Servlet響應的HttpServletRequest和HttpServletResponse對象。

HttpServletRequest接口擴展于javax.servlet.ServletRequest接口,HttpServletResponse接口擴展于javax.servlet.servletResponse接口。

HttpServlet抽象類覆蓋了GenericServlet抽象類中的Service( )方法,并且添加了一個自己獨有的Service(HttpServletRequest request,HttpServletResponse方法

讓我們來具體的看一看HttpServlet抽象類是如何實現自己的service方法吧:

我們看到是一個抽象方法,也就是HttpServlet要自己去實現這個service方法,我們在看看HttpServlet是怎么覆蓋這個service方法的:

protected void service(HttpServletRequest req, HttpServletResponse resp) ? ? ? ?throws ServletException, IOException { ? ? ? ?String method = req.getMethod(); ? ? ? ?if (method.equals(METHOD_GET)) { ? ? ? ? ? ?long lastModified = getLastModified(req); ? ? ? ? ? ?if (lastModified == -1) { ? ? ? ? ? ? ? ?// servlet doesn't support if-modified-since, no reason ? ? ? ? ? ? ? ?// to go through further expensive logic ? ? ? ? ? ? ? ?doGet(req, resp); ? ? ? ? ? } else { ? ? ? ? ? ? ? ?long ifModifiedSince; ? ? ? ? ? ? ? ?try { ? ? ? ? ? ? ? ? ? ?ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); ? ? ? ? ? ? ? } catch (IllegalArgumentException iae) { ? ? ? ? ? ? ? ? ? ?// Invalid date header - proceed as if none was set ? ? ? ? ? ? ? ? ? ?ifModifiedSince = -1; ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ?if (ifModifiedSince < (lastModified / 1000 * 1000)) { ? ? ? ? ? ? ? ? ? ?// If the servlet mod time is later, call doGet() ? ? ? ? ? ? ? ? ? ?// Round down to the nearest second for a proper compare ? ? ? ? ? ? ? ? ? ?// A ifModifiedSince of -1 will always be less ? ? ? ? ? ? ? ? ? ?maybeSetLastModified(resp, lastModified); ? ? ? ? ? ? ? ? ? ?doGet(req, resp); ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ?resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); ? ? ? ? ? ? ? } ? ? ? ? ? } ? ? ? } else if (method.equals(METHOD_HEAD)) { ? ? ? ? ? ?long lastModified = getLastModified(req); ? ? ? ? ? ?maybeSetLastModified(resp, lastModified); ? ? ? ? ? ?doHead(req, resp); ? ? ? } else if (method.equals(METHOD_POST)) { ? ? ? ? ? ?doPost(req, resp); ? ? ? } else if (method.equals(METHOD_PUT)) { ? ? ? ? ? ?doPut(req, resp); ? ? ? } else if (method.equals(METHOD_DELETE)) { ? ? ? ? ? ?doDelete(req, resp); ? ? ? } else if (method.equals(METHOD_OPTIONS)) { ? ? ? ? ? ?doOptions(req,resp); ? ? ? } else if (method.equals(METHOD_TRACE)) { ? ? ? ? ? ?doTrace(req,resp); ? ? ? } else { ? ? ? ? ? ?String errMsg = lStrings.getString("http.method_not_implemented"); ? ? ? ? ? ?Object[] errArgs = new Object[1]; ? ? ? ? ? ?errArgs[0] = method; ? ? ? ? ? ?errMsg = MessageFormat.format(errMsg, errArgs); ? ? ? ? ? ?resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); ? ? ? } ? }

我們會發現在service方法中還是沒有任何的服務邏輯,但是卻在解析HttpServletRequest中的方法參數,并調用以下方法之一:doGet,doPost,doHead,doPut,doTrace,doOptions和doDelete。這7種方法中,每一種方法都表示一個Http方法。doGet和doPost是最常用的。所以,如果我們需要實現具體的服務邏輯,不再需要覆蓋service方法了,只需要覆蓋doGet或者doPost就好了

總之,HttpServlet有兩個特性是GenericServlet所不具備的:

1.不用覆蓋service方法,而是覆蓋doGet或者doPost方法。在少數情況,還會覆蓋其他的5個方法。

2.使用的是HttpServletRequest和HttpServletResponse對象。

HttpServletRequest接口

?HttpServletRequest表示Http環境中的Servlet請求。它擴展于javax.servlet.ServletRequest接口,并添加了幾個方法。如圖:

常用方法:

String getContextPath();//返回請求上下文的請求URI部分Cookie[] getCookies();//返回一個cookie對象數組String getHeader(String var1);//返回指定HTTP標題的值String getMethod();//返回生成這個請求HTTP的方法名稱String getQueryString();//返回請求URL中的查詢字符串HttpSession getSession();//返回與這個請求相關的會話對象

HttpServletResponse接口

它繼承自ServletResponse接口,專門用來封裝HTTP響應消息。?由于HTTP請求消息分為狀態行,響應消息頭,響應消息體三部分,因此,在HttpServletResponse接口中定義了向客戶端發送響應狀態碼,響應消息頭,響應消息體的方法。

常用方法:

void addCookie(Cookie var1);//給這個響應添加一個cookievoid addHeader(String var1, String var2);//給這個請求添加一個響應頭void sendRedirect(String var1) throws IOException;//發送一條響應碼,講瀏覽器跳轉到指定的位置void setStatus(int var1);//設置響應行的狀態碼

Response的亂碼問題:

由于計算機中的數據都是以二進制形式存儲的,因此,當傳輸文本時,就會發生字符和字節之間的轉換。字符與字節之間的轉換是通過查碼表完成的,將字符轉換成字節過程稱為編碼,將字節轉換成字符的過程為解碼,如果編碼和解碼使用的碼表不一致,就會導致亂碼問題。

解決方式1:

response緩存區的默認編碼是ISO-8859-1,此碼表沒有中文。所以需要更改response的編碼方式:

response.setCharacterEncoding("UTF-8");

通過更改response的編碼方式為UTF-8,任然無法解決亂碼問題,因為發送端服務端雖然改變了編碼方式為UTF-8,但是接收端瀏覽器端仍然使用GB2312編碼方式解碼,還是無法還原正常的中文,因此還需要告知瀏覽器端使用UTF-8編碼去解碼。所以還需加上:

response.setHeader("Content-Type","text/html;charset=utf-8");

上面通過調用兩個方式分別改變服務端對于Response的編碼方式以及瀏覽器的解碼方式為同樣的UTF-8編碼來解決編碼方式不一樣發生亂碼的問題。

解決方式2:

response.setContentType("text/html;charset=UTF-8")這個方法包含了上面的兩個方法的調用,因此在實際的開發中,只需要調用一個response.setContentType("text/html;charset=UTF-8")方法即可.

response.setContentType("text/html;charset=UTF-8");

ServletConfig接口

當Servlet容器初始化Servlet時,Servlet容器會給Servlet的init( )方式傳入一個ServletConfig對象.

方法如下:

ServletContext接口

獲取Web應用上下文,與Servlet容器進行通信

ServletContext對象表示Servlet應用程序。每個Web應用程序都只有一個ServletContext對象。在將一個應用程序同時部署到多個容器的分布式環境中,每臺Java虛擬機上的Web應用都會有一個ServletContext對象。

通過在ServletConfig中調用getServletContext方法,也可以獲得ServletContext對象。

那么為什么要存在一個ServletContext對象呢?存在肯定是有它的道理,因為有了ServletContext對象,就可以共享從應用程序中的所有資料處訪問到的信息,并且可以動態注冊Web對象。前者將對象保存在ServletContext中的一個內部Map中。保存在ServletContext中的對象被稱作屬性。

常用方法:

方法名稱功能描述
String getInitParameter ( ? ? ? ? ? ? ?String name )獲取名為name的系統范圍的初始化參數值,系統范圍的初始化參數可在部署描述符中使用param>元素定義**
void setAttribute ( ?String name, Object object )設置名稱為name的屬性
Object getAttribute ( ? ? ? ? ? ? ?String name )獲取名稱為name的屬性
String getRealPath ( ? ? ? ? ? ? ? String path )返回參數所代表目錄的真實路徑
void log ( String message )記錄一般日志信息

上機案例:

案例1:

package com.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 MyServlet extends HttpServlet { private static final long serialVersionUID = 1L; ? ? ? @Override public void init() throws ServletException { super.init(); System.out.println("初始化Servlet");} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response);} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("正在執行業務....");} @Override public void destroy() { System.out.println("銷毀Servlet..."); super.destroy();}}

注意:這里的關閉服務器,一定要在tomcat/bin目錄下,shutDown.sh下關閉才能實現

還有就是Eclipse2020版默認是使用注解方式,如果需要編寫Servlet后自動配置web.xml文件你就需要把這個項目編寫的版本調到3.0一下就可以。

如圖:

案例2:

xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> ?<display-name>ServletDemo2display-name> ?<welcome-file-list> ? ?<welcome-file>index.jspwelcome-file> ?welcome-file-list> ?<servlet> ? ?<servlet-name>MyServletservlet-name> ? ?<servlet-class>com.servlet.MyServletservlet-class> ? ?<init-param> ? <param-name>initParamparam-name> ? <param-value>Hello Servletparam-value> ? ?init-param> ?servlet> ?<servlet-mapping> ? ?<servlet-name>MyServletservlet-name> ? ?<url-pattern>/myServleturl-pattern> ?servlet-mapping>web-app>package com.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 MyServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response);} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("處理請求時,doGet()方法被調用。"); String initParam = getInitParameter("initParam"); System.out.println(initParam);}}

案例3:

xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> ?<display-name>ServletDemo2display-name> ?<context-param> ? ?<param-name>contextParamparam-name> ? ?<param-value>ContextParamValueparam-value> ?context-param> ? ?<servlet> ? ?<servlet-name>MyServletservlet-name> ? ?<servlet-class>com.servlet.MyServletservlet-class> ? ?<init-param> ? <param-name>initParamparam-name> ? <param-value>Hello Servletparam-value> ? ?init-param> ?servlet> ?<servlet-mapping> ? ?<servlet-name>MyServletservlet-name> ? ?<url-pattern>/myServleturl-pattern> ?servlet-mapping> ? ? ?<welcome-file-list> ? ? ?<welcome-file>myServletwelcome-file> ? welcome-file-list>web-app>public void doGet(HttpServletRequest request, ? ? ? ? ? ? ? ? ? ? HttpServletResponse response) ? ? ? ? ? ? ? ? ? throws ServletException, IOException { ? ? ? System.out.println("處理請求時,doGet()方法被調用。"); ? ? ? String initParam = getInitParameter("initParam"); ? ? ? String contextParam = ? ? ? ? ? this.getServletContext().getInitParameter("contextParam"); ? ? ? System.out.println("Servlet初始化參數" + initParam); ? ? ? System.out.println("上下文參數" + contextParam); ? }

Servlet注解:

Servlet3.0通過注解實現Servlet,簡化web.xml的配置,后期我們的框架技術都是可以通過注解來簡化配置,大大提高開發效率。

@WebServlet(name = "MyServlet",urlPatterns ="/myServlet" )public class MyServlet extends HttpServlet { private static final long serialVersionUID = 1L; ? ? ? @Override public void init() throws ServletException { super.init(); System.out.println("初始化Servlet");} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response);} protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("正在執行業務....");} @Override public void destroy() { System.out.println("銷毀Servlet..."); super.destroy();}}

@WebServlet屬性列表:

屬性名類型描述
nameString指定Servlet 的 name 屬性,等價于 。如果沒有顯式指定,則該 Servlet 的取值即為類的全限定名。
valueString[]該屬性等價于 urlPatterns 屬性。兩個屬性不能同時使用。
urlPatternsString[]指定一組 Servlet 的 URL 匹配模式。等價于標簽。
loadOnStartupint指定 Servlet 的加載順序,等價于 標簽。
initParamsWebInitParam[]指定一組 Servlet 初始化參數,等價于標簽。
asyncSupportedboolean聲明 Servlet 是否支持異步操作模式,等價于 標簽。
descriptionString該 Servlet 的描述信息,等價于 標簽。
displayNameString該 Servlet 的顯示名,通常配合工具使用,等價于 標簽。

總結

以上是生活随笔為你收集整理的jsp调用servlet_宇宙最全Servlet详解!!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。