摘要:無論我訪問的是還是。映射的可以使用通配符通配符有兩種格式擴(kuò)展名正斜杠開頭并以結(jié)尾。當(dāng)多個(gè)用戶并發(fā)訪問共享資源的時(shí)候就會(huì)出現(xiàn)線程安全問題。
Servlet的調(diào)用圖
前面我們已經(jīng)學(xué)過了Servlet的生命周期了,我們根據(jù)Servlet的生命周期畫出Servlet的調(diào)用圖加深理解
Servlet的細(xì)節(jié) 一個(gè)已經(jīng)注冊(cè)的Servlet可以被多次映射同一個(gè)Servlet可以被映射到多個(gè)URL上。
Demo1 zhongfucheng.web.Demo1 Demo1 /Demo1 Demo1 /ouzicheng
無論我訪問的是http://localhost:8080/Demo1還是http://localhost:8080/ouzicheng。我訪問的都是Demo1。
Servlet映射的URL可以使用通配符通配符有兩種格式:
*.擴(kuò)展名
正斜杠(/)開頭并以“/*”結(jié)尾。
匹配所有
匹配擴(kuò)展名為.jsp的
如果.擴(kuò)展名和正斜杠(/)開頭并以“/”結(jié)尾兩種通配符同時(shí)出現(xiàn),匹配的是哪一個(gè)呢?
看誰的匹配度高,誰就被選擇
*.擴(kuò)展名的優(yōu)先級(jí)最低
Servlet映射的URL可以使用通配符和Servlet可以被映射到多個(gè)URL上的作用:
隱藏網(wǎng)站是用什么編程語言寫的【.php,.net,.asp實(shí)際上訪問的都是同一個(gè)資源】
用特定的后綴聲明版權(quán)【公司縮寫】
Servlet是單例的 為什么Servlet是單例的Demo1 zhongfucheng.web.Demo1 Demo1 *.jsp Demo1 *.net Demo1 *.asp Demo1 *.php
瀏覽器多次對(duì)Servlet的請(qǐng)求,一般情況下,服務(wù)器只創(chuàng)建一個(gè)Servlet對(duì)象,也就是說,Servlet對(duì)象一旦創(chuàng)建了,就會(huì)駐留在內(nèi)存中,為后續(xù)的請(qǐng)求做服務(wù),直到服務(wù)器關(guān)閉。
每次訪問請(qǐng)求對(duì)象和響應(yīng)對(duì)象都是新的對(duì)于每次訪問請(qǐng)求,Servlet引擎都會(huì)創(chuàng)建一個(gè)新的HttpServletRequest請(qǐng)求對(duì)象和一個(gè)新的HttpServletResponse響應(yīng)對(duì)象,然后將這兩個(gè)對(duì)象作為參數(shù)傳遞給它調(diào)用的Servlet的service()方法,service方法再根據(jù)請(qǐng)求方式分別調(diào)用doXXX方法。
線程安全問題當(dāng)多個(gè)用戶訪問Servlet的時(shí)候,服務(wù)器會(huì)為每個(gè)用戶創(chuàng)建一個(gè)線程。當(dāng)多個(gè)用戶并發(fā)訪問Servlet共享資源的時(shí)候就會(huì)出現(xiàn)線程安全問題。
原則:
如果一個(gè)變量需要多個(gè)用戶共享,則應(yīng)當(dāng)在訪問該變量的時(shí)候,加同步機(jī)制synchronized (對(duì)象){}
如果一個(gè)變量不需要共享,則直接在 doGet() 或者 doPost()定義.這樣不會(huì)存在線程安全問題
load-on-startup如果在
作用:
為web應(yīng)用寫一個(gè)InitServlet,這個(gè)servlet配置為啟動(dòng)時(shí)裝載,為整個(gè)web應(yīng)用創(chuàng)建必要的數(shù)據(jù)庫表和數(shù)據(jù)
完成一些定時(shí)的任務(wù)【定時(shí)寫日志,定時(shí)備份數(shù)據(jù)】
在web訪問任何資源都是在訪問Servlet當(dāng)你啟動(dòng)Tomcat,你在網(wǎng)址上輸入http://localhost:8080。為什么會(huì)出現(xiàn)Tomcat小貓的頁面?
這是由缺省Servlet為你服務(wù)的!
我們先看一下web.xml文件中的配置,web.xml文件配置了一個(gè)缺省Servlet
default org.apache.catalina.servlets.DefaultServlet debug 0 listings false 1 default /
什么叫做缺省Servlet?凡是在web.xml文件中找不到匹配的
既然我說了在web訪問任何資源都是在訪問Servlet,那么我訪問靜態(tài)資源【本地圖片,本地HTML文件】也是在訪問這個(gè)缺省Servlet【DefaultServlet】
證實(shí)一下:當(dāng)我沒有手工配置缺省Servlet的時(shí)候,訪問本地圖片是可以訪問得到的
現(xiàn)在我自己配置一個(gè)缺省Servlet,Demo1就是我手工配置的缺省Servlet,覆蓋掉web.xml配置的缺省Servlet
Demo1 zhongfucheng.web.Demo1 Demo1 /
下面我繼續(xù)訪問一下剛才的圖片,此時(shí)輸出的是Demo1這個(gè)Servlet寫上的內(nèi)容了
總結(jié):無論在web中訪問什么資源【包括JSP】,都是在訪問Servlet。沒有手工配置缺省Servlet的時(shí)候,你訪問靜態(tài)圖片,靜態(tài)網(wǎng)頁,缺省Servlet會(huì)在你web站點(diǎn)中尋找該圖片或網(wǎng)頁,如果有就返回給瀏覽器,沒有就報(bào)404錯(cuò)誤
ServletConfig對(duì)象 ServletConfig對(duì)象有什么用?通過此對(duì)象可以讀取web.xml中配置的初始化參數(shù)。
現(xiàn)在問題來了,為什么我們要把參數(shù)信息放到web.xml文件中呢?我們可以直接在程序中都可以定義參數(shù)信息,搞到web.xml文件中又有什么好處呢?
好處就是:能夠讓你的程序更加靈活【更換需求,更改配置文件web.xml即可,程序代碼不用改】
獲取web.xml文件配置的參數(shù)信息為Demo1這個(gè)Servlet配置一個(gè)參數(shù),參數(shù)名是name,值是zhongfucheng
Demo1 zhongfucheng.web.Demo1 name zhongfucheng Demo1 /Demo1
在Servlet中獲取ServletConfig對(duì)象,通過ServletConfig對(duì)象獲取在web.xml文件配置的參數(shù)
ServletContext對(duì)象 什么是ServletContext對(duì)象?當(dāng)Tomcat啟動(dòng)的時(shí)候,就會(huì)創(chuàng)建一個(gè)ServletContext對(duì)象。它代表著當(dāng)前web站點(diǎn)
ServletContext有什么用?ServletContext既然代表著當(dāng)前web站點(diǎn),那么所有Servlet都共享著一個(gè)ServletContext對(duì)象,所以Servlet之間可以通過ServletContext實(shí)現(xiàn)通訊。
ServletConfig獲取的是配置的是單個(gè)Servlet的參數(shù)信息,ServletContext可以獲取的是配置整個(gè)web站點(diǎn)的參數(shù)信息
利用ServletContext讀取web站點(diǎn)的資源文件
實(shí)現(xiàn)Servlet的轉(zhuǎn)發(fā)【用ServletContext轉(zhuǎn)發(fā)不多,主要用request轉(zhuǎn)發(fā)】
Servlet之間實(shí)現(xiàn)通訊ServletContext對(duì)象可以被稱之為域?qū)ο?/strong>
到這里可能有一個(gè)疑問,域?qū)ο笫鞘裁茨??其?shí)域?qū)ο罂梢院唵卫斫獬?strong>一個(gè)容器【類似于Map集合】
實(shí)現(xiàn)Servlet之間通訊就要用到ServletContext的setAttribute(String name,Object obj)方法,
第一個(gè)參數(shù)是關(guān)鍵字,第二個(gè)參數(shù)是你要存儲(chǔ)的對(duì)象
這是Demo2的代碼
//獲取到ServletContext對(duì)象 ServletContext servletContext = this.getServletContext(); String value = "zhongfucheng"; //MyName作為關(guān)鍵字,value作為值存進(jìn) 域?qū)ο蟆绢愋陀贛ap集合】 servletContext.setAttribute("MyName", value);
這是Demo3的代碼
//獲取ServletContext對(duì)象 ServletContext servletContext = this.getServletContext(); //通過關(guān)鍵字獲取存儲(chǔ)在域?qū)ο蟮闹? String value = (String) servletContext.getAttribute("MyName"); System.out.println(value);
訪問Demo3可以獲取Demo2存儲(chǔ)的信息,從而實(shí)現(xiàn)多個(gè)Servlet之間通訊
獲取web站點(diǎn)配置的信息如果我想要讓所有的Servlet都能夠獲取到連接數(shù)據(jù)庫的信息,不可能在web.xml文件中每個(gè)Servlet中都配置一下,這樣代碼量太大了!并且會(huì)顯得非常啰嗦冗余。
web.xml文件支持對(duì)整個(gè)站點(diǎn)進(jìn)行配置參數(shù)信息【所有Servlet都可以取到該參數(shù)信息】
name zhongfucheng
Demo4代碼
//獲取到ServletContext對(duì)象 ServletContext servletContext = this.getServletContext(); //通過名稱獲取值 String value = servletContext.getInitParameter("name"); System.out.println(value);
試一下Demo3是否能拿到,相同的代碼
//獲取到ServletContext對(duì)象 ServletContext servletContext = this.getServletContext(); //通過名稱獲取值 String value = servletContext.getInitParameter("name"); System.out.println(value);讀取資源文件
第一種方式:
現(xiàn)在我要通過Servlet111讀取1.png圖片
按我們以前的方式,代碼應(yīng)該是這樣的。
FileInputStream fileInputStream = new FileInputStream("1.png"); System.out.println(fileInputStream);
當(dāng)我們?cè)L問的時(shí)候,卻出錯(cuò)了!說找不到1.png文件
這是為什么呢?我們以前讀取文件的時(shí)候,如果程序和文件在同一包名,可以直接通過文件名稱獲取得到的!,原因很簡單,以前我們寫的程序都是通過JVM來運(yùn)行的,而現(xiàn)在,我們是通過Tomcat來運(yùn)行的
根據(jù)web的目錄規(guī)范,Servlet編譯后的class文件是存放在WEB-INFclasses文件夾中的
看到這里,我們知道了要進(jìn)入classes目錄中讀取文件,所以我們將代碼改成以下方式
FileInputStream fileInputStream = new FileInputStream("D:zhongfuchengwebWEB-INFclasseszhongfuchengweb1.png"); System.out.println(fileInputStream);
再去讀取時(shí),就發(fā)現(xiàn)可以獲取到文件了。
但是現(xiàn)在問題又來了,我讀取文件的時(shí)候都要寫上絕對(duì)路徑,這樣太不靈活了。試想一下,如果我將該讀取文件的模塊移到其他的web站點(diǎn)上,我的代碼就又要修改了【因?yàn)閣eb站點(diǎn)的名字不一樣】。
我們通過ServletContext讀取就可以避免修改代碼的情況,因?yàn)镾ervletContext對(duì)象是根據(jù)當(dāng)前web站點(diǎn)而生成的
代碼如下所示:
//獲取到ServletContext對(duì)象 ServletContext servletContext = this.getServletContext(); //調(diào)用ServletContext方法獲取到讀取文件的流 InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/classes/zhongfucheng/web/1.png");
第二種方式:
如果我的文件放在web目錄下,那么就簡單得多了!,直接通過文件名稱就能獲取
代碼如下所示
//獲取到ServletContext對(duì)象 ServletContext servletContext = this.getServletContext(); //調(diào)用ServletContext方法獲取到讀取文件的流 InputStream inputStream = servletContext.getResourceAsStream("2.png");
第三種方式:
通過類裝載器讀取資源文件。
我的文件放在了src目錄下【也叫做類目錄】
代碼如下所示
//獲取到類裝載器 ClassLoader classLoader = Servlet111.class.getClassLoader(); //通過類裝載器獲取到讀取文件流 InputStream inputStream = classLoader.getResourceAsStream("3.png");
我的文件放在了src目錄下的包下
代碼如下,添加包名路徑即可。
//獲取到類裝載器 ClassLoader classLoader = Servlet111.class.getClassLoader(); //通過類裝載器獲取到讀取文件流 InputStream inputStream = classLoader.getResourceAsStream("/zhongfucheng/web/1.png");
原則:如果文件太大,就不能用類裝載器的方式去讀取,會(huì)導(dǎo)致內(nèi)存溢出
如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章的同學(xué),可以關(guān)注微信公眾號(hào):Java3y
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/68412.html
摘要:前言由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 前言 由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時(shí)間才會(huì)更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號(hào):Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡單 注解就這么簡單 Druid數(shù)據(jù)庫連接池...
閱讀 847·2023-04-25 19:49
閱讀 3778·2021-09-30 09:47
閱讀 2770·2021-09-13 10:21
閱讀 2699·2021-08-24 10:04
閱讀 3187·2019-08-30 15:55
閱讀 2341·2019-08-30 15:55
閱讀 2419·2019-08-30 15:54
閱讀 3484·2019-08-30 13:53