エンコードとデコード
次の図を通して、Javawebのトランスコーディングがどこにあるかを理解できます。
ユーザーは、サーバーにHTTPリクエストを送信することを望んでいます。エンコーディングがURL、Cookie、およびパラメーターである場所が必要です。エンコード後、サーバーはHTTP要求を受け入れ、HTTP要求を解析し、URL、Cookie、およびパラメーターをデコードします。サーバーのビジネスロジック処理中に、ネットワーク内のデータベース、ローカルファイル、またはその他のファイルなどを読み取る必要がある場合があり、これらのプロセスではエンコードとデコードが必要です。処理が完了すると、サーバーはデータをエンコードしてクライアントに送信し、ブラウザはデコード後にユーザーに表示します。このプロセス全体に関与するエンコードとデコードが多くあり、文字化けする可能性が最も高い場所は、サーバーとクライアントと対話するプロセスです。
上記のプロセス全体を次のように要約できます。ページエンコードデータはサーバーに渡され、サーバーは取得したデータを解読し、いくつかのビジネスロジック処理の後、最終結果がエンコードおよび処理され、クライアントはそれをデコードしてユーザーに表示します。そのため、以下では、Javawebのエンコードとデコードの説明をお願いします。
クライアントがサーバーにリクエストを送信することを望む場合、4つの状況を渡します。
1。URLによる直接アクセス。
2。ページリンク。
3。フォームの提出を取得します
4。フォーム投稿の提出
URLメソッド:URLの場合、すべてのURLが英語の場合、問題はありません。中国人がいる場合、エンコーディングが関与します。エンコードする方法は?どのようなルールをエンコードしたいですか?では、それをデコードする方法は?答えは以下で1つずつ回答されます!まず、URLのコンポーネントを見てください。
このURLでは、ブラウザはパスとパラメーターをエンコードします。エンコーディングプロセスをよりよく説明するには、次のURLを使用します
http://127.0.0.1:8080/perbank/i am cm?name = i am cm
上記のアドレスをブラウザURL入力ボックスに入力します。 HTTPメッセージヘッダー情報を表示することにより、ブラウザがどのようにエンコードするかを確認できます。 3つのブラウザのエンコーディング条件は次のとおりです。
主要なブラウザによる「I Am」のエンコードは次のとおりです。
パス部分 | クエリ文字列 | |
Firefox | E6 88 91 E6 98 AF | E6 88 91 E6 98 AF |
クロム | E6 88 91 E6 98 AF | E6 88 91 E6 98 AF |
すなわち | E6 88 91 E6 98 AF | CE D2 CA C7 |
保護されたvoid converturi(messagebytes uri、request request)スロー例外{bytechunk bc = uri.getbytechunk(); int length = bc.getLength(); Charchunk cc = uri.getCharchunk(); cc.allocate(length、-1);文字列enc = connector.geturiencoding(); // URIデコードセットを取得しますif(enc!= null){b2cconverter conv = request.geturiconverter(); try {if(conv == null){conv = new b2cconverter(enc); request.seturiconverter(conv); }} catch(ioException e){...} if(conv!= null){try {conv.convert(bc、cc、cc.getbuffer()。length -cc.getend()); uri.setchars(cc.getbuffer()、cc.getstart()、cc.getlength());戻る; } catch(ioexception e){...}}} //デフォルトエンコード:高速変換byte [] bbuf = bc.getbuffer(); char [] cbuf = cc.getbuffer(); int start = bc.getStart(); for(int i = 0; i <length; i ++){cbuf [i] =(char)(bbuf [i+start]&0xff); } uri.setchars(cbuf、0、length); }上記のコードから、URIのデコード操作は、server.xmlで構成されているコネクタのデコードセットを最初に取得することであることがわかります。
<コネクタuriencoding = "utf-8" />
定義されていない場合、ISO-8859-1のデフォルトエンコードが解析に使用されます。
クエリ文字列パーツの場合、getまたはpostを介して送信するかどうかにかかわらず、すべてのパラメーターがパラメーターに保存され、request.getParameterを使用して、getParameterメソッドが初めて呼ばれるとデコード作業が実行されます。 getParameterメソッド内では、org.apache.catalina.connector.requestのParseParametersメソッドを呼び出します。次のコードは、ParseParametersメソッドの一部にすぎません。
//エンコード文字列enc = getCharacterenCoding()を取得します。 // contentTypeで定義されているcharset booleanを取得しますbodyencodingforuri = connector.getuseBodyEncodingforuri(); if(enc!= null){//エンコードが空でない場合、エンコードをenc parameters.setencoding(enc)に設定します。 if(usebodyencodingforuri){//チャートセットが設定されている場合、QueryStringのデコードをパラメーターにチャートセットに設定します。 }} else {//デフォルトのデコードメソッドパラメーターを設定します。setencoding(org.apache.coyote.constants.default_character_encoding); if(usebodyencodingforuri){parameters.setquerystringencoding(org.apache.coyote.constants.default_character_encoding); }}上記のコードから、クエリ文字列のデコード形式が設定されたチャートセットを使用するか、デフォルトのデコード形式ISO-8859-1を使用していることがわかります。この設定のチャートセットは、HTTPヘッダーで定義されているコンテンツタイプであることに注意してください。同時に、指定された属性を変更して有効にする必要がある場合は、以下を構成する必要があります。
<connector uriencoding = "utf-8" usebodyencodingforui = "true"/>
上記のパートでは、URL要求のエンコードおよびデコードプロセスを詳細に紹介します。実際、私たちにとって、私たちのより多くの方法は、形で提出することです。
form get
URLを介してデータを送信することは、文字化けされたコードの問題を引き起こすのが簡単であるため、フォームフォームを使用する傾向があることがわかっています。ユーザーが[フォームを送信]をクリックすると、ブラウザはより多くのコードを設定してデータをサーバーに渡します。 GETを通じて送信されたデータは、URLの後にスプライスされます(クエリ文字列??)と見なされるため、UriencodingはTomcatサーバーのデコードプロセスで役割を果たします。 Tomcatサーバーは、セットUriencodingに従ってデコードし、設定されていない場合は、デフォルトのISO-8859-1を使用してデコードします。ページ上のUTF-8にエンコードを設定し、Uriencodingが設定されていない、または設定されていない場合、サーバーがデコードすると、細いコードが発生します。この時点で、通常、新しい文字列(request.getParameter( "name")。getBytes( "ISO-8859-1")、 "utf-8")の形式で正しいデータを取得できます。
フォームポスト
POSTメソッドの場合、使用するエンコードはページ、つまりcontentTypeによっても決定されます。ページ上の[送信]ボタンをクリックしてフォームを送信すると、ブラウザは最初にOntentTypeのCharSetエンコード形式に従ってPOSTフォームのパラメーターをエンコードし、サーバーに送信します。サーバー側では、ContentTypeの文字セットを使用してデコードします(ここのGETメソッドとは異なります)。これは、投稿フォームを介して提出されたパラメーターには一般に、文字化けの問題がないことを意味します。もちろん、自分自身をエンコードするキャラクターセットを設定できます:request.setcharacterencoding(charset)。
中国語の文字化けのURLの問題を解決します
主に、URLとフォームの2つの形式の提出を介してサーバーにリクエストを送信します。フォームフォームには一般に、文字化けの問題はありません。文字化けの問題は主にURLにあります。以前のブログの導入を通じて、URLによってサーバーにエンコードする要求を送信するプロセスが本当に混乱していることがわかります。異なるオペレーティングシステム、異なるブラウザ、およびさまざまなWeb文字セットが、まったく異なるエンコード結果につながります。プログラマーがすべての結果を考慮に入れたい場合、それほど怖くないのでしょうか?クライアントが1つのエンコード方法のみを使用してサーバーにリクエストを発行することを保証する方法はありますか?
持っている!ここでは、主に次の方法を提供します
JavaScript
JavaScriptエンコードを使用しても、ブラウザに介入する機会が与えられません。エンコード後、サーバーにリクエストを送信し、サーバーでデコードします。この方法を習得するときは、JavaScriptエンコードの3つの方法が必要です:Escape()、encodeuri()、およびencodeuricomponent()。
逃げる
指定された文字列は、SIOラテン文字セットを使用してエンコードされます。すべての非ASCII文字は、%xx形式の文字列としてエンコードされます。ここで、xxは文字セットの文字に対応する16進数を表します。たとえば、形式に対応するエンコーディングは%20です。対応するデコード方法はunescape()です。
実際、Escase()はURLエンコードに直接使用することはできません。その実際の機能は、キャラクターのUnicodeエンコード値を返すことです。たとえば、上記の「I Am CM」の結果は%U6211%U662FCMです。「I」の対応するエンコードは6211、「はい」のエンコードは662F、「CM」のエンコードはCMです。
Escape()は「+」でエンコードされていないことに注意してください。ただし、Webページがフォームを送信すると、スペースがある場合、 +文字に変換されることがわかります。サーバーがデータを処理すると、 +サインはスペースに処理されます。したがって、使用するときは注意してください。
ecodeuri
URL全体をエンコードすると、UTF-8形式を使用してエンコードされた文字列を出力します。ただし、Encodeuriは、次のようなASCIIエンコードを除いて、いくつかの特殊文字をエンコードしません。 @#$& *()=: /; ? + '。
ecodeuricomponent
URI文字列をUTF-8エンコード形式のエスケープフォーマット文字列に変換します。 encodeuriと比較して、ecodeuricomponentはより強力であり、encodeuri()でエンコードされていないシンボル(; /?: @&= + $、#)にエンコードされます。ただし、Encodeuricomponentは、URLのコンポーネントを個別にのみエンコードし、URL全体をエンコードするために使用されません。対応するデコード関数メソッドDecodeuricomponent。
もちろん、私たちは通常、Encodeuriパーティーを使用してエンコード操作を実行します。バックグラウンドで2回エンコードしてデコードするいわゆるJavaScriptは、この方法を使用することです。 JavaScriptには、この問題を解決するための2つのソリューションがあります。1つのトランスコーディングと2つのトランスコーディング方法です。
トランスコーディングが一度
JavaScriptトランスコード:
var url = '<s:Property value = "webpath" />/ showmoblieqrcode.servlet?name=i am cm'; window.location.href = encodeuri(url);
トランスコードURL:http://127.0.0.1:8080/perbank/showmoblieqrcode.servlet?name=%E6%88%91%E6%98%AFCM
バックエンド処理:
文字列名= request.getParameter( "name"); System.out.println( "前景着信パラメーター:" + name); name = new String(name.getBytes( "ISO-8859-1")、 "utf-8"); System.out.println( "デコードされたパラメーター:" + name);
出力結果:
フロントデスクの着信パラメーター:?????? CM
パラメーターを解読した後:私はCMです
二次トランスコーディング
JavaScript
var url = '<s:Property value = "webpath" />/ showmoblieqrcode.servlet?name=i am cm'; window.location.href = encodeuri(encodeuri(url));
トランスコードURL:http://127.0.0.1:8080/perbank/showmoblieqrcode.servlet?name=%25e6%2588%2591%25E6%2598%25AFCM
バックエンド処理:
文字列名= request.getParameter( "name"); System.out.println( "前景着信パラメーター:" + name); name = urldecoder.decode(name、 "utf-8"); System.out.println( "デコードされたパラメーター:" + name);
出力結果:
フロントエンドの着信パラメーター:E68891E698AFCM
パラメーターを解読した後:私はCMです
フィルター
フィルターを使用して、フィルターは2つのタイプを提供します。1つ目はエンコードを設定することであり、2つ目はフィルターでデコード操作を直接実行することです。
フィルター1
このフィルターは、リクエストのエンコード形式を直接設定します。
パブリッククラスのキャラクターエンコードはフィルター{private filterconfig config;文字列エンコード= null; public void Destroy(){config = null; } public void dofilter(servletRequest request、servletResponse応答、フィルターチェーンチェーン)IoException、servletexception {request.setcharacterencoding(encoding); Chain.dofilter(リクエスト、応答); } public void init(filterconfig config)servletexception {this.config = config; //構成パラメーターを取得するstring str = config.getInitParameter( "encoding"); if(str!= null){encoding = str; }}}構成:
<! - 中国のフィルター構成 - > <filter> <filter-name>中国人coding </filter-name> <filter-class> com.test.filter.characterencoding </filter-class> <init-param> <param-name>エンコーディング</param-name> <paramvalue> utf-8 </param-> </init-param> <フィルター> <フィルター> <フィルター> <フィルター> <filter-name>中国人coding </filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
フィルター2
処理方法では、フィルターはパラメーターを直接デコードし、デコードされたパラメーターを要求属性にリセットします。
パブリッククラスのキャラクターエンコードは、フィルター{Protected filterConfig filterconfig;文字列エンコード= null; public void Destroy(){this.filterconfig = null; } / ***初期化* / public void init(filterconfig filterconfig){this.filterconfig = filterconfig; } / *** utf -8のエンコーディングフォームにインストルを変換** @param string* @return utf -8のエンコードフォームstring* @throws unsupportedencodingexception* / private string toutf(string instr)throws unsupportedencodingexception {string outstr = ""; if(grouth!= null){outstr = new String(instr.getBytes( "iso-8859-1")、 "utf-8"); } return outstr; } / ***中国の文字盤フィルタリング処理* / public void dofilter(servletrequest servletrequest、servletResponse servletResponse、フィルターチェーンチェーン)IoException、servletexception {httpservletrequest request =(httpservletrequest)servletrequest; httpservletResponse応答=(httpservletResponse)servletResponse; //リクエスト(1.postまたは2.get)を取得する方法、および異なるリクエストメソッドString method = request.getMethod()に従って異なる処理が実行されます。 //1。postで送信されたリクエストについては、エンコードをutf-8に直接設定します(method.equalsignorecase( "post")){try {request.setcharacterencoding( "utf-8"); } catch(unsupportedencodingexception e){e.printstacktrace(); }} // 2。get else {//クライアント列挙<string> paramnames = request.getparameternames()によって送信されたパラメーターセットを取得するget else {// request request // [パラメーター設定]をトラバースして、各パラメーターの名前と値を取得します(paramnames.hasmoreelements()){string name = paramnames.nextelement(); //パラメーター名を取得する文字列値[] = request.getParametervalues(name); //パラメーター名に従ってその値を取り出します値[i] = vlustr; } catch(unsupportedencodingexception e){e.printstacktrace(); }} //リクエストリクエストリクエストの属性の形式で値を非表示。 }}} //応答方法を設定し、サポート漢字セットResponse.setContentType( "text/html; charset = utf-8"); //次のフィルターの実行を続けます。フィルターがない場合、リクエストは実行されます。dofilter(リクエスト、応答); }}構成:
<! - 中国のフィルター構成 - > <filter> <filter-name>中国人coding </filter-name> <filter-class> com.test.filter.characterencoding </filter-class> </filter> <filter-mapping> <filter-name>中国人</filter-name> <url-pattern>/*
他の
1. PageEncodingとContentTypeを設定します
<%@ページ言語= "java" contentType = "text/html; charset = utf-8" pageencoding = "utf-8"%>
2. TomcatのUriencodingをセットアップします
デフォルトでは、TomcatサーバーはISO-8859-1エンコード形式を使用して、Uriencodingパラメーターによって要求されたURLをエンコードするため、uriencoding = "utf-8"をtomcatのserver.xmlファイルの<connector>タグに追加する必要があります。