柚子快報邀請碼778899分享:java Servlet
1.編寫一個簡單的Servlet程序?
1.1 創(chuàng)建項目
?
?Maven是JAVA中一個常用的"構(gòu)建工具".
一個程序,編寫過程中,往往需要涉及到一些第三方庫的依賴,另外還需要對這個寫好的程序進行打包部署.
Maven存在的意義,就是為了能夠方便的進行依賴管理和打包.
1.2 引入依賴
當(dāng)前的代碼要使用Servlet開發(fā),而Servlet并不是java標(biāo)準(zhǔn)庫自帶的,就需要讓maven能夠把Servlet的依賴給獲取出來.
在maven中央倉庫中找到依賴.
手動創(chuàng)建一個
此時IDEA就會自動的通過maven從中央倉庫來下載這里的依賴.
?
1.3 手動創(chuàng)建一些必要的目錄文件
?
此處的目錄結(jié)構(gòu),目錄名字,都是固定的.
web.xml就是告訴tomcat,現(xiàn)在這個目錄里的東西就是一個webapp,要把加載起來.
當(dāng)然,web.xml里,需要寫一些固定的內(nèi)容.
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
1.4 編寫代碼
?這里簡單寫一個Hello World
這個doGet方法不需要手動調(diào)用,doGet本質(zhì)上也是一個"回調(diào)函數(shù)".
把這個方法寫好之后,就會交給Tomcat,Tomcat在收到一個合適的GET請求的時候,就會自動調(diào)用doGet.
調(diào)用doGet的時候,tomcat就會解析這次的HTTP請求.生成一個HTTPServletRequest對象.(這個對象里的屬性什么的都是和HTTP協(xié)議格式匹配的)
同時,Tomcat也會構(gòu)造出一個空的HTTPServletResponse對象(這個空不是null,而是一個new好的,但是沒有初始化屬性的對象,把這個resp對象也會傳遞到doGet里面)
doGet要做的事情,就是根據(jù)這次請求,計算出響應(yīng).
doGet里的代碼,就是根據(jù)rep里不同的參數(shù)的細節(jié),生成一個具體的resp對象(往空對象里設(shè)置屬性)
tomcat就會根據(jù)這個響應(yīng)對象,轉(zhuǎn)換成符合HTTP協(xié)議的響應(yīng)報文,返回給瀏覽器了.
總之,doGet做的事,就是根據(jù)請求計算出響應(yīng).
一個Servlet程序里,可能有多個Servlet類的.
這些Servlet類,就需要在不同的情況下被執(zhí)行到了.
當(dāng)請求的路徑中帶有hello的時候,才能執(zhí)行到這個HelloServlet的代碼.
不同的Servlet類,就可以關(guān)聯(lián)到不同的路徑.
問:
這個代碼寫完了嗎,不需要一個main方法嘛?
Servlet程序,不需要main方法!!!一個程序,是需要main方法,作為入口.實際上,我們寫的這個代碼,并不是獨立的程序,而是放到Tomcat上執(zhí)行的.main方法其實是在tomcat里的.我們寫的這些doGet之類的,都是讓Tomcat來調(diào)用的.
1.5 打包程序
我們的程序是放在Tomcat上執(zhí)行的,就需要對程序進行打包.
打成一個Tomcat能識別的包的格式,此時代碼才會被Tomcat給加載起來.
打包,也是借助maven完成的.
?
看到BUILD SUCCESS即為打包成功.
此時,就會出現(xiàn)下述內(nèi)容.
在maven中,默認打包生成的是jar包,但是tomcat需要的是war包!
此時就需要修改pom.xml,添加一個
當(dāng)然,也可以給打包命名
?下面重新打包,就可以把這個war包放到tomcat里了.
1.6 部署
?把寫好的war包,放到Tomcat上.
具體就是,把這個war包拷貝到Tomcat的webapps的目錄中.
啟動Tomcat即可.
1.7 驗證程序,是否能夠正常工作
通過瀏覽器發(fā)起HTTP Get請求,觸發(fā)剛才的Servle代碼.
?
通過第一級路徑,確定一個webapp
通過第二級路徑,確定哪個Servlet
通過方法,確定執(zhí)行Servlet中的哪個方法?
2. Smart Tomcat插件
觀察上述程序,如果要修改代碼,就得重復(fù)步驟5,6,7.比較麻煩
這個時候就可以使用Smart Tomcat插件,讓IDEA和Tomcat集成起來.
第一次使用Smart Tomcat需要簡單配置
?
點擊這里,就可以運行了.?
這是怎么回事呢?
因為我們前面啟動了Tomcat,之前的Tomcat已經(jīng)占用了8080,一個端口號只能被一個進程綁定.
把之前的Tomcat關(guān)閉,再啟動:
此時,啟動成功.
3. 一些訪問出錯
3.1 404
?瀏覽器要訪問的資源,在服務(wù)器上不存在!!!
①檢查你請求的路徑,和你服務(wù)器這邊的配置,是否一致.
②確認你的webapp是否被正確加載.
Smart Tomcat由于只是加載這一個webapp,如果加載失敗,就會直接啟動失敗.
拷貝war的方式,Tomcat要加載多個webapp,如果加載失敗,只會有日志.(觀察是否有"部署成功")
如果web.xml沒有/目錄錯了/內(nèi)容錯了/名字拼寫錯了,都可能引起加載失敗!!!
3.2 405
①寫的doXX方法,和請求發(fā)起的方法,是不匹配的.
瀏覽器發(fā)起GET請求,服務(wù)器代碼寫的是doPost
在瀏覽器地址欄輸入URL,發(fā)起的是get請求,但是服務(wù)器寫的是doPost.
②發(fā)的是Get請求,服務(wù)器寫的也是doGet,但是沒有把supe.doGet給刪了.
?
?
3.3 500
?服務(wù)器內(nèi)部錯誤,代碼中拋出異常了.
?
3.4 空白頁面
往往是沒有執(zhí)行g(shù)etWriter.write方法.
?
3.5 無法訪問此網(wǎng)站
這種情況,要么就是Tomcat服務(wù)器沒有正確運行.
要么就是ip或端口號編寫的不對.
4.Servlet API
API就是一組類和方法.
Servlet中的類很多,這里詳解其中三個
4.1 HTTPServlet
我們寫 Servlet 代碼的時候, 首先第一步就是先創(chuàng)建類, 繼承自 HttpServlet, 并重寫其中的某些方法,讓Tomcat去調(diào)用到這里的邏輯.
4.1.1?核心方法
方法名稱方法名稱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)用)
①init方法:
webapp被加載的時候,執(zhí)行init,使用這個方法,進行一些初始化操作.
②destory方法:
webapp在被銷毀的時候(Tomcat結(jié)束)執(zhí)行destory,使用這個方法進行一些收尾工作.
當(dāng)然,這個方法不保證能夠被調(diào)用到.
1.通過8005端口,給Tomcat發(fā)起特殊的請求,Tomcat就關(guān)閉了.(能夠執(zhí)行destory)
2.直接殺死Tomcat進程.(無法執(zhí)行到destory了)
③service方法:
每次收到請求,都會執(zhí)行service,處理每個請求.
往往使用doXX方法替代service.
[面試題]談?wù)凷ervlet的生命周期:
生命周期,更嚴(yán)格的理解"什么階段,做什么事情".
就像人的幼兒,少年,青年,中年,老年,每個時期要做的事情是不一樣的.
1)webapp剛被加載的時候,調(diào)用Servlet的init方法.
2)每次收到請求的時候,調(diào)用service方法.
3)webapp要結(jié)束的時候,調(diào)用destroy方法.
4.1.2 示例一:處理請求
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/method")
public class MethodServlet extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("doGet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("doPost");
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("doPut");
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("doDelete");
}
}
針對上述的這三個方法,瀏覽器只能比較方便的構(gòu)get請求,不太方便構(gòu)造其它的.使用ajax或postman.?
?
4.2 HTTPServletRequest
HTTPServletRequest是和HTTP請求數(shù)據(jù),是匹配的.?
?4.2.1 核心方法
方法描述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 對象.
①String getRequestURI()方法:
URL唯一資源定位符,描述了網(wǎng)絡(luò)上的一個資源.
URI唯一資源標(biāo)識符.
URL也可以理解成URI的一種實現(xiàn)方式.
②Enumeration getParameterNames()和String getParameter(String name)方法:
可以通過一些方式,給服務(wù)器傳遞自定義數(shù)據(jù).
1.query string
2.body(通過post form表單的形式提交的請求的話,此時body也是鍵值對格式)
query string本身就是鍵值對結(jié)構(gòu)的數(shù)據(jù),Tomcat收到這個請求之后,就會把這個query string解析成Map,使用getParameter就可以根據(jù)key獲取到value.
③Enumeration getHeaderNames()和String getHeader(String name)方法:
獲取到請求頭里的鍵值對.
Tomcat收到請求之后也會把請求頭解析長Map.
④InputStream getInputStream()方法:
讀取這個流對象就能得到body的內(nèi)容.
Ajax也可以把提交的數(shù)據(jù)放到query string中,使用getParameter獲取.
如果使用ajax POST提交json格式的數(shù)據(jù)(或者其它非form表單的格式),就需要getInputStream來獲取了.
4.2.2 示例一:打印請求信息
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("/request")
public class RequestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//這個操作是必要的,顯示告訴瀏覽器,你拿到的數(shù)據(jù)是html
resp.setContentType("text/html");
//調(diào)用req的各個方法,把得到的結(jié)果匯總到一個字符串中,統(tǒng)一返回到頁面上.
StringBuilder respBody = new StringBuilder();
//下列內(nèi)容是在瀏覽器上按照html的方式來展示的,此時\n在html中并不是換行.
//而使用
標(biāo)簽來表示換行
respBody.append(req.getProtocol());
respBody.append("
");
respBody.append(req.getMethod());
respBody.append("
");
respBody.append(req.getRequestURI());
respBody.append("
");
respBody.append(req.getQueryString());
respBody.append("
");
//拼接header
Enumeration
//迭代器遍歷枚舉里面的每個部分
while (headers.hasMoreElements()){
String header = headers.nextElement();//取回
respBody.append(header);
respBody.append(header + ": " + req.getHeader(header));//header的key和value
respBody.append("
");
}
//返回結(jié)果
resp.getWriter().write(respBody.toString());
}
}
?
如何獲取到query string和body的數(shù)據(jù)?
4.2.3 示例二:獲取 GET 請求中的參數(shù)?
獲取query string:
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("/parameter")
public class ParameterServlet extends HttpServlet {
//約定,客戶端使用query string傳遞數(shù)據(jù)
//query string形如: username=zhangshan&password=123
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("username= "+ username);
System.out.println("password= "+ password);
resp.getWriter().write("ok");
}
}
4.2.4 示例三:?獲取 POST 請求中的參數(shù)
4.2.4.1 獲取body(考慮form表單的格式)
form表單:和query string格式意義,也是鍵值對.
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("/parameter2")
public class Parameter2Servlet extends HttpServlet {
//預(yù)期讓客戶端發(fā)送一個POST請求,同時使用form格式的數(shù)據(jù),在body中把數(shù)據(jù)傳送過來
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println("username= "+ username);
System.out.println("password= "+ password);
resp.getWriter().write("ok");
}
}
?
4.2.4.2 獲取body(考慮json格式)
這種格式在開發(fā)中非常常見.
Servlet自身不能對json格式的數(shù)據(jù)進行解析,需要引入第三方庫:
那么如何使用ObjectMapper?
Map也叫做映射表.
把一個對象映射到JSON字符串,也可以把JSON字符串映射到對象.
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 username;
public String password;
}
@WebServlet("/json")
public class JsonServlet extends HttpServlet {
/**
此處約定客戶端body按照json格式來進行傳輸
* {
* username:"zhangshan"
* password:"123"
* }
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(req.getInputStream(),User.class);//從字符串到對象
System.out.println("username= " + user.username +", password= "+user.password);
//也可以java對象轉(zhuǎn)成json字符串
String userString = objectMapper.writeValueAsString(user);
System.out.println("userString: "+userString);
resp.getWriter().write("ok");
}
}
?
這個方法有很多版本,作用就是把json字符串給解析成JAVA對象.
其中這里第一個參數(shù),是一個流對象,也就表示json從哪里來讀.
請求的body是通過getlnputStream得到流對象,進一步讀出來的.
請求的第二個參數(shù),則是指定的類型.當(dāng)前你這邊得到的json字符串,需要轉(zhuǎn)成什么樣的一個java對象,需要指定一下對象的類型.
就可以定義一個類,讓這個類里的屬性的名字和類型都和json字符串匹配.
這里必須先知道json的結(jié)構(gòu)是什么,才能夠根據(jù)json結(jié)構(gòu),構(gòu)造出User對象.
readValue就把req的body中的字符串讀取并解析了,然后構(gòu)造成了User對象,User對象中的屬性,就是前面json中所體現(xiàn)的內(nèi)容.
在這里寫json格式的時候,key也加上了",但是之前在注釋里沒寫?
在ison格式中,key一定是字符串類型,所以原則上,key不寫"也是完全可以的.
但是有些庫/程序,檢查更加嚴(yán)格,就必須強制寫".
js的ajax方式構(gòu)造json,此時key是沒有引號的.
但是使用postman構(gòu)造的json,此時key就需要引號.
此處的public能不能寫成private?
不能,會出現(xiàn)500.
本身,jackson會通過反射的方式,把User類里包含的public的屬性給獲取到.
此時,就可以根據(jù)反射這里得到的"屬性名字",去json解析出來的鍵值對中進行匹配.
如果匹配到了,就把value設(shè)置到剛才得到的屬性中.
由于把username改成了private,而Jackson并不會直接針對private屬性進行掃描,username就不認識了.
當(dāng)然,提供對應(yīng)的getter和setter方法就可以寫成private
[重點理解]jackson的readValue工作過程:
先把json字符串解析成鍵值對,放到Map中.再根據(jù)參數(shù)填入的類對象,通過反射API就可以知道,這個類里面有什么屬性,每個屬性的名字和類型.一次把這里的每個屬性都取出來,通過屬性名字查詢上述的Map,把得到的值,賦給這個類的屬性.
?
4.3 HTTPServletResponse
HTTPServletResponse同樣也是和HTTP響應(yīng)數(shù)據(jù),是匹配的.
針對狀態(tài)碼,各種header,body這些屬性,就可以進行"設(shè)置".
請求對象,我們拿到之后的目的,是為了獲取里面的屬性(讀).響應(yīng)對象,?我們拿到之后的目的,是為了設(shè)置里面的屬性(寫).
對于doXX這樣的方法來說,本身要做的事情就是"根據(jù)請求計算響應(yīng)".
請求對象,是Tomcat收到請求之后,對HTTP協(xié)議解析得到的對象.響應(yīng)對象,是Tomcat創(chuàng)建的空的對象,我們在代碼中把響應(yīng)對象的屬性設(shè)置好.(響應(yīng)對象,相當(dāng)于是一個輸出型參數(shù))
4.3.1 核心方法?
方法描述void setStatus(int sc)為該響應(yīng)設(shè)置狀態(tài)碼。void setHeader(String name, String value)設(shè)置一個帶有給定的名稱和值的 header. 如果 name 已經(jīng)存在, 則覆蓋舊的值.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 中寫入二進制格式數(shù)據(jù).
①void setCharacterEncoding(String charset)方法:
這里是告訴瀏覽器,要按照什么樣的字符集來解析響應(yīng)的body.如果不去描述清楚,可能瀏覽器展示的內(nèi)容就會亂碼.
②void addHeader(String name, String value)方法:
使用addHeader,header中可能出現(xiàn),key相同的兩個鍵值對.
一般來說,約定鍵值對中的key是唯一的,但實踐中,有些情況,確實也會需要key不唯一.
③void sendRedirect(String location)方法:
這個是特殊的方法,用來設(shè)置"重定向"響應(yīng).
4.3.2 示例一:設(shè)置狀態(tài)碼
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.setStatus(200);
//resp.sendError(404);
}
}
?
其實可以在返回狀態(tài)碼的同時,給body寫入數(shù)據(jù),就可以得到一些"個性化的錯誤頁面".
resp.sendError(404):
4.3.3 示例二:重定向
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.setStatus(302);
//重定向響應(yīng),一定腰帶有Location屬性,
//resp.setHeader("Location","http://www.sogou.com");
resp.sendRedirect("http://www.sogou.com");
}
}
?
4.3.4 示例三:自動刷新
可以使用setHeader設(shè)置任意的響應(yīng)報頭.
通過refresh屬性,設(shè)置瀏覽器自動刷新.
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("/refresh")
public class RefreshServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("refresh","2");
//返回系統(tǒng)時間,方便再次觀察
resp.getWriter().write("time: "+ System.currentTimeMillis());
}
}
?
設(shè)置這個屬性之后,瀏覽器就會每隔兩秒自動刷新一次!!!
但這里的刷新的間隔也不是精準(zhǔn)的2000ms,會比2000稍微多點.
必將,瀏覽器發(fā)起請求,服務(wù)器響應(yīng),知道頁面被解析出來,都是需要消耗一定的時間的.
4.3.5 示例四:編碼方式匹配
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("/body")
public class BodyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//讓服務(wù)器返回一個html數(shù)據(jù)
resp.getWriter().write("
}
}
這是怎么回事?
瀏覽器,默認會跟隨系統(tǒng)的編碼.
windows簡體中文版,默認的編碼是gbk.
一般在IDEA里面直接寫一個中文字符串,就是utf8的編碼.
拿著utf8的數(shù)據(jù),瀏覽器按照gbk的方式來解析,勢必就會出現(xià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("/body")
public class BodyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//設(shè)置響應(yīng)的字符集
resp.setContentType("text/html;charset=utf8");
//讓服務(wù)器返回一個html數(shù)據(jù)
resp.getWriter().write("
}
}
字符集,其實是ContentType的一部分.
這里要注意,給resp設(shè)置屬性的時候,必須要注意順序!!
先設(shè)置header,后設(shè)置body.
一旦開始設(shè)置body,就相當(dāng)于header和status都定型了,已經(jīng)來不及修改了.
?
柚子快報邀請碼778899分享:java Servlet
文章鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。