1. 程式人生 > >Servlet學習筆記(一)

Servlet學習筆記(一)

對java web學習的記錄,有關的一些教學視訊和原始碼可以加qq 1269557707 諮詢,如果對本教程滿意的話給個贊,留個好評吧,歡迎轉載,但請註明出處!

目錄:

下面是正文:

-------------------------------------------------------------------------------------------------------------------------------

什麼是Servlet?

Servlet 並不難理解,其實就是一個java應用程式,但是它和普通的java程式不同,它是由開發者建立,但是是由Servlet容器(Tomcat)執行的,它不能自動執行。Servlet容器將使用者的請求傳給Servlet應用程式,並把Servlet應用程式的響應回傳給使用者

  • Servlet是JavaWeb三大元件之一(Servlet、Filter、Listener)
  • Servlet是用來處理客戶端請求的動態資源
  • Servlet的任務有:
    獲取請求資料處理請求完成響應
  • Servlet介面方法:
    void init(ServletConfig)void service(ServletRequest,ServletResponse)void destory()ServletConfig getServletConfig()String getServletInfo()

實現Servlet的方法

  • 實現Servlet介面(不方便)
  • 繼承GenericServlet類(不方便)
  • 繼承HttpServlet類(方便)

Servlet API

Servlet生命週期

Servlet介面一共5個方法,但其中只有三個是生命週期方法:
  • void init(ServletConfig)
  • void service(ServletRequest,ServletResponse)
  • void destory()
Servlet執行過程:1). 伺服器建立Servlet:
  • 當Servlet第一次被請求時,或伺服器啟動時,伺服器會建立Servlet例項。
  • 伺服器預設是在servlet第一次被請求時建立Servlet例項,如果希望伺服器啟動時就建立Servlet實現需要在web.xml中配置
  • 伺服器只為一個型別的Servlet建立一個例項物件,所以Servlet是單例的;
2). 伺服器初始化Servlet:
  • 當伺服器建立Servlet例項後會馬上呼叫Servlet的init(ServletConfig)方法,完成對Servlet的初始化;
  • init(ServletConfig)只會被呼叫一次
  • 伺服器會在呼叫init()方法時傳遞ServletConfig引數
3). 伺服器使用Servlet處理請求:
  • 當Servlet被請求時,伺服器會呼叫Servlet的service(ServletRequest,ServletResponse)方法
  • service(ServletRequest,ServletResponse)方法每處理一次請求,就會被呼叫一次,所以它可能會被呼叫N次
  • 因為Servlet是單例的,所以可能在同一時刻一個Servlet物件會被多個請求同時訪問,所以這可能出現執行緒案例問題
  • Servlet不是執行緒案例的,這有助與提高效率,但不能讓Servlet具有狀態,以免多個執行緒爭搶資料
4). 伺服器銷燬Servlet
  • 伺服器通常不會銷燬Servlet,通常只有在伺服器關閉時才會銷燬Servlet
  • 伺服器會在銷燬Servlet之前呼叫Servlet的destory()方法
  • 可以在destory()方法中給出釋放Servlet佔有的資源,但通常Servlet是沒什麼可要釋放的,所以該方法一般都是空的

ServletConfig

ServletConfig是Servlet中的init()方法的引數型別,伺服器會在呼叫init()方法時傳遞ServletConfig物件給init()方法。ServletConfig物件封裝了Servlet在web.xml中的配置資訊,它對應< servlet >元素。ServletConfig類的功能有:
  • String getServletName():獲取Servlet配置名,即< servlet-name >的值;
  • ServletContext getServletContext():獲取ServletContext物件,這個物件稍後介紹
  • String getInitParameter(String name):獲取初始化引數
  • Enumeration getInitParameterNames():獲取所有初始化引數的名稱
在web.xml檔案中,配置< servlet >時可以為配置0~N個初始化引數,例如:<servlet><servlet-name>xxx</servlet-name><servlet-class>cn.itcast.servlet.MyServlet</servlet-class><init-param><param-name>p1</param-name><param-value>v1</param-value></init-param><init-param><param-name>p2</param-name><param-value>v2</param-value></init-param></servlet>

GenericServlet

