當前位置:編程學習大全網 - 源碼下載 - 如何解決JavaWeb亂碼問題

如何解決JavaWeb亂碼問題

request-line中的URL部分必須以application/x-www-form-urlencoded方式編碼。編碼時使用的字符集是當前網頁在瀏覽器上顯示時所使用的字符集。

JDK中專門有兩個類處理application/x-www-form-urlencoded類型的數據,它們是URLEncoder及URLDecoder。當網頁上的數據需要手動進行URLEncoding處理時,可使用URLEncoder類完成編碼工作。需要手動進行URLEncoding處理的位置包括:

鏈接(<a></a>)中的href標簽屬性;

以POST方式提交的表單(<form></form>)中的action標簽屬性。

例如,網頁上不應該產生這樣的鏈接:

[xhtml]?view plain?copy

<!--?不正確的寫法?-->?

<a?href="/hello/checkUser.html?opt=中文>使用者身份驗證"</a>?

正確的寫法是:

[xhtml]?view plain?copy

<!--?使用UTF-8字符集進行URLEncoding的結果?-->?

<a?href="/hello/checkUser.html?opt=%E4%B8%AD%E6%96%87">使用者身份驗證</a>?

為此,方案之壹可以在JSP網頁上使用腳本化語言進行URLEncoding處理。如:

[xhtml]?view plain?copy

<%@page?import="java.net.URLEncoder"%>?

<a?href="/hello/checkUser.html?opt=<%=URLEncoder.encode("中文",?"UTF-8")%>">使用者身份驗證</a>?

request-body的編碼處理

request-body只有在POST提交的方式下才會產生。request-body的編碼方式由表單的enctype標簽屬性指定,同request-line壹樣,編碼request-body時使用的字符集也是當前網頁在瀏覽器上顯示時所使用的字符集。request-body的編碼過程由客戶端瀏覽器自動完成,不需要額外的編程處理。

服務器的處理

相對於用戶端,服務器端在接收到HTTP請求時提供了兩種處理請求數據的方式:自動處理與不處理。

服務器壹般會自動處理application/x-www-form-urlencoded類型的數據(包括request-line及request-body中的數據),就servlet(Servlet類或JSP網頁)而言,可以通過request對象的getParameter()或getParameterValues()取得這些數據。對於除此以外的其它MIME類型的數據,HTTP服務器則是將處理的過程直接交到了與HTTP請求相對應的servlet(Servlet類或JSP網頁)身上。

例如用戶端有以下表單被提交:

[xhtml]?view plain?copy

<form?action="checkUser.html?opt=xxx"?method="POST">

<input?type="text"?name="username"?value="yyy"/>

<input?type="text"?name="username"?value="zzz"/>

<inupt?type="submit"?value="submit"/>

</form>?

表單提交時經服務器端自動處理後與checkUser.html相對應的servlet(Servlet類或JSP網頁)可以通過下面的方式取得數據:

[java]?view plain?copy

String?opt?=?request.getParameter("opt");?

String[]?users?=?request.getParameterValues("username");?

默認情況下,服務器對於接收到的application/x-www-form-urlencoded類型數據進行字符集為ISO-8859-1的URLDecoding處理,經過處理之後的字符串內碼為ISO-8859-1。對於沒有附加任何設置的HTTP服務器而言,我們的servlet在取得數據之後必須進行相應的解碼處理,生成內碼為UTF-16(unicode)的字符串。

例如對於用戶端請求數據中以UTF-8字符集進行URLEncoding的數據,servlet需要進行如下方式的解碼:

[java]?view plain?copy

String?opt?=?request.getParameter("opt");?

if?(opt!=null?&&?!"".equals(opt))?{?

opt?=?new?String(opt.getBytes("ISO-8859-1"),?"UTF-8");?

}?

為了避免這種額外的編碼/解碼處理,也就是說讓服務器了解到用戶端在URLEncoding時所使用的字符集,從而直接進行相應字符集的URLDecoding處理,不同的HTTP服務器提供了不同的解決方案。

以Tomcat為例,Tomcat自動解碼request-line的處理方式由Tomcat的配置文件server.xml指定。在server.xml中的Connector標簽中提供了URIEncoding標簽屬性,只要為其指定解碼用的字符集,Tomcat就會自動解碼request-line中經過application/x-www-form-urlencoded編碼處理的數據。例如:

