인코딩 및 디코딩
다음 그림을 통해 Javaweb에서 트랜스 코딩이 어디에 있는지 이해할 수 있습니다.
사용자는 서버가 HTTP 요청을 보내기를 원합니다. 인코딩이 URL, 쿠키 및 매개 변수 인 장소가 필요합니다. 인코딩 후 서버는 HTTP 요청을 수락하고 HTTP 요청을 구문 분석 한 다음 URL, 쿠키 및 매개 변수를 디코딩합니다. 서버의 비즈니스 로직 처리 중에 네트워크의 데이터베이스, 로컬 파일 또는 기타 파일 등을 읽어야하며 이러한 프로세스에는 인코딩 및 디코딩이 필요합니다. 처리가 완료된 후 서버는 데이터를 인코딩하여 클라이언트로 보냅니다. 브라우저는 디코딩 후 사용자에게 표시합니다. 이 전체 프로세스와 관련된 많은 인코딩 및 디코딩이 있으며, 가장 많이 나타날 가능성이 가장 높은 곳은 서버 및 클라이언트와 상호 작용하는 프로세스입니다.
위의 전체 프로세스는 다음과 같이 요약 될 수 있습니다. 페이지 인코딩 된 데이터는 서버로 전달되고 서버는 얻은 데이터를 디코딩하고 일부 비즈니스 로직 처리 후 최종 결과가 인코딩되고 처리되고 클라이언트가 디코딩되어 사용자에게 표시됩니다. 아래에서 나는 Javaweb의 인코딩 및 디코딩에 대한 설명을 요청할 것입니다.
클라이언트가 서버가 요청을 보내려면 4 가지 상황을 통과합니다.
1. URL에 의한 직접 액세스.
2. 페이지 링크.
3. 양식을 제출하십시오
4. 제출 후 양식
URL 방법 : URL의 경우 모든 URL이 영어로 된 경우 아무런 문제가 없습니다. 중국인이 있으면 인코딩이 관련됩니다. 인코딩하는 방법? 어떤 규칙을 인코딩하고 싶습니까? 그래서 어떻게 해독 하는가? 답은 아래에서 하나씩 답변 할 것입니다! 먼저 URL의 구성 요소를보십시오.
이 URL에서 브라우저는 경로와 매개 변수를 인코딩합니다. 인코딩 프로세스를 더 잘 설명하려면 다음 URL을 사용하십시오.
http://127.0.0.1:8080/perbank/i am cm? name = i am cm
위의 주소를 브라우저 URL 입력 상자에 입력하십시오. HTTP 메시지 헤더 정보를 보면 브라우저가 어떻게 인코딩하는지 확인할 수 있습니다. 3 개의 브라우저의 인코딩 조건은 다음과 같습니다.
주요 브라우저에서 "I AM"의 인코딩은 다음과 같습니다.
경로 부분 | 쿼리 문자열 | |
파이어 폭스 | 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, 요청 요청) 예외 {bytechunk bc = uri.getByTechunk (); int 길이 = bc.getLength (); charchunk cc = uri.getcharchunk (); cc. 합당 (길이, -1); 문자열 enc = connector.geturiencoding (); // if (enc! = null) {b2cconverter conc = request.geturiconverter (); try {if (conc == 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) {...}}} // 기본 인코딩 : 빠른 변환 바이트 [] bbuf = bc.getBuffer (); char [] cbuf = cc.getBuffer (); int start = bc.getstart (); for (int i = 0; i <길이; i ++) {cbuf [i] = (char) (bbuf [i+start] & 0xff); } uri.setchars (cbuf, 0, 길이); } 위의 코드에서 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 useBodyEncodingFori = connector.getUseBodyEncodingForuri ()에 정의 된 charset boolean을 가져옵니다. if (enc! = null) {// 인코딩이 비어 있지 않은 경우 인코딩을 ENC 매개 변수로 설정합니다. if (useBodyEncodingForuri) {// 차트가 설정된 경우 QueryString의 디코딩을 ChartSet 매개 변수로 설정합니다. }} else {// 기본 디코딩 메소드 매개 변수를 설정합니다. if (usebodyencodingforuri) {parameters.setQueryStringEncoding (org.apache.coyote.constants.default_character_encoding); }} 위의 코드에서 쿼리 문자열의 디코딩 형식이 세트 차트 세트를 사용하거나 기본 디코딩 형식 ISO-8859-1을 사용하는 것을 알 수 있습니다. 이 설정의 차트는 HTTP 헤더에 정의 된 내용 유형입니다. 동시에, 지정된 속성을 변경하여 발효 해야하는 경우 다음을 구성해야합니다.
<Connector uriencoding = "UTF-8"useBodyEncodingForuri = "true"/>
위의 부분은 URL 요청의 인코딩 및 디코딩 프로세스를 자세히 소개합니다. 사실, 우리에게 우리의 더 많은 방법은 양식으로 제출하는 것입니다.
양식을 얻으십시오
URL을 통해 데이터를 제출하는 데 쉽게 차량 코드 문제가 발생하므로 양식을 사용하는 경향이 있습니다. 사용자가 양식을 클릭하면 브라우저가 더 많은 코드를 설정하여 데이터를 서버로 전달합니다. GET를 통해 제출 된 데이터는 URL 이후 (쿼리 문자열로 간주 될 수 있습니까 ??), Uriencoding은 Tomcat 서버의 디코딩 프로세스에서 역할을 수행합니다. Set Uriencoding에 따라 Tomcat 서버가 디코딩되며 설정되지 않은 경우 기본 ISO-8859-1을 사용하여 디코딩합니다. 인코딩을 페이지에서 UTF-8로 설정하고 Uriencoding이 설정되지 않았거나 설정되지 않으면 서버가 디코딩 할 때 차량 코드가 발생합니다. 이 시점에서는 일반적으로 새 문자열 (request.getParameter ( "name"). getBytes ( "ISO-8859-1"), "UTF-8")를 통해 올바른 데이터를 얻을 수 있습니다.
양식 게시물
Post 메소드의 경우 사용하는 인코딩은 페이지, 즉 ContentType에 의해 결정됩니다. 페이지에서 제출 버튼을 클릭하여 양식을 제출하면 브라우저는 먼저 OntentType의 숯으로 인코딩 형식에 따라 게시물 양식의 매개 변수를 인코딩하여 서버에 제출합니다. 서버 측면에서는 ContentType의 세트 세트를 사용하여 디코딩합니다 (여기서 GET 메소드와 다릅니다). 이것은 포스트 양식을 통해 제출 된 매개 변수가 일반적으로 문제가 없음을 의미합니다. 물론, 우리는 자신을 인코딩하는 문자 세트를 설정할 수 있습니다 : request.setcharacterencoding (charset).
중국어로 된 URL의 문제를 해결하십시오
우리는 주로 두 가지 형식의 제출을 통해 서버에 요청을 보냅니다 : URL과 양식. 형태는 일반적으로 문제가 없으며, 차량 문제는 주로 URL에 있습니다. 이전 블로그의 소개를 통해 URL에 의해 서버로 인코딩하는 요청을 보내는 프로세스가 너무 혼란 스럽다는 것을 알고 있습니다. 다른 운영 체제, 다른 브라우저 및 다른 웹 문자 세트는 완전히 다른 인코딩 결과로 이어집니다. 프로그래머가 모든 결과를 고려하고 싶다면 너무 무섭지 않습니까? 클라이언트가 하나의 인코딩 메소드 만 사용하여 서버에 요청을 발행하도록하는 방법이 있습니까?
가지다! 여기서 나는 주로 다음 방법을 제공합니다
자바 스크립트
JavaScript 인코딩을 사용해도 브라우저에 개입 할 수있는 기회는 없습니다. 인코딩 후 요청을 서버로 보내고 서버에서 해독하십시오. 이 메소드를 마스터 할 때는 JavaScript 인코딩의 세 가지 메소드가 필요합니다 : Escape (), encodeuri () 및 encodeUricomponent ().
탈출하다
지정된 문자열은 SIO 라틴 문자 세트를 사용하여 인코딩됩니다. 모든 비 ASCII 문자는 %XX 형식으로 문자열로 인코딩되며, 여기서 XX는 문자 세트의 문자에 해당하는 16 진수를 나타냅니다. 예를 들어, 형식에 해당하는 인코딩은 %20입니다. 해당 디코딩 방법은 Unescape ()입니다.
실제로 Escape ()는 URL 인코딩에 직접 사용할 수 없으며 실제 기능은 문자의 유니 코드 인코딩 된 값을 반환하는 것입니다. 예를 들어, 위의 "I AM CM"의 결과는 %U6211 %U662FCM이며, "I"의 해당 인코딩은 6211이고 "예"의 인코딩은 662F이고 "CM"의 인코딩은 CM입니다.
Escape ()는 "+"로 인코딩되지 않습니다. 그러나 우리는 웹 페이지가 양식을 제출하면 공백이 있으면 + 문자로 변환됩니다. 서버가 데이터를 처리하면 + 부호가 공간으로 처리됩니다. 따라서 사용할 때주의하십시오.
Encodeuri
전체 URL을 인코딩하면 UTF-8 형식을 사용하여 인코딩 된 문자열을 출력합니다. 그러나 Encodeuri는 ASCII 인코딩을 제외한 일부 특수 문자를 인코딩하지 않습니다. @ # $ & * () = : /; ? + '.
encodeUricomponent
URI 문자열을 UTF-8 인코딩 형식으로 탈출 형식 문자열로 변환하십시오. Encodeuri와 비교하여 EncodeUricomponent는 더 강력하며 Encodeuri ()에서 인코딩되지 않은 기호 (; /? : @ & = + $, #)에 대해 인코딩됩니다. 그러나 EncodeUricomponent는 URL의 구성 요소 만 개별적으로 인코딩하며 전체 URL을 인코딩하는 데 사용되지 않습니다. 해당 디코드 함수 방법 디코드 아리코 어이 조합 요소입니다.
물론, 우리는 일반적으로 Encodeuri 파티를 사용하여 인코딩 작업을 수행합니다. 배경에서 두 번 소위 JavaScript 인코딩 및 디코딩은이 방법을 사용하는 것입니다. JavaScript 에서이 문제를 해결하기위한 두 가지 솔루션이 있습니다 : 하나의 트랜스 코딩 및 2 개의 트랜스 코딩 방법.
한 번 트랜스 코딩
JavaScript 트랜스 코딩 :
var url = '<s : 속성 값 = "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입니다
2 차 트랜스 코딩
자바 스크립트
var url = '<s : 속성 값 = "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 (이름, "utf-8"); System.out.println ( "디코딩 된 매개 변수 :" + name);
출력 결과 :
프론트 엔드 수신 매개 변수 : E68891E698AFCM
매개 변수를 디코딩 한 후 : 나는 CM입니다
필터
필터를 사용하여 필터는 두 가지 유형을 제공하며, 첫 번째는 인코딩을 설정하는 것이며, 두 번째는 필터에서 직접 디코딩 작업을 수행하는 것입니다.
필터 1
이 필터는 요청의 인코딩 형식을 직접 설정합니다.
공개 클래스 캐릭터 encoding 구현 필터 {private filterconfig config; 문자열 인코딩 = null; public void destrove () {config = null; } public void dofilter (ServletRequest 요청, ServletRepsonge 응답, 필터 체인 체인) IoException, ServleTeXception {request.SetchAracterEncoding (인코딩); Chain.dofilter (요청, 응답); } public void init (FilterConfig config) servleTeXception {this.config = config; // 구성 매개 변수 가져 오기 문자열 str = config.getInitParameter ( "Encoding"); if (str! = null) {encoding = str; }}} 구성:
<!-중국 필터 구성-> <filter> <filter-name> ChineseCoding </filter-name> <filter-class> com.test.filter.characterencoding </filter-class> <init-param> <param-name> encoding </param-name> <param-value> utf-8 </param-value> </init-param> </param> <filter-name> 중국어 코딩 </filter-name> <url-pattern>/*</url-pattern> </필터 매핑>
필터 2
처리 방법에서 필터는 매개 변수를 직접 디코딩 한 다음 디코딩 된 매개 변수를 요청 속성으로 재설정합니다.
공개 클래스 캐릭터 encoding 구현 필터 {Protected FilterConfig FilterConfig; 문자열 인코딩 = null; public void destrove () {this.filterconfig = null; } / *** 초기화* / public void init (FilterConfig FilterConfig) {this.filterConfig = FilterConfig; } / *** 기기를 UTF -8의 인코딩 형식으로 변환* @param instr String* @return utf -8의 인코딩 양식 문자열* @throws UnSupportedEncodingException* / private String toutf (String Inst)는 unsupportedEncodingException {String outstr = ""; if (inst! = null) {outstr = new String (instr.getBytes ( "iso-8859-1"), "utf-8"); } Outstr 리턴; } / *** 중국어 가블드 필터링 처리* / public void dofilter (ServletRequest ServletRequest, ServletResponse ServletResponse, FilterChain 체인)는 ioException, ServleTeXception {httpservletRequest request = (httpservletRequest) servletRequest; httpservletresponse 응답 = (httpservletResponse) servletResponse; // 요청을 얻는 메소드 (1.post 또는 2.get) 및 다른 요청 방법에 따라 다른 처리가 수행됩니다. String Method = request.getMethod (); // 1. POST에 제출 된 요청의 경우, 인코딩을 UTF-8 If (method.equalSignoreCase ( "post")) {try {request.SetchAracterEncoding ( "UTF-8"); } catch (UnsupportedEncodingException e) {e.printstacktrace (); }} // 2. get else에 제출 된 요청 {// 클라이언트 열거 <String> ParamNames = request.getParameterNames ()에 의해 제출 된 매개 변수 세트를 꺼냅니다. // 각 매개 변수의 이름과 값을 얻기 위해 설정된 매개 변수를 통과합니다 (paramnames.hasmoreElements ()) {String name = paramnames.nextElement (); // 매개 변수 이름 문자열 값 [] = request.getParametErvalues (name); // 매개 변수 이름에 따라 값을 꺼냅니다. // 매개 변수 값 세트가 비어 있지 않은 경우 (values! = null) {// (int i = 0; i <value.length; i ++) {try {// value [i]) 메소드 (value [i]) 메소드를 호출하여 매개 변수 value vlsout = toutf (valsf [i)); 값 [i] = Vlust; } catch (UnsupportedEncodingException e) {e.printstacktrace (); }} // request request.setAttribute (이름, 값)에서 속성 형식으로 값을 숨 깁니다. }}} // 응답 메소드를 설정하고 중국어를 지원하십시오. // 다음 필터를 계속 실행합니다. 필터가 없으면 요청이 실행됩니다 .Dofilter (요청, 응답); }} 구성:
<!-중국 필터 구성-> <filter> <filter-name> ChineseCoding </filter-name> <filter-class> com.test.filter.characterencoding </filter-class> </filter> <filter-mapping> <filter-name> ChineseCoding </filter-name> <url-fattern>/*</url-plattern> </filptern>
다른
1. PageEncoding 및 ContentType를 설정하십시오
<%@ page language = "java"contenttype = "text/html; charset = utf-8"pageencoding = "utf-8"%>
2. Tomcat의 uriencoding을 설정하십시오
기본적으로 Tomcat Server는 ISO-8859-1 인코딩 형식을 사용하여 Uriencoding 매개 변수에 의해 요청 된 URL을 인코딩하므로 Tomcat의 Server.xml 파일의 <커넥터> 태그에 uriencoding = "utf-8"을 추가하면됩니다.