GenericServlet是Servlet介面的實現類,但它是一個抽象類,它唯一的抽象方法就是service()方法GenericServlet實現了Servlet介面:
  • 實現了String getServletInfo()方法
  • 實現了void destory()方法,空實現
  • 實現了void init(ServletConfig)方法,用來儲存ServletConfig引數
  • 實現了ServletConfig getServletConfig()方法
GenericServlet實現了ServletConfig介面:
  • 實現了ServletContext getServletContext()方法
  • 實現了String getInitParameter()方法
  • 實現了String getServletName()方法
  • 實現了Enumeration getInitParameterNames()方法
GenericServlet添加了init()方法:
  • 該方法會被init(ServletConfig)方法呼叫
  • 如果希望對Servlet進行初始化,那麼應該覆蓋init()方法,而不是init(ServletConfig)方法

HttpServlet

HttpServlet是GenericServlet的子類,它專注HTTP請求HttpServlet類的方法:
  • 實現了void service(ServletRequest,ServletResponse)方法,實現內容是:
    • 把ServletRequest強轉成HttpServletRequest
    • 把ServletResponse強轉成HttpServletResponse
    • 呼叫本類新增的void service(HttpServletRequest,HttpServletResponse)方法
  • 添加了void service(HttpServletRequest,HttpServletResponse)方法,內容是:
    • 呼叫request的getMethod()獲取請求方式
    • 如果請求方式為GET,那麼呼叫本類新增的doGet(HttpServletRequest,HttpServletResponse)方法
    • 如果請求方式為POST,那麼呼叫本類新增的doPost(HttpServletRequest,HttpServletResponse)方法
  • 添加了doGet(HttpServletRequest,HttpServletResponse)方法,內容是響應405,表示錯誤,所以我們應該去覆蓋這個方法
  • 添加了doPost(HttpServletRequest,HttpServletResponse)方法,內容是響應405,表示錯誤,所以我們應用去覆蓋這個方法
 如果是通過繼承HttpServlet類來自定義Sevlet的話,那麼:
  • 不要去覆蓋void service(ServletRequest,ServletResponse)
  • 不要去覆蓋void service(HttpServletRequest, HttpServletResponse)
  • 而應該去覆蓋doGet()或doPost()方法。

< url-pattern >