<Connector connectionTimeout="40000" port="8080" protocol="HTTP/1.1"

URIEncoding="UTF-8" redirectPort="8443"/>

Tomcat自動解碼request-body的處理方式是設置request的characterEncoding值。如:

request.setCharacterEncoding("UTF-8");

但是這壹操作必須提前在filter中完成,在servlet中使用此方法已經不起作用了。filter的例子如下:

[java]?view plain?copy

import?java.io.IOException;?

import?javax.servlet.Filter;?

import?javax.servlet.FilterChain;?

import?javax.servlet.FilterConfig;?

import?javax.servlet.ServletException;?

import?javax.servlet.ServletRequest;?

import?javax.servlet.ServletResponse;?

public?class?CharacterEncodingFilter?implements?Filter?{?

private?String?encoding;?

public?CharacterEncodingFilter()?{?

encoding?=?null;?

}?

public?void?destroy()?{?

encoding?=?null;?

}?

public?void?doFilter(ServletRequest?request,?ServletResponse?response,?

FilterChain?chain)?throws?IOException,?ServletException?{?

request.setCharacterEncoding(encoding);?

chain.doFilter(request,?response);?

}?

public?void?init(FilterConfig?filterConfig)?throws?ServletException?{?

encoding?=?filterConfig.getInitParameter("encoding");?

if?(encoding?==?null?||?"".equals(encoding))?{?

encoding?=?"UTF-8";?

}?

}?

}?

我們可以在web.xml使用這個filter。web.xml的相應配置如下:

[xhtml]?view plain?copy

<filter>?

<filter-name>Character?Encoding?Filter</filter-name>?

<filter-class>?

CharacterEncodingFilter?

</filter-class>?

<init-param>?

<param-name>encoding</param-name>?

<param-value>UTF-8</param-value>?

</init-param>?

</filter>?

<filter-mapping>?

<filter-name>Character?Encoding?Filter</filter-name>?

<url-pattern>/*</url-pattern>?

</filter-mapping>?

通過上述兩種方式的預處理,在servlet中取出的數據可以不必進行ISO-8859-1解碼而直接使用。

字符集的選擇

在處理application/x-www-form-urlencoded類型的數據過程中,需要註意的另壹個問題是字符集的選擇問題。如上所述,不論是request-line還是request-body,其URLEncoding所使用的字符集都是當前網頁在瀏覽器上顯示時所使用的字符集。而這個信息又是HTTP服務器端生成HTML網頁時,在HTTP響應中提供的。

當HTTP服務器接收到壹個HTTP請求時,服務器總是需要向用戶端發送壹個HTTP響應。HTTP響應數據與HTTP請求數據格式相同,同樣由以下幾個部分組成:

<response-line>

<headers>

<CRLF>

[<response-body><CRLF>]

下面描述的是請求壹個HTML網頁數據時服務器的響應信息:

HTTP/1.1 200 OK

Server: Apache-Coyote/1.1

Content-Type: text/html;charset=UTF-8

Content-Length: 265

Date: Thu, 17 Dec 2009 05:20:36 GMT

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>test</title>

</head>

<body>

<h1>Hello World</h1>

</body>

</html>

[End]

其中headers的Content-Type指定了數據流的數據格式以及顯示用的字符集。這壹指標可以通過以下幾種方式指定:

1. HTML網頁

在HTML網頁的<head></head>中存在多個<meta/>標簽,其中可以設置Content-Type。例如:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

2. JSP網頁

JSP網頁中,除了<meta/>標簽之外,還需要在JSP網頁頭部設置如下代碼:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

3. Servlet類

如果要在Servlet類中通過response向用戶端傳送HTML數據,需要在傳送前指定Content-Type。代碼如下:

response.setContentType("text/html;charset=UTF-8");

通過上述三種方式,可以確保響應數據傳送到用戶端瀏覽器時,瀏覽器使用正確解碼方式和字符集顯示其內容。

結束語

總之,Content-Type是聯系用戶端與服務器端的紐帶,通過這壹指標,雙方得以對相關的數據進行正確的編碼與解碼。只要了解了Content-Type的作用以及使用方法,亂碼問題就會迎刃而解。

  • 上一篇:詳說股市護身符MACD
  • 下一篇:php怎麽抓取天氣預報?
  • copyright 2024編程學習大全網