Servlet方法详解
Servlet:
Servlet是SUN公司提供的一套規范,名稱就叫Servlet規范,它也是JavaEE規范之一。使用JavaEE的API。目前在Oracle官網中的最新版本是JavaEE8,
- Servlet是一個運行在web服務端的java小程序
- 它可以用于接收和響應客戶端的請求
- 要想實現Servlet功能,可以實現Servlet接口,繼承GenericServlet或者HttpServlet
- 每次請求都會執行service方法
- Servlet還支持配置
Servlet執行過程:
Servlet關系視圖:
Servlet實現方式:
1、 實現Servlet接口,接口中的方法必須全部實現。
表示接口中的所有方法在需求方面都有重寫的必要。這種方式支持最大程度的自定義。
2、繼承GenericServlet,service方法必須重寫,其他方可根據需求,選擇性重寫。
表示只在接收和響應客戶端請求這方面有重寫的需求,而其他方法可根據實際需求選擇性重寫,使開發Servlet變得簡單。但是,此種方式是和HTTP協議無關的。
3、繼承HttpServlet,它是javax.servlet.http包下的一個抽象類,是GenericServlet的子類。如果選擇繼承HttpServlet時,只需要重寫doGet和doPost方法,不要覆蓋service方法。
表示我們的請求和響應需要和HTTP協議相關。也就是說通過HTTP協議來訪問的。那么每次請求和響應都符合HTTP協議的規范。請求的方式就是HTTP協議所支持的方式
實現Servlet:
public class ServletDemo03 implements Servlet {@Overridepublic void init(ServletConfig servletConfig) throws ServletException {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("實現Servlet方式");}@Overridepublic String getServletInfo() {return null;}@Overridepublic void destroy() {} }繼承GenericServlet:
public class ServletDemo01 extends GenericServlet {@Overridepublic void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {System.out.println("service方法執行了...");} }繼承HttpServlet::
public class ServletDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("Servlet執行了");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);} }配置文件:
<?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_4_0.xsd"version="4.0"><!--Servlet配置--><servlet><servlet-name>servletDemo</servlet-name><servlet-class>com.example.demo.ServletDemo</servlet-class></servlet><!--映射配置--><servlet-mapping><servlet-name>servletDemo</servlet-name><url-pattern>/servletDemo</url-pattern></servlet-mapping><!--生命周期配置--><servlet><servlet-name>servletDemo02</servlet-name><servlet-class>com.example.demo.ServletDemo02</servlet-class></servlet><servlet-mapping><servlet-name>servletDemo02</servlet-name><url-pattern>/servletDemo02</url-pattern></servlet-mapping></web-app>Servlet生命周期:
- 對象的生命周期,就是對象從生到死的過程,
- 出生:請求第一次到達Servlet時,對象就創建出來,并且初始化成功。只出生一次,就放到內存中。
- 活著:服務器提供服務的整個過程中,該對象一直存在,每次都是執行service方法。
- 死亡:當服務停止時,或者服務器宕機時,對象消亡。
- Servlet對象只會創建一次,銷毀一次。所以,Servlet對象只有一個實例。如果一個對象實例在應用中是唯一的存在,用了單例模式。
演示:
public class ServletDemo02 extends HttpServlet {// 對象出生@Overridepublic void init() throws ServletException {System.out.println("出生了");}// 對象服務@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("收到客戶端請求");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}// 對象死亡@Overridepublic void destroy() {System.out.println("掛了");} }線程安全:
在Servlet中定義了類成員之后,多個瀏覽器都會共享類成員的數據。其實每一個瀏覽器端發送請求,就代表是一個線程,那么多個瀏覽器就是多個線程,多個線程會共享Servlet類成員中的數據,其中任何一個線程修改了數據,都會影響其他線程。因此,所以Servlet它不是線程安全的。分析產生這個問題的根本原因,其實就是因為Servlet是單例,單例對象的類成員只會隨類實例化時初始化一次,之后的操作都是改變,而不會重新初始化。
解決:
在Servlet中定義類成員要慎重。如果類成員是共用的,并且只會在初始化時賦值,其余時間都是獲取的話,那么是沒問題。如果類成員并非共用,或者每次使用都有可能對其賦值,那么就要考慮線程安全問題了,把它定義到doGet或者doPost方法里面去就可以了?;蛘呤侵苯蛹觭ynchronized
演示:
public class ServletDemo03 extends HttpServlet {private String username;@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {synchronized (this) {// 在這里聲明的話,就是把成員變量變成局部變量,谷歌進來是一個username,火狐進來又是另一個就不會出現出數據不安全了// String username = null;// String getParameter(String name):根據參數名稱獲取參數值username = req.getParameter("username");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// resp.getWriter 傳數據給前端PrintWriter writer = resp.getWriter();writer.println("username:" + username);writer.close();}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);} }Servlet映射三種方式:
說明:映射優先級:越具體優先級越高,1>2>3
演示:
<?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_4_0.xsd"version="4.0"><!--<!–ServletHttp配置–><servlet><servlet-name>servletDemo</servlet-name><servlet-class>com.example.demo.ServletDemo</servlet-class></servlet><servlet-mapping><servlet-name>servletDemo</servlet-name><url-pattern>/servletDemo</url-pattern></servlet-mapping>--><!-- <!–/開頭+通配符的方式–><servlet><servlet-name>servletDemo</servlet-name><servlet-class>com.example.demo.ServletDemo</servlet-class></servlet><servlet-mapping><servlet-name>servletDemo</servlet-name><url-pattern>/servlet/*</url-pattern></servlet-mapping>--><!--通配符+固定格式結尾 結尾寫什么就寫什么,開心就好--><servlet><servlet-name>servletDemo</servlet-name><servlet-class>com.example.demo.ServletDemo</servlet-class></servlet><servlet-mapping><servlet-name>servletDemo</servlet-name><url-pattern>*.itzhuzhu</url-pattern></servlet-mapping> </web-app>實現類:
public class ServletDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 定義一個商品金額int money = 1000;// 獲取訪問路徑String uri = req.getRequestURI();// public int lastIndexOf(int ch): 返回指定字符在此字符串中最后一次出現處的索引,如果此字符串中沒有這樣的字符,則返回 -1。uri = uri.substring(uri.lastIndexOf("/"));// 條件判斷if ("/vip".equals(uri)) {System.out.println("原價:" + money + "尊敬的Vip您的折后價是:" + money * 0.8);} else if ("/svip".equals(uri)) {System.out.println("原價:" + money + "尊敬的Sip您的折后價是:" + money * 0.1);} else {System.out.println("會員都不開還想打折?打骨折");}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);} }Servlet創建時機:
第一種:服務器加載時創建
優勢:
在服務器啟動時,就把需要的對象都創建完成了,從而在使用的時候減少了創建對象的時間,提高了首次執行的效率。
弊端:
因為在應用加載時就創建了Servlet對象,因此,導致內存中充斥著大量用不上的Servlet對象,造成了內存的浪費。
第二種:第一次訪問時創建
優勢:
就是減少了對服務器內存的浪費,因為那些一直沒有被訪問過的Servlet對象都沒有創建,因此也提高了服務器的啟動時間。
弊端:
如果有一些要在應用加載時就做的初始化操作,它都沒法完成,從而要考慮其他技術實現。
修改創建時機:在標簽中添加標簽
標簽里的數字越小優先級越高,正整數代表服務器加載時創建,負數或不寫代表第一次訪問的時候創建
<servlet><servlet-name>servletDemo</servlet-name><servlet-class>com.example.demo.ServletDemo</servlet-class><!--數字越小越高,負數或者不寫就是第一次訪問的時候創建--><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>servletDemo</servlet-name><url-pattern>/servletDemo</url-pattern></servlet-mapping>默認Servlet:
默認Servlet是由服務器提供的一個Servlet,它配置在Tomcat的conf目錄下web.xml中。它的映射路徑是<url-pattern>/<url-pattern>,在發送請求時,首先會在應用中的web.xml中查找映射配置,找到就執行。找不到對應的Servlet路徑時,就去找默認的Servlet,由默認Servlet處理。
ServletConfig:
ServletConfig是Servlet的配置參數對象,在Servlet規范中,允許為每個Servlet都提供一些初始化配置。所以,每個Servlet都一個自己的ServletConfig。它的作用是在Servlet初始化期間,把一些配置信息傳遞給Servlet。比如servlet是個孩子,ServletConfig就是保姆
生命周期:
由于它是在初始化階段讀取了web.xml中為Servlet準備的初始化配置,并把配置信息傳遞給Servlet,所以生命周期與Servlet相同。需要注意的是,如果Servlet配置了1,那么ServletConfig也會在應用加載時創建。
配置ServletConfig:
在<servlet>標簽中,通過<init-param>標簽配置,有兩個子標簽
<param-name>:代表初始化參數的key
<param-value>:代表初始化參數的value
ServletConfig方法:
| String | getInitParameter(String name) | 根據參數名稱獲取參數的值 |
| Enumeration | getInitParameterNames() | 獲取所有參數名稱的枚舉 |
| String | getServletName | 獲取Servlet的名稱 |
| SerlvetContext | getServletContext | 獲取ServletContext對象 |
演示:
配置信息:
<servlet><servlet-name>servletDemo05</servlet-name><servlet-class>com.example.demo.ServletDemo05</servlet-class><!--配置ServletConfig,是以鍵值對的形式存在的--><init-param><param-name>itz</param-name><param-value>itzhuzhu</param-value></init-param></servlet><servlet-mapping><servlet-name>servletDemo05</servlet-name><url-pattern>/servletDemo05</url-pattern></servlet-mapping>實現類:
public class servletDemo04 extends HttpServlet {// 聲明ServletConfigprivate ServletConfig config;// 因為ServletConfig是在初始化期間傳遞信息,所以要在init方法里去獲取@Overridepublic void init(ServletConfig config) throws ServletException {// 通過init方法,對ServletConfig對象賦值this.config = config;}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// getInitParameter(String name):根據key獲取valueString encodingValue = config.getInitParameter("encoding");System.out.println(encodingValue);// getInitParameterNames():獲取所有keyEnumeration<String> keys = config.getInitParameterNames();while (keys.hasMoreElements()) {// 獲取每一個keyString key = keys.nextElement();// 根據key獲取valueString value = config.getInitParameter(key);System.out.println(key + " : " + value);}// getServletName 獲取Servlet的名稱String servletName = config.getServletName();System.out.println(servletName);// getServletContext 獲取ServletContext對象ServletContext servletContext = config.getServletContext();System.out.println(servletContext);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);} }ServletContext:
ServletContext對象,它是應用上下文對象。每一個應用有且只有一個ServletContext對象。
作用:
它可以配置和獲取應用的全局初始化參數,實現所有Servlet之間的數據共享。
生命周期:
- 出生: 應用一加載,該對象就被創建出來了。一個應用只有一個實例對象。(Servlet和ServletContext都-是單例的)
- 活著:只要應用一直提供服務,對象就一直存在。
- 死亡:應用被卸載(或者服務器掛了),對象死亡。
域對象概念:
- 域對象:指的是對象有作用域(作用范圍)
- 域對象的作用:域對象可以實現數據共享。
- 不同作用范圍的域對象,共享數據的能力不一樣。在Servlet規范中,一共有4個域對象。ServletContext就是其中一個。也是web應用中最大的作用域,叫application域。每個應用只有一個application域(應用域),它可以實現整個應用間的數據共享功能。
ServletContext配置:
ServletContext被稱之為應用上下文對象,所以它的配置是針對整個應用的配置,而非某個特定Servlet的配置。它的配置被稱為應用的初始化參數配置。
配置的方式,需要在標簽中使用來配置初始化參數
<param-name>:全局初始化參數的key
<param-value>:全局初始化參數的value
常用方法:
| String | getInitParameter(String name) | 根據名稱獲取全局配置的參數 |
| String | getContextPath() | 獲取當前應用訪問的虛擬目錄 |
| String | getRealPath | 根據虛擬目錄獲取應用部署的磁盤絕對路徑 |
應用域常用方法:
| void | setAttribute(String name,Object value) | 向應用域對象中存儲數據 |
| Object | getAttribute(String name) | 通過名稱獲取應用域對象中的數組 |
| void | removeAttribute(String name) | 通過名稱移除應用域對象中的數據 |
配置文件:
<!--因為servletContext它不屬于某一個servlet,它是配置全局的,所以不能寫在servlet里--><context-param><param-name>desc</param-name><param-value>This is Ser vletContextDemo</param-value></context-param><servlet><servlet-name>servletContextDemo</servlet-name><servlet-class>com.example.demo.ServletContextDemo</servlet-class></servlet><servlet-mapping><servlet-name>servletContextDemo</servlet-name><url-pattern>/servletContextDemo</url-pattern></servlet-mapping>實現類:
public class ServletContextDemo extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 獲取ServletContext對象 , GenericServlet底層已經實現了getInitParameter所以可以直接調用 ServletConfig sc = this.getServletConfig();ServletContext context = getServletContext();//獲取全局配置參數的descString value = context.getInitParameter("desc");System.out.println(value);//獲取應用的訪問虛擬目錄String contextPath = context.getContextPath();System.out.println(contextPath);//根據虛擬目錄獲取應用部署的磁盤絕對路徑String realPath = context.getRealPath("/");System.out.println(realPath);// 在src、wabapp、webinf創建三個文件獲取路徑//獲取a.txt文件的絕對路徑String a = context.getRealPath("/WEB-INF/classes/a.txt");System.out.println(a);//獲取b.txt文件的絕對路徑String b = context.getRealPath("/b.txt");System.out.println(b);String c = context.getRealPath("/WEB-INF/c.txt");System.out.println(c);//向域對象中存儲數據context.setAttribute("username", "itzhuzhu");//移除域對象中username的數據,刪除了再訪問就變成null了context.removeAttribute("username");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);} }獲取共享數據:
public class ServletDemo05 extends HttpServlet {// 聲明ServletConfigprivate ServletConfig config;// 因為ServletConfig是在初始化期間傳遞信息,所以要在init方法里去獲取@Overridepublic void init(ServletConfig config) throws ServletException {// 通過init方法,對ServletConfig對象賦值this.config = config;}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// getServletContext 獲取ServletContext對象ServletContext servletContext = config.getServletContext();System.out.println(servletContext);// getAttribute(String name) 通過名稱獲取應用域對象中的數組Object username = servletContext.getAttribute("username");System.out.println(username);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);} }Request方法詳解:
總結
以上是生活随笔為你收集整理的Servlet方法详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring AOP切入点与通知XML类
- 下一篇: java去掉图片边框颜色_sharp 去