Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
、英語國際音標(biāo)總表(48個)
I、元音(20)
單元音(12) : / i: / / ? / / ?: / / ? / / ?? / / ? / / u:/ / ? / / ɑ:/ / ? / / e / / ? /
雙元音(8) : / e? / / a? / / ?? / / a? / / ?? / / ?? / / e? / / ?? /
II、輔音(28)
爆破音(6) : / p / / b / / t / / d / / k / / d /
摩擦音(9) : / f / / v / / θ / / e / / s / / z / / ? / / ? / / h /
破擦音(2) : / t ? / / d? /
鼻腔音(3) : / m / / n / / ? /
延續(xù)音(3) : / j / / w / / r /
旁流音(1) : / l /
輔音連綴(4): / tr / / dr / / ts / / dz /
英語國際音標(biāo)總表(詳細(xì)分類及清濁對照)
二、音標(biāo)及例詞練習(xí):
I. 元音(20):
1.單元音(12)
/ i: / sheep sleep seat these
/ ? / ship slip sit this
/ ?: / girl first work turn
/ ? / ago worker farmer letter
/ ?? / four door small morning
/ ? / clock dog doctor orange
/ u: / fool who moon food
/ ? / look good book could
/ ɑ: / car art glass far
/ ? / bus cup run must
/ e / bed head desk egg
/ ? / dad bag apple thank
2. 雙元音(8)
/ e? / take face may say
/ a? / my bike Mike white
/ ?? / boy toy oil boil
/ a? / how down town mouse
/ ?? / go home know open
/ ?? / dear here near beer
/ e? / hair bear parent their
/ ?? / poor sure tour fewer
英語國際音標(biāo)(IPA)簡明總表
II. 輔音(28個):
1.爆破音(6)
/ p / park put pork play
/ b / body Bob buy back
/ t / tape tell sit foot
/ d / day dish dad did
/ k / key kite cake cock
/ g / green goat big great
2.摩擦音(9)
/ f / friend fat knife fine
/ v / five very give twelve
/ θ / math both think thank
/ e / this that mother father
/ s / six seat sister nice
/ z / zoo zero does his
/ ? / she fish finish wash
/ ? / pleasure measure television
/ h / her hand have hard
3.破擦音(2)
/ t ? / cheap chair much catch
/ d? / jeep job jump juice
4.鼻腔音(3)
/ m / make Tom milk time
/ n / pen ten nine nose
/ ? / sing think English morning
5.延續(xù)音(3)
/ j / yes yellow young you
/ w / what we why way
/ r / room ruler read ride
6.旁流音(1)
/ l / look leg apple table
7.輔音連綴(4)
/ tr / tree try train strong
/ dr / drink drive dress dream
/ ts / cats hats sits gets
/ dz / beds hands birds decides
Learn English
三、二十六個字母音標(biāo):
A-G: / e? bi: si: di: i: ef d?i: /
H-N: / e?t ? a? d?e? ke? el em en /
O-T : / ?? pi: kju: ɑ: es ti: /
U-Z: / ju: vi: ‘d?blju: eks wa? zi:(zed) /
26個英文字母書寫規(guī)范
四、其它音標(biāo)練習(xí)法:
I.拼讀法:
用單個輔音和所有元音搭配,自由組合成任意的音節(jié)。如: /p/ 和/i:/ /?/ /?:/ /?/ /??/ /?/ /u:/ /?/ /ɑ:/ /?/ /e/ /?/ 相組合,可拼成 /pi:/ /p?/ /p?:/ /p?/ /p??/ /p?/ /pu:/ /p?/ /pɑ:/ /p? / /pe/ /p?/。 依此類推,再用/b/和其它所有輔音,分別與所有元音相拼讀,可拼出共四百多個音節(jié)。注意,有個別輔音不能放在元音前面與其拼接,請找出來。
II.列舉法:
在朗讀單個音標(biāo)時,可列舉幾個最常見、最典型的例詞,作為擴(kuò)充發(fā)音練習(xí)材料,鞏固發(fā)音。如: / i: / sheep sleep seat these 。
III.對比法:
1、將長元音和短元音進(jìn)行對比朗讀,找出區(qū)別所在。如:可將下列音標(biāo)及例詞進(jìn)行縱向朗讀,以加強(qiáng)長音 /i:/和短音/?//的區(qū)分能力:
/i:/ sheep sleep seat these
/?/ ship slip sit this
2、將清輔音和濁輔音進(jìn)行縱向?qū)Ρ染毩?xí),找出他們之間的聯(lián)系和區(qū)別,即:相對應(yīng)的清濁音口型相同,舌位相同,發(fā)音原理相同;發(fā)清輔音時聲帶不震動,發(fā)濁輔音時聲帶震動,發(fā)出響聲。如:
/p/ park put pork play
/b/ body Bob buy back
IV.標(biāo)音法:
學(xué)習(xí)國際音標(biāo)的最直接目的有兩個:一是遇到生詞后查詞典得到音標(biāo),然后根據(jù)音標(biāo)自己能夠讀出任意一個生詞的讀音;二是給單詞或其它形式用音標(biāo)來標(biāo)記出其讀音。這樣做可以確保發(fā)音的的準(zhǔn)確性,保證標(biāo)音的規(guī)范性,杜絕用漢字或拼音來給英文標(biāo)音的壞習(xí)慣。可以有以下三種練習(xí)方式:
1、直接根據(jù)讀音標(biāo)出26個英文字母的讀音。這是最基礎(chǔ)的,參見:本教程第三節(jié):二十六個字母音標(biāo)。
2、根據(jù)音標(biāo)寫出相對應(yīng)的單詞。如:/'ru:l?/ ruler
3、根據(jù)單詞寫出相對應(yīng)的音標(biāo),即:給單詞標(biāo)音。如:ruler /'ru:l?/
Do you speak English ?
V.繞口令法:
對頑固性的發(fā)音障礙,可以采用強(qiáng)化或過度的訓(xùn)練方法。如用繞口令的形式來強(qiáng)化"失去爆破"的發(fā)音技巧:A good cook could cook good cookies . (此繞口令中的12個粗黑體字母為爆破音,其中的5個帶下劃線的爆破音要"失去爆破"。)
1. A big black bear sat on a big black bug.
2. A big black bug bit a big black bear and made the big black bear bleed blood.
3. A big black bug bit a big black dog on his big black nose!
4. A loyal warrior will rarely worry why we rule.
5. A noise annoys an oyster, but a noisy noise annoys an oyster more!
6. Ann and Andy's anniversary is in April.
7. Bake big batches of bitter brown bread.
8. Big black bugs bleed blue black blood but baby black bugs bleed blue blood.
9. Black background, brown background.
10. Blake's black bike's back brake bracket block broke.
11. Blue glue gun, green glue gun.
12. Caution: Wide Right Turns
13. Each Easter Eddie eats eighty Easter eggs.
14. Elizabeth has eleven elves in her elm tree.
15. Elizabeth's birthday is on the third Thursday of this month.
16. Fresh fried fish, Fish fresh fried, Fried fish fresh, Fish fried fresh.
17. Freshly fried fresh flesh
18. Green glass globes glow greenly.
19. He threw three balls.
20. He threw three free throws.
21. Here's an easy game to play. Here's an easy thing to say:
22. How many cookies could a good cook cook If a good cook could cook cookies? A good cook could cook as much cookies as a good cook who could cook cookies.
23. How may saws could a see-saw saw if a see-saw could saw saws?
24. How much oil boil can a gum boil boil if a gum boil can boil oil?
25. I thought a thought. But the thought I thought wasn't the thought I thought I thought. If the thought I thought I thought had been the thought I thought, I wouldn't have thought so much.
26. I wish I were what I was when I wished I were what I am.
27. I wish to wish the wish you wish to wish, but if you wish the wish the witch wishes, I won't wish the wish you wish to wish.
28. I wish you were a fish in my dish
29. If two witches would watch two watches, which witch would watch which watch?
30. If you notice this notice, you will notice that this notice is not worth noticing.
31. It's not the cough that carries you off, it's the coffin they carry you off in!
32. Little red lorry
33. Miss Smith's fish-sauce shop seldom sells shellfish.
34. Never trouble about trouble until trouble troubles you!
35. Nothing is worth thousands of deaths.
36. Picky people pick Peter Pan Peanut Butter. Peter Pan Peanut is the peanut picky people pick.
37. Ripe white wheat reapers reap ripe white wheat right.
38. She said she should sit.
39. She sells sea shells on the seashore. The seashells she sells are seashells she is sure.
40. Shut up the shutters and sit in the shop.
41. Silly sheep weep and sleep.
42. Six shining cities, six shining cities, six shining cities.
43. Six sick sea-serpents swam the seven seas.
44. Six sleek swans swam swiftly southwards
45. Stupid superstition!
46. The batter with the butter is the batter that is better!
47. The great Greek grape growers grow great Greek grapes.
48. The soldier's shoulder surely hurts!
49. There those thousand thinkers were thinking how did the other three thieves go through.
50. There's a sandwich on the sand which was sent by a sane witch.
51. Two tiny tigers take two taxis to town.
52. Very well, very well, very well ...
53. What noise annoys an oyster most? A noisy noise annoys an oyster most.
54. Willie's really weary.
Englsih Tongue-Twisters 英語繞口令
What is a tongue-twister ?
編者說明:
本教程旨在為具有一定基礎(chǔ)的廣大英語愛好者提供規(guī)范的英語國際音標(biāo)常見的數(shù)據(jù),包括音標(biāo)總表及分類,26個英文字母的標(biāo)準(zhǔn)發(fā)音,大量的練習(xí)用例詞和例句,實用的語音練習(xí)方法等。
因篇幅較長,事先用WORD排版和編輯過,導(dǎo)入過來后一大堆亂碼。音標(biāo)符號屬于特殊符號,要在電腦上正常顯示必須安裝特定的字體文件,或者從網(wǎng)絡(luò)中尋找特定格式的符號一個個拷貝過來,是一個龐大而繁瑣的工程。好在我終于完成了!
不知什么原因,頭條導(dǎo)入的文章編輯功能有一定限制,不能任意加粗字體,不能有序或無序編號,有些內(nèi)容只好忍痛放棄。受篇幅和排版功能的限制,本教程未列出詳細(xì)發(fā)音口型示意圖和發(fā)音要領(lǐng),需要的朋友可以參考其它音標(biāo)教材或網(wǎng)絡(luò)獲取。
關(guān)于在電腦中怎樣正常輸入和顯示英語音標(biāo)符號,我計劃另外寫一篇文章單獨詳細(xì)介紹。不管是老師還是學(xué)生,或者是其它從業(yè)人員,歡迎所有英語愛好者加入我們的交流,共同學(xué)習(xí),共同進(jìn)步!
如果有問題的朋友,可以私信頭條號:云夢夜話。
2018年2月7日16:36。
Servlet是屬于上層建筑,它處在應(yīng)用層,它的下層有傳輸層,網(wǎng)絡(luò)層,數(shù)據(jù)鏈路層,硬件,屬于“經(jīng)濟(jì)基礎(chǔ)”,畢竟下層經(jīng)濟(jì)基礎(chǔ)決定上層建筑。前面說過,Servlet是一組操作HTTP的API,Tomcat可作為HTTP服務(wù)器來處理請求,這個處理請求的關(guān)鍵就是調(diào)用Servlet來操作HTTP給客戶端做出響應(yīng)。
我們所寫的Servlet代碼沒有main方法,那他是如何運行的呢?其實是Tomcat在調(diào)用Servlet,Tomcat其實就是一個應(yīng)用程序,是運行在用戶態(tài)上的一個普通的Java進(jìn)程。
當(dāng)瀏覽器發(fā)送請求給服務(wù)器的時候,Tomcat作為HTTP Server會調(diào)用Serlvet API,然后執(zhí)行我們所寫的Servlet程序來處理請求。
處理請求的過程中牽涉的不僅僅只有HTTP,還有其他層的協(xié)議,但是我們并沒有感知到其他層協(xié)議的細(xì)節(jié),只關(guān)注了應(yīng)用層HTTP協(xié)議的細(xì)節(jié),這就是協(xié)議分層好處,程序員在實現(xiàn)處理請求時,不必去關(guān)心應(yīng)用層下面的細(xì)節(jié)。
為了方便描述Tomcat的執(zhí)行邏輯,我們使用偽代碼的形式來分析:
初始化與收尾工作,又細(xì)分為以下幾部分:
1)從指定的目錄中找到Servlet類,并加載。
2根據(jù)加載的結(jié)果,給這些類型創(chuàng)建實例。
3)創(chuàng)建好實例后,調(diào)用Servlet對象中的 init 方法。
4)創(chuàng)建TCP socket對象,監(jiān)聽8080端口,等待客戶端來連接。
5)如果請求處理完畢,也就是處理請求的循環(huán)退出了,那Tomcat也結(jié)束了,調(diào)用 destroy 方法結(jié)束進(jìn)程,但是這個環(huán)節(jié)不一定可靠,正常退出的情況下,需要在管理端口(8005)去調(diào)用 destroy ,將Tomcat關(guān)閉,但很多時候都是直接殺死進(jìn)程來達(dá)到關(guān)閉的目的,此時根本來不及調(diào)用 dsetroy 方法。
class Tomcat {
// 用來存儲所有的 Servlet 對象
private List<Servlet> instanceList = new ArrayList<>();
public void start() {
// 根據(jù)約定,讀取 WEB-INF/web.xml 配置文件;
// 并解析被 @WebServlet 注解修飾的類
// 假定這個數(shù)組里就包含了我們解析到的所有被 @WebServlet 注解修飾的類.
Class<Servlet>[] allServletClasses = ...;
// 這里要做的的是實例化出所有的 Servlet 對象出來;
for (Class<Servlet> cls : allServletClasses) {
// 這里是利用 java 中的反射特性做的
// 實際上還得涉及一個類的加載問題,因為我們的類字節(jié)碼文件,是按照約定的
// 方式(全部在 WEB-INF/classes 文件夾下)存放的,所以 tomcat 內(nèi)部是
// 實現(xiàn)了一個自定義的類加載器(ClassLoader)用來負(fù)責(zé)這部分工作。
Servlet ins = cls.newInstance();
instanceList.add(ins);
}
// 調(diào)用每個 Servlet 對象的 init() 方法,這個方法在對象的生命中只會被調(diào)用這一次;
for (Servlet ins : instanceList) {
ins.init();
}
// 利用我們之前學(xué)過的知識,啟動一個 HTTP 服務(wù)器
// 并用線程池的方式分別處理每一個 Request
ServerSocket serverSocket = new ServerSocket(8080);
// 實際上 tomcat 不是用的固定線程池,這里只是為了說明情況
ExecuteService pool = Executors.newFixedThreadPool(100);
while (true) {
Socket socket = ServerSocket.accept();
// 每個請求都是用一個線程獨立支持,這里體現(xiàn)了我們 Servlet 是運行在多線程環(huán)境下的
pool.execute(new Runnable() {
doHttpRequest(socket);//處理請求
});
}
// 調(diào)用每個 Servlet 對象的 destroy() 方法,這個方法在對象的生命中只會被調(diào)用這一次;
for (Servlet ins : instanceList) {
ins.destroy();
}
}
public static void main(String[] args) {
new Tomcat().start();
}
}
Tomcat處理請求工作:
1)讀取socket中的數(shù)據(jù),并按照HTTP協(xié)議的格式來進(jìn)行解析,獲取請求。
2)判斷請求是需要靜態(tài)內(nèi)容還是動態(tài)內(nèi)容,如果是靜態(tài)內(nèi)容,可以在根路徑上找到目的文件,返回請求
3)如果是動態(tài)文件,則需要通過URL上的一級路徑與二級路徑來確定通過哪一個Servlet類來進(jìn)行處理,沒有的話就會返回404
4)找到對應(yīng)Servlet對象,調(diào)用對象里面的 service 方法,根據(jù)請求的方法來調(diào)用對應(yīng)的 do... 方法
class Tomcat {
void doHttpRequest(Socket socket) {
// 參照我們之前學(xué)習(xí)的 HTTP 服務(wù)器類似的原理,進(jìn)行 HTTP 協(xié)議的請求解析,和響應(yīng)構(gòu)建
HttpServletRequest req = HttpServletRequest.parse(socket);
HttpServletRequest resp = HttpServletRequest.build(socket);
// 判斷 URL 對應(yīng)的文件是否可以直接在我們的根路徑上找到對應(yīng)的文件,如果找到,就是靜態(tài)
// 直接使用我們學(xué)習(xí)過的 IO 進(jìn)行內(nèi)容輸出
if (file.exists()) {
// 返回靜態(tài)內(nèi)容
return;
}
// 走到這里的邏輯都是動態(tài)內(nèi)容了
// 根據(jù)我們在配置中說的,按照 URL -> servlet-name -> Servlet 對象的鏈條
// 最終找到要處理本次請求的 Servlet 對象
Servlet ins = findInstance(req.getURL());
// 調(diào)用 Servlet 對象的 service 方法
// 這里就會最終調(diào)用到我們自己寫的 HttpServlet 的子類里的方法了
try {
ins.service(req, resp);
} catch (Exception e) {
// 返回 500 頁面,表示服務(wù)器內(nèi)部錯誤
}
}
}
service方法執(zhí)行邏輯:
class Servlet {
public void service(HttpServletRequest req, HttpServletResponse resp) {
String method = req.getMethod();
if (method.equals("GET")) {
doGet(req, resp);
} else if (method.equals("POST")) {
doPost(req, resp);
} else if (method.equals("PUT")) {
doPut(req, resp);
} else if (method.equals("DELETE")) {
doDelete(req, resp);
}
......
}
}
在整個流程中,有三個關(guān)鍵的方法:
init
HttpServlet關(guān)鍵方法:
方法名稱 | 調(diào)用時機(jī) |
init | 在 HttpServlet 實例化之后被調(diào)用一次 |
destory | 在 HttpServlet 實例不再使用的時候調(diào)用一次 |
service | 收到 HTTP 請求的時候調(diào)用 |
doGet | 收到 GET 請求的時候調(diào)用(由 service 方法調(diào)用) |
doPost | 收到 POST 請求的時候調(diào)用(由 service 方法調(diào)用) |
doPut/doDelete/doOptions/… | 收到其他請求的時候調(diào)用(由 service 方法調(diào)用) |
這些方法的調(diào)用時機(jī),就構(gòu)成了“Servlet”的生命周期。
HttpServletRequest關(guān)鍵方法:
方法 | 描述 |
String getProtocol() | 返回請求協(xié)議的名稱和版本。 |
String getMethod() | 返回請求的 HTTP 方法的名稱,例如,GET、POST 或 PUT。 |
String getRequestURI() | 從協(xié)議名稱直到 HTTP 請求的第一行的查詢字符串中,返回該請求的 URL 的層次路徑部分。 |
String getContextPath() | 返回指示請求上下文的請求 URI 部分(一級路徑)。 |
String getQueryString() | 返回包含在路徑后的請求 URL 中的查詢字符串。 |
Enumeration getParameterNames() | 返回一個 String 對象的枚舉,包含在該請求中包含的參數(shù)的名稱。 |
String getParameter(String name) | 以字符串形式返回請求參數(shù)的值,或者如果參數(shù)不存在則返回null。 |
String[] getParameterValues(String name) | 返回一個字符串對象的數(shù)組,包含所有給定的請求參數(shù)的值,如果參數(shù)不存在則返回 null。 |
Enumeration getHeaderNames() | 返回一個枚舉,包含在該請求中包含的所有的頭名。 |
String getHeader(String name) | 以字符串形式返回指定的請求頭的值。 |
String getCharacterEncoding() | 返回請求主體中使用的字符編碼的名稱。 |
String getContentType() | 返回請求主體的 MIME 類型,如果不知道類型則返回 null。 |
int getContentLength() | 以字節(jié)為單位返回請求主體的長度,并提供輸入流,或者如果長度未知則返回 -1。 |
InputStream getInputStream() | 用于讀取請求的 body 內(nèi)容. 返回一個 InputStream 對象. |
HttpServletResponse關(guān)鍵方法:
方法 | 描述 |
void setStatus(int sc) | 為該響應(yīng)設(shè)置狀態(tài)碼。 |
void setHeader(String name, String value) | 設(shè)置一個帶有給定的名稱和值的 header. 如果 name 已經(jīng)存在,則覆蓋舊的值,可以實現(xiàn)頁面的刷新 |
void addHeader(String name, String value) | 添加一個帶有給定的名稱和值的 header. 如果name 已經(jīng)存在,不覆蓋舊的值, 并列添加新的鍵值對 |
void setContentType(String type) | 設(shè)置被發(fā)送到客戶端的響應(yīng)的內(nèi)容類型。 |
void setCharacterEncoding(String charset) | 設(shè)置被發(fā)送到客戶端的響應(yīng)的字符編碼(MIME 字符集)例如,UTF-8。 |
void sendRedirect(String location) | 使用指定的重定向位置 URL 發(fā)送臨時重定向響應(yīng)到客戶端。 |
PrintWriter getWriter() | 用于往 body 中寫入文本格式數(shù)據(jù). |
OutputStream getOutputStream() | 用于往 body 中寫入二進(jìn)制格式數(shù)據(jù). |
在同一webapp里面,關(guān)聯(lián)路徑不能夠相同,不然Tomcat跑不起來,對于GET請求,可以使用URL的查詢字符串進(jìn)行構(gòu)造,但是POST請求不行,需要使用form或者ajax。
構(gòu)造Post請求(使用ajax構(gòu)造):
在webapp目錄下創(chuàng)建一個HTML文件,用來構(gòu)造POST請求,首先我們先的引入 jquery 依賴(博主使用的是本地導(dǎo)入,你可以如果網(wǎng)絡(luò)地址: https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js 導(dǎo)入依賴),然后調(diào)用ajax構(gòu)造請求。
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
$.ajax({
type: "post",
url: "method",
success: function (body){
console.log(body);
}
})
</script>
注意上面的URL屬性不能加 / ,加上表示的就是絕對路徑了,當(dāng)然你也可以使用 ./ 來表示相對路徑,但是在Servlet注解關(guān)聯(lián)路徑必須得加上 / 。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/method")
public class MethodServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("POST請求");
}
}
我們訪問 http://127.0.0.1:8080/hello_servlet/test.html 來看控制臺輸出的返回結(jié)果。
我們發(fā)現(xiàn)與我們的預(yù)期不一致,我們處理請求的時候返回了 POST請求 ,而這里顯示了 POST?? ,原因是發(fā)生了亂碼,idea默認(rèn)編碼格式為 utf-8 ,Windows默認(rèn)的編碼格式是 gbk ,那瀏覽器解析body的時候也是以 gbk 格式去進(jìn)行解析,要想統(tǒng)一格式,就得先告訴瀏覽器響應(yīng)數(shù)據(jù)的編碼格式是什么,我們需要在Servlet程序里面設(shè)置字符格式,設(shè)置方法為調(diào)用HttpServletResponse對象的 setContentType 方法,傳入?yún)?shù) text/html; charset=utf8 。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/method")
public class MethodServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf8");
resp.getWriter().write("POST請求");
}
}
重新打包部署,刷新頁面:
對于請求的信息,我們運用HttpServletRequest類的方法來進(jìn)行請求信息的獲取:
比如我們訪問的url為 http://127.0.0.1:8080/hello_servlet/showreq?key=10&a=100&b=200 ,很明顯這是使用查詢字符串構(gòu)造的一個GET請求,通過HttpServletRequest類一系列對應(yīng)的方法,我們可以獲取到這個請求的方法類型,協(xié)議版本,URL,查詢字符串,頭部的一些信息等。其中查詢字符串與頭部信息的獲取先要使用getParameterNames方法或者getHeaderNames方法獲取所有的查詢字符串或頭部信息的所有 key 值,這個一個枚舉對象,然后在根據(jù)getParameter或者getHeader方法通過 key 值遍歷枚舉對象獲取 value 。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
@WebServlet("/showreq")
public class ShowRequestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//訪問鏈接:http://127.0.0.1:8080/hello_servlet/showreq?key=10&a=100&b=200
StringBuilder stringBuilder = new StringBuilder();
resp.setContentType("text/html; charset=utf-8");
//1協(xié)議名稱與版本
stringBuilder.append("協(xié)議版本:");
stringBuilder.append(req.getProtocol());
stringBuilder.append("<br>");
//2方法類型
stringBuilder.append("方法:");
stringBuilder.append(req.getMethod());
stringBuilder.append("<br>");
//3獲取查URL路徑
stringBuilder.append("URL路徑:");
stringBuilder.append(req.getRequestURI());
stringBuilder.append("<br>");
//4URL(不包括查詢字符串后面的部分)
stringBuilder.append("URL(不包括查詢字符串后面的部分):");
stringBuilder.append(req.getRequestURL());
stringBuilder.append("<br>");
//5一級路徑
stringBuilder.append("一級路徑:");
stringBuilder.append(req.getContextPath());
stringBuilder.append("<br>");
//6查詢字符串
stringBuilder.append("查詢字符串:");
stringBuilder.append(req.getQueryString());
stringBuilder.append("<br>");
//7正文編碼格式
stringBuilder.append("正文編碼格式:");
stringBuilder.append(req.getCharacterEncoding());
stringBuilder.append("<br>");
//8mine
stringBuilder.append("mine:");
stringBuilder.append(req.getContentType());
stringBuilder.append("<br>");
//9正文長度
stringBuilder.append("正文長度:");
stringBuilder.append(req.getContentLength());
stringBuilder.append("<br>");
//10獲得每一個查詢字符串的鍵值:
stringBuilder.append("<h3>獲得每一個查詢字符串的鍵值:</h3>");
Enumeration query = req.getParameterNames();
while(query.hasMoreElements()) {
String key = (String)query.nextElement();
stringBuilder.append(key);
stringBuilder.append(":");
stringBuilder.append(req.getParameter(key));
stringBuilder.append("<br>");
}
//11獲得頭部的鍵值
stringBuilder.append("<h3>獲得頭部的鍵值:</h3>");
Enumeration header = req.getHeaderNames();
while(header.hasMoreElements()) {
String key = (String)header.nextElement();
stringBuilder.append(key);
stringBuilder.append(":");
stringBuilder.append(req.getHeader(key));
stringBuilder.append("<br>");
}
resp.getWriter().write(stringBuilder.toString());
}
}
結(jié)果:
我們知道post請求的請求信息在http格式中的 body 部分當(dāng)中,而 body 中的請求內(nèi)容的格式是有很多種的,比如最常見的有:
k e y = v a l u e & k e y = v a l u e & . . . key=value\&key=value\&... k e y = v a l u e & k e y = v a l u e & . . .
form表單創(chuàng)建 x-www-form-urlencode格式 請求:
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<title>post</title>
</head>
<body>
<form action="./postParameter" method="post" accept-charset="utf-8">
<span>userId</span>
<input type="text" name="userId">
<span>classId</span>
<input type="text" name="classId">
<input type="submit" value="提交">
</form>
</body>
</html>
Servlet程序接收和處理請求:
對于 x-www-form-urlencode格式 請求可以直接使用 HttpServletRequest 中的 getParameter 方法依據(jù) key 來獲取 value ,然后再將獲取到的數(shù)據(jù)返回,form表單構(gòu)造的請求會自動跳轉(zhuǎn)頁面。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/postParameter")
public class GetPostParameterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//獲取post請求body請求中的參數(shù)
//設(shè)置請求與響應(yīng)編碼格式
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html; charset=utf8");
//比如useId = classId=
String userId = req.getParameter("userId");
String classId = req.getParameter("classId");
//寫會數(shù)據(jù)
resp.getWriter().write("userId=" + userId + ", " + "classId=" + classId);
}
}
運行結(jié)果:
json格式:
{ \{ {
k e y : v a l u e , key:value, k e y : v a l u e ,
k e y : v a l u e , key:value, k e y : v a l u e ,
k e y : v a l u e , key:value, k e y : v a l u e ,
. . . ... . . .
} \} }
對于json格式,手動解析不容易,因為json里面的字段是可以嵌套的,但我們可以借助第三方庫來解析處理json,比如Jackson,Jackson依賴導(dǎo)入過程如下:
處理json請求步驟:
第一步,在前端js代碼中構(gòu)造出格式為 json 格式的請求。
其中 ajax 構(gòu)造 post 請求,使用 contentType 來說明請求的類型, data 屬性來設(shè)置 body 的內(nèi)容。
<!DOCTYPE html>
<html lang="cn">
<head>
<meta charset="UTF-8">
<title>json</title>
</head>
<body>
<!-- 前端HTML部分 -->
<input type="text" id="userId">
<input type="text" id="classId">
<input type="button" id="submit" value="提交">
<!-- 如果已經(jīng)準(zhǔn)備好本地的jQuery就導(dǎo)入本地的,否則可以找網(wǎng)上的jQuery cdn網(wǎng)絡(luò)路徑 -->
<script src="./jquery3.6.0.js"></script>
<script>
let userIdInput = document.querySelector("#userId");
let classIdInput = document.querySelector("#classId");
let button = document.querySelector("#submit");
button.onclick = function() {
$.ajax({
type : "post",
url: "getJsonPost",
contentType: "appliaction/json",
data:JSON.stringify({
userId: userIdInput.value,
classId:classIdInput.value
}),
success: function(body){
console.log(body);
}
})
}
</script>
</body>
</html>
第二步,在java后端代碼中使用Jackson處理。
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
class User {
public String userId;
public String classId;
}
@WebServlet("/getJsonPost")
public class GetJsonPostServlet extends HttpServlet {
//1.創(chuàng)建一個Jackson的核心對象
private ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//格式
resp.setContentType("text/html; charset=utf8");
//處理
//2.讀取body請求的內(nèi)容,使用ObjectMapper對象的readValue方法來解析
//就是將字符串轉(zhuǎn)換成java的對象,readValue方法的第一個參數(shù)可以是路徑字符串可以是輸入流對象,引入可以是File對象
//第二個參數(shù),表示需要將請求的json格式數(shù)據(jù)轉(zhuǎn)換成哪一個java對象
User user = objectMapper.readValue(req.getInputStream(), User.class);
System.out.println(user.userId);
System.out.println(user.classId);
resp.getWriter().write("userId=" + user.userId + " ,classId=" + user.classId);
}
}
運行結(jié)果:
readValue 方法基本原理:
案例1:設(shè)置響應(yīng)狀態(tài)碼
設(shè)置方法很簡單,只需要調(diào)用 httpServletResponse 對象中的 setStatus 方法就可以了
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/status")
public class StatusServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//格式
resp.setContentType("text/html; charset=utf8");
//設(shè)置狀態(tài)碼
int status = 200;
resp.setStatus(status);
resp.getWriter().write("hello,這是" + status + "狀態(tài)碼的響應(yīng)內(nèi)容!");
}
}
啟動程序,網(wǎng)頁顯示如下:
我把狀態(tài)碼修改為 404 ,網(wǎng)頁顯示如下:
那為什么不是之前我們所遇到的那種404頁面呢?這是因為我們設(shè)置的頁面響應(yīng)內(nèi)容就是 hello,這是404狀態(tài)碼的響應(yīng)內(nèi)容! ,可以理解為自定義的 404 狀態(tài)響應(yīng)頁面,就像其他的網(wǎng)站,如果訪問不到頁面,顯示的提醒頁面也是不一樣的,比如b站的頁面是這個樣子的:
案例2:自動頁面刷新
自動頁面刷新只要在響應(yīng)中設(shè)置一個header: Refresh就能實現(xiàn)頁面的定時刷新了,對于響應(yīng) header 的設(shè)置,我們可以通過 HttpServletResponse 對象中的 setHeader 方法來設(shè)置Refresh屬性和刷新頻率。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/autorefresh")
public class AutoRefreshServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//格式
resp.setContentType("text/html; charset = utf8");
//設(shè)置Refresh,第二個參數(shù)表示刷新頻率,單位是秒
resp.setHeader("Refresh", "1");
//響應(yīng)
resp.getWriter().write("時間戳:" + System.currentTimeMillis());
}
}
效果:
案例3:重定向案例
第一步,設(shè)置狀態(tài)碼為 302 。
第二步,設(shè)置header:Location,調(diào)用 setHeader 方法時,第一個參數(shù)填 Location ,表示設(shè)置 header 字段為 Location ,第二個參數(shù)為重定向的目的地址,你要重定向到哪一個網(wǎng)址就傳入哪一個地址的字符串。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//格式
resp.setContentType("text/html; charset = utf8");
//設(shè)置狀態(tài)碼
resp.setStatus(302);
//設(shè)置重定向字段與地址,如跳轉(zhuǎn)到力扣官網(wǎng)
resp.setHeader("Location", "https://leetcode.cn/");
}
}
效果:
當(dāng)然,servlet提供了更為簡便的重定向方法,就是使用 HttpServletResponse 類中的 sendRedirect 方法。
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//格式
resp.setContentType("text/html; charset = utf8");
//設(shè)置狀態(tài)碼
// resp.setStatus(302);
// //設(shè)置重定向字段與地址,如跳轉(zhuǎn)到力扣官網(wǎng)
// resp.setHeader("Location", "https://leetcode.cn/");
resp.sendRedirect("https://leetcode.cn/");
}
}
效果與上面第一種方法是一樣的。
原文:https://blog.csdn.net/m0_59139260/article/details/125578758
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。