< url-pattern >是的子元素,用來繫結Servlet的訪問路徑可以在一箇中給出多個< url-pattern >,也就是說一個Servlet可以有多個訪問路徑:<servlet-mapping><servlet-name>xxx</servlet-name><url-pattern>/helo1<url-pattern><url-pattern>/hello2<url-pattern></servlet-mapping>還可以在中使用萬用字元,即“*”。
  • < url-pattern > /* < url-pattern >:表示匹配任何路徑
  • < url-pattern >/do/*< url-pattern >:表示匹配以/do開頭的任何路徑
  • < url-pattern >*.do< url-pattern >:表示匹配任何以“.do”結尾的路徑
注意:
  • 萬用字元要麼在開頭,要麼在結尾,不能在中間,例如:/*.do就是錯誤的使用。
  • 如果不使用萬用字元,那麼< url-pattern >必須以“/”開頭,例如:< url-pattern >abc< /url-pattern >就是錯誤的

ServletContext

ServletContext是Servlet三大域物件之一ServletContext在伺服器啟動時建立,在伺服器關閉時銷燬,一個JavaWeb應用只建立一個ServletContext物件它的功能分類:
  • 存取資料
  • 讀取web.xml中的應用初始化引數
  • 讀取應用資源
  1. 獲取ServletContext物件
    在HttpServlet中可以通過以下方法來獲取ServletContext物件
  • ServletContext sc = this.getServletContext()
  • ServletContext sc = this.getServletConfig().getServletContext()
  1. 存取資料
    因為在一個JavaWeb應用中,只有一個ServletContext物件,所以在ServletContext中儲存的資料可以共整個JavaWeb應用中的動態資源共享
    ServletContext是Servlet三大域物件之一,域物件內部有一個Map,用來儲存資料
  • void setAttribute(String name, Object value):用來新增或替換ServletContext域資料
    servletContext.setAttribute("xxx", "XXX"),新增域資料servletContext.setAttribute("xxx", "XXXX"),覆蓋域資料,因為在域中已經存在了名為xxx的資料,所以這次就是覆蓋了
  • Object getAttribute(String name):通過名稱來獲取域資料
  • void removeAttribute(String name):通過名稱移除域資料
  • Enumeration getAttributeNames():獲取所有ServletContext域資料的名稱
注:Web資源
  • 靜態資源:html、css、javascript、圖片等;
  • 動態資源:javaweb的動態資源有jsp/servlet,其他web程式動態資源有asp、php等。
  1. 讀取web.xml中配置的應用初始化引數
<context-param><param-name>p1</param-name><param-value>v1</param-value> </context-param><context-param><param-name>p2</param-name><param-value>v2</param-value> </context-param>
  • servletContext.getInitParameter("p1"),返回v1
  • servletContext.getInitParameter("p2"),返回v2
  • servletContext.getInitParameterNames(),返回Enumeration,包含p1和p2
  1. 獲取專案資源
  • String getRealPath(String path):獲取資源的真實名稱
    String path = servletContext.getRealPath("/WEB-INF/a.jpg");
    返回值為/WEB-INF/a.jpg真實路徑,即磁碟路徑:C:/tomcat6/wabapps/hello/WEB-INF/a.jpg
  • InputStream getResourceAsStream(String path):獲取資源的輸入流
    InputStream in = servletContext.getResourceAsStream("/WEB-INF/a.jpg");
    返回的是a.jpg的輸入流物件,可以從流中得到a.jpg的資料
  • Set getResourcePaths(String path):獲取指定目錄下的所有資源路徑
    Set paths = servletContext.getResourcePaths("/WEB-INF");
    返回的Set中包含如下字串:

    /WEB-INF/lib//WEB-INF/classes//WEB-INF/web.xml/WEB-INF/a.jpg
  1. 獲取類路徑資源
可以通過Class類的物件來獲取類路徑下的資源,對應JavaWeb應用的類路徑就是classes目錄下的資源例如:InputStream in = cn.itcast.servlet.MyServlet.class.getResourceAsStream("a.jpg");獲取的是:/WEB-INF/classes/cn/itcast/servlet/a.jpg,即與MyServlet.class同目錄下的資源例如:InputStream in = cn.itcast.servlet.MyServlet.class.getResourceAsStream("/a.jpg");獲取的是:/WEB-INF/classes/a.jpg,即類路徑的根目錄下的資源,類路徑的根目錄就是/classes目錄

request和response

  • 當伺服器接收到請求後,伺服器會建立request和response物件,把請求資料封裝到request物件中;
  • 然後呼叫Servlet的service()方法時把這兩個物件傳遞給service()方法;
  • 在service()方法中可以通過request物件獲取請求資料,可以使用response物件向客戶端完成響應;
  • 每次請求伺服器都會建立新的request和response物件,即每個請求有自己獨自的request和response物件

HttpServletRequest

HttpServletRequest表示HTTP環境中的Servlet請求常用方法:
  • Cookie[] getCookies() 返回一個Cookie陣列
  • java.lang.String getContextPath() 返回表示請求Context的URI部分
  • java.lang.String getHeader(java.lang.String name) 返回指定的HTTP請求頭
  • HttpSession getSession() 返回與這個請求有關的session物件,如果沒有就新建一個
request功能介紹
  • 獲取請求頭
  • 獲取請求引數
  • Servlet三大域物件之一
  • 請求包含和請求轉發

1.request域方法

  • void setAttribute(String name, Object value):新增或替換request域屬性
  • Object getAttribute(String name):獲取request域指定名稱的域屬性
  • void removeAttribute(String name):移除request域指定名稱的域屬性
  • Enumeration getAttributeNames():獲取所有request域的屬性名稱

2. request獲取請求頭

  • String getHeader(String name):獲取指定名稱的請求頭
  • int getIntHeader(String name):獲取指定名稱的請求頭,把值轉換成int型別。
  • Enumeration getHeaderNames():獲取所有請求頭名稱

3.request請求資料相關其他方法

重點:
  • String getMethod():獲取請求方式
  • String getContextPath():獲取上下文路徑,即“/” + 應用名稱,例如:/day05_1
  • void setCharacterEncoding(String):設定請求體的編碼
  • String getRemoteAddr():獲取客戶端IP地址
非重點:
  • int getContentLength():獲取請求體位元組數
  • Locale getLocale():獲取請求Locale,例如zh_CN表示中文,中國
  • String getCharacterEncoding():獲取請求體編碼,在沒有呼叫setCharacterEncoding()之前該方法返回null
  • String getQueryString():獲取引數列表,例如:username=zhangSan&password=123
  • String getRequestURI():返回請求URI路徑,從應用名稱開始,到引數之前這一段,例如:/day05_1/AServlet
  • StringBuffer getRequestURL():整個請求URL,不包含引數部分
  • String getServletPath():返回Servlet路徑,從應用名稱後開始,到引數之前這一段,不包含應用名稱。
  • String getServerName():返回主機名,例如:localhost
  • int getServerPort():返回伺服器埠號,例如:8080

4. 請求引數

獲取請求引數,即獲取超連結上的引數和表單中的引數
  • String getParameter(String name):獲取指定名稱的引數,如果存在同名引數,那麼該方法只獲取第一個引數值
  • String[] getParameterValues(String name):獲取指定名稱的引數,因為同名引數的存在,所以返回值為String[]
  • Enumeration getParameterNames():獲取所有引數名稱
  • Map getParameterMap():獲取所有引數,封裝到Map中,key為引數名稱,value為引數值。

5. 請求包含和請求轉發

有時一個請求需要多個Servlet協作才能完成,所以需要在一個Servlet跳到另一個Servlet!
  • 請求包含和請求轉發都是在一個請求中,訪問兩個Servlet
  • 請求包含和請求轉發都是有一個Servlet去呼叫執行另一個Servlet
  • 請求包含和請求轉發都可以共享request中的資料,因為都是一個請求。

轉發和包含總結:
一個請求跨多個Servlet,需要使用轉發和包含。請求轉發:由下一個Servlet完成響應體!當前Servlet可以設定響應頭!(留頭不留體)請求包含:由兩個Servlet共同未完成響應體!(都留)無論是請求轉發還是請求包含,都在一個請求範圍內!使用同一個request和response!
eg:
  • 從AServlet請求轉發到BServlet
    在AServlet中可以設定響應頭在AServlet中不能使用響應流輸出
如果在AServlet中執行了響應操作,那麼有兩種可能:
  • 如果在AServlet中響應的資料導致response提交,那麼在轉發時丟擲異常;
  • 如果在AServlet中響應的資料沒有導致response提交,那麼response中的資料會被清空。
  • 從AServlet請求包含BServlet
    在AServlet可以設定響應頭在AServlet可以使用響應流輸出
  • 請求轉發和請求包含都要使用RequestDispatcher物件:RequestDispatcher rd = request.getRequestDispatcher("/BServlet");使用request獲取RequestDispatcher物件,方法的引數是被轉發或被包含的Servlet路徑
  • 請求轉發執行RequestDispatcher的forward()方法:rd.forward(request,response);
  • 請求包含執行RequestDispatcher的include()方法:rd.include(request,response);
  • 請求轉發和請求包含的路徑都是伺服器端路徑,相對當前應用

6. 請求轉發與重定向


重定向
1)請求轉發是一個請求一次響應,而重定向是兩次請求兩次響應2)請求轉發位址列不變化,而重定向會顯示後一個請求的地址3)請求轉發只能轉發到本專案其他Servlet,而重定向不只能重定向到本專案的其他Servlet,還能定向到其他專案4)請求轉發是伺服器端行為,只需給出轉發的Servlet路徑,而重定向需要給出requestURI,即包含專案名!5)請求轉發和重定向效率是轉發高!因為是一個請求!
如何選擇?   需要位址列發生變化,那麼必須使用重定向!   需要在下一個Servlet中獲取request域中的資料,必須要使用轉發!

7.request域

Servlet中三大域物件:request、session、application,都有如下三個方法:
1)void setAttribute(String name, Object value)2)Object getAttribute(String name)3)void removeAttribute(String name);
同一請求範圍內使用request.setAttribute()、request.getAttribute()來傳值!前一個Servlet呼叫setAttribute()儲存值,後一個Servlet呼叫getAttribute()獲取值。

9.請求引數和request域的不同( request.getParameter()和request.getAttribute())


請求引數和request域
  • getParameter()是獲取客戶端引數,它是從客戶端傳遞給伺服器的資料。
  • getAttribute()是獲取伺服器端自己設定的資料,而不是客戶端的資料。
  • request沒有setParameter()方法,不能自己設定引數,引數都由客戶端傳遞
  • request有setAttribute()方法,在getAttribute()之前,需要先setAttribute()才能獲取到。
  • getAttribute()和setAttribute()是用來在請求轉發和請求包含中的多個Servlet中共享資料。

HttpServletResponse

response是響應物件,用來在Servlet的service()方法中向客戶端響應資料常用方法:
  • void addCookie(Cookie cookie) 為響應物件新增Cookie
  • void addHeader(java.lang.String name, java.lang.String value) 為響應物件新增標頭
  • void sendRedirect(java.lang.String location) 傳送響應代號,把瀏覽器重定向到指定位置
response的功能如下:
  • 設定響應頭
  • 傳送狀態碼
  • 設定響應正文
  • 重定向

1.響應正文

  • ServletOutputStream getOutputStream():用來向客戶端響應位元組資料;
  • PrintWriter getWriter():用來向客戶端響應字元資料;
response.getWriter().print("你好");//向客戶端響應字元資料byte[] bytes = ...;response.getOutputStream().write(bytes);//向客戶端響應位元組資料

2.response字元編碼

  • Tomcat響應資料預設使用ISO-8859-1
  • 通常瀏覽器預設使用GBK編碼
  • response.setCharacterEncoding("utf-8"); / /設定response.getWriter()的字元編碼
response.getWriter().print("大家好");因為Tomcat預設使用的是ISO-8859-1編碼,不支援中文。所以一定編碼!response.setCharacterEncoding("utf-8");response.getWriter().print("大家好");因為已經設定了字元流編碼為utf-8,所以響應給客戶端的資料為utf-8編碼!但因為瀏覽器預設使用的是gbk來解析響應資料,所以亂碼!如果瀏覽器使用utf-8編碼,那麼就不會亂碼了。response.setCharacterEncoding("gbk");response.getWriter().print("大家好");因為設定了字元流編碼為gbk,所以響應給客戶端的資料為gbk編碼!因為瀏覽器預設使用gbk來解析資料,所以不會出現亂碼!如果瀏覽器使用utf-8編碼,那麼就會出現亂碼!4)response.setContentType("text/html;charset=utf-8");response.getWriter().print("大家好");setContentType()方法有兩個作用:
  • 設定字元流編碼。等同與呼叫了response.setCharacterEncoding("utf-8");
  • 設定Content-type響應頭,即通知瀏覽器響應資料的編碼為utf-8。
    因為設定字元流的編碼為utf-8,所以響應給客戶端資料為utf-8編碼
    因為設定了Content-type頭為utf-8,所以瀏覽器會使用utf-8來解析響應資料
    沒有亂碼!
response.setContentType("text/html;charset=gbk");response.getWriter().print("大家好");
  • 設定了字元流為gbk,所以響應給客戶端的資料為gbk
  • 設定了Content-type頭為gbk,所以通知瀏覽器響應資料為gbk編碼
    沒有亂碼!
response.setHeader("Content-type", "text/html;charset=utf-8")等同於repsonse.setContentType("text/html;charset=utf-8")response.getOutputStream().write("大家好".getBytes("gbk"));響應的資料是gbk編碼客戶端瀏覽器預設使用gbk編碼所以沒有亂碼

3. response字元流緩衝區

response字元流緩衝區大小為8KB,當向字元流中寫入資料後,資料可能只在緩衝區中,而沒有傳送到瀏覽器。可以呼叫response.flushBuffer()或response.getWriter().flush()方法重新整理緩衝區,把資料傳送到瀏覽器。

4.設定響應頭

response.setHeader("Content-type", "text/html;charset=utf-8");等同與response.setContentType("text/html;charset=utf-8");response.setHeader("Refresh", "5; URL=http://www.itcast.cn");

5.指定狀態碼

response.setStatus(200):設定狀態碼為200response.sendError(404, “您要查詢的資源不存在”):設定狀態碼為404repsonse.sendError(500, “伺服器出氏了”):設定狀態碼為500在呼叫sendError()方法時,不只是設定了狀態碼,而且還會給瀏覽器一個顯示錯誤的頁面。

6.重定向


重定向response.sendStatus(302);repsonse.setHeader("Location", "http://www.baidu.com");快捷的方法重定向:
  • 重定向是兩次請求
  • 重定向不侷限與當前應用,也可以是其他應用,例如重定向到百度
  • 重定向響應碼為302,而且必須有Location響應頭
  • 重定向與response響應流同時使用。

路徑

客戶端路徑和伺服器路徑

  1. 客戶端路徑和伺服器端路徑
  • 客戶端路徑需要給出應用名稱,例如:/day05_1/AServlet
  • 伺服器端路徑無需給出應用名稱,例如:/AServlet
  1. 客戶端路徑
    1). 頁面中都是客戶端路徑:
  • 超連結的href
  • 表單的action
  • 的src
    2). 重定向也是客戶端路徑:response.sendRedirect("/day05_1/BServlet");
  1. 伺服器端路徑
  • 請求轉發和請求包含
  • ServletContext獲取資源等

對以上的解釋(有點廢話)

  • web.xml中路徑,(叫它Servlet路徑!)
要麼以“ * ”開關,要麼為“ / ”開頭
  • 轉發和包含路徑
以“/”開頭:相對當前專案路徑,例如:http://localhost:8080/專案名/ request.getRequestdispacher("BServlet").for...();不以“/”開頭:相對當前Servlet路徑。 request.getRequestdispacher("/BServlet").for...();,假如當前Servlet是:http://localhost:8080/專案名/servlet/AServlet, 就是http://localhost:8080/專案名/servlet/BServlet
  • 重定向路徑(客戶端路徑)
     > 以“ / ”開頭:相對當前主機,例如:http: //localhost:8080/, 所以需要自己手動新增專案名,例如;response.sendRedirect(" /day10_1/Bservlet");
  • 頁面中超連結和表單路徑
     > 與重定向相同,都是客戶端路徑!需要新增專案名
    < form action="/day10_1/AServlet">< a href="/day10_/AServlet">< a href="AServlet" > ,如果不以“/”開頭,那麼相對當前頁面所在路徑。如果是http://localhost:8080/day10_1/html/form.html。 即:http://localhost:8080/day10_1/html/ASevlet建議使用以“/”開頭的路徑,即絕對路徑!  * ServletContext獲取資源路徑    > 相對當前專案目錄,即當然index.jsp所在目錄  * ClassLoader獲取資源路徑    > 相對classes目錄  * Class獲取資源路徑    > 以“/”開頭相對classes目錄    > 不以“/”開頭相對當前.class檔案所在目錄。

編碼

  常見字元編碼:iso-8859-1(不支援中文)、gb2312、gbk、gb18030(系統預設編碼,中國的國標碼)、utf-8(萬國碼,支援全世界的編碼,所以我們使用這個)

亂碼解決方案

一、瀏覽器和伺服器之間傳輸亂碼
  1. 請求編碼
  • 客戶端傳送的資料編碼:由瀏覽器來決定:
    1). 如果是在位址列中直接給出url,那麼一般都是預設為GBK,但這個可能不太大。
    2). 如果是通過頁面上的表單或超連結發出請求,那麼由當前頁面的編碼來決定傳送的引數的編碼。
  • 無論瀏覽器傳送過來的是什麼編碼的資料,Tomcat都預設使用ISO-8859-1來解碼
    1). POST:可以使用request.setCharacterEncoding()方法來設定請求體資料的編碼,因為POST請求引數在請求體中,所以是可以設定編碼的。在使用request.getParameter()方法獲取引數之前,先使用request.setCharacterEncoding("UTF-8")方法來設定編碼即可。
    2). GET:沒有方法可以設定它,因為引數在url中。所以使用request.getParameter()獲取到的資料一定是錯誤的使用了iso-8859-1解碼的。可以再使用iso-8859-1把字串轉回到byte[],再重新使用正確的編碼來解碼即可。
    String s = request.getParameter("s");//使用iso-8859-1錯誤的解碼了
    byte[] bytes = s.getBytes("iso-8859-1");//退回錯誤的解碼,讓字串通過iso-8859-1返回到位元組資料,即還原位元組資料
    s = new String(bytes, "utf-8");//重新使用正確的utf-8來解碼。
2.響應編碼在使用response.getWriter()之前可以使用setContentType("text/html;charset=utf-8)。或者response.setCharacterEncoding("UTF-8");
  1. 使用過濾器
二、檔案亂碼1、專案文字檔案預設編碼:【右擊專案】->【Properties】->【Resource】->【Text file encoding】2、檔案預設編碼:預設使用專案的預設編碼:【右擊檔案】->【Properties】->【Resource】->【Text file encoding】3、 JSP 檔案編碼:【右擊檔案】->【Properties】->【Resource】->【Text file encoding】4、JSP翻譯為Servlet時的編碼:< %@ page language="java" pageEncoding="utf-8"% >

亂碼詳解(有點廢話)

  1. 響應編碼

      * 當使用response.getWriter()來向客戶端傳送字元資料時,如果在之前沒有設定編碼,那麼預設使用iso,因為iso不支援中文,一定亂碼
      * 在使用response.getWriter()之前可以使用response.setCharaceterEncoding()來設定字元流的編碼為gbk或utf-8,當然我們通常會選擇utf-8。這樣使用response.getWriter()傳送的字元就是使用utf-8編碼的。但還是會出現亂碼!因為瀏覽器並不知道伺服器傳送過來的是什麼編碼的資料!這時瀏覽器會使用gbk來解碼,所以亂碼!
      * 在使用response.getWriter()之前可以使用response.setHeader("Content-type","text/html;charset=utf-8")來設定響應頭,通知瀏覽器伺服器這邊使用的是utf-8編碼,而且在呼叫setHeader()後,還會自動執行setCharacterEncding()方法。這樣瀏覽器會使用utf-8解碼,所以就不會亂碼了!
      * setHeader("Content-Type", "text/html;charset=utf-8")的快捷方法是:setContentType("text/html;charset=utf-8)。
  2. 請求編碼
      * 客戶端傳送給伺服器的請求引數是什麼編碼:
        客戶端首先要開啟一個頁面,然後在頁面中提交表單或點選超連結!在請求這個頁面時,伺服器響應的編碼是什麼,那麼客戶端傳送請求時的編碼就是什麼。
      * 伺服器端預設使用什麼編碼來解碼引數:
        伺服器端預設使用ISO-8859-1來解碼!所以這一定會出現亂碼的!因為iso不支援中文!
      * 請求編碼處理分為兩種:GET和POST:GET請求引數不在請求體中,而POST請求引數在請求體中,所以它們的處理方式是不同的!
      * GET請求編碼處理:
      
        > String username = new String(request.getParameter("iso-8859-1"), "utf-8");
        > 在server.xml中配置URIEncoding=utf-8
      * POST請求編碼處理:
        > String username = new String(request.getParameter("iso-8859-1"), "utf-8");
        > 在獲取引數之前呼叫request.setCharacterEncoding("utf-8");
  3. URL編碼
      表單的型別:Content-Type: application/x-www-form-urlencoded,就是把中文轉換成%後面跟隨兩位的16進位制。
      為什麼要用它:在客戶端和伺服器之間傳遞中文時需要把它轉換成網路適合的方式。
  * 它不是字元編碼!  * 它是用來在客戶端與伺服器之間傳遞引數用的一種方式!  * URL編碼需要先指定一種字元編碼,把字串解碼後,得到byte[],然後把小於0的位元組+256,再轉換成16進位制。前面再新增一個%。  * POST請求預設就使用URL編碼!tomcat會自動使用URL解碼!  * URL編碼:String username = URLEncoder.encode(username, "utf-8");  * URL解碼:String username = URLDecoder.decode(username, "utf-8");  最後我們需要把連結中的中文引數,使用url來編碼!

補充:Get請求和Post請求

最為常見的客戶端傳遞引數方式有兩種:
  • 瀏覽器位址列直接輸入:一定是GET請求;
  • 超連結:一定是GET請求;
  • 表單:可以是GET,也可以是POST,這取決與的method屬性值;
GET請求和POST請求的區別:GET請求:
  • 請求引數會在瀏覽器的位址列中顯示,所以不安全;
  • 請求引數長度限制長度在1K之內;
  • GET請求沒有請求體,無法通過request.setCharacterEncoding()來設定引數的編碼;
    POST請求:
  • 請求引數不會顯示瀏覽器的位址列,相對安全;
  • 請求引數長度沒有限制;