Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 亚洲精品久久久久影,国产91热爆ts人妖在线,男女拍拍免费视频60分钟

          整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          踩坑日記(十一):微服務間 OpenFeign 傳遞

          踩坑日記(十一):微服務間 OpenFeign 傳遞Header返回值亂碼

          在微服務架構(gòu)下,業(yè)務系統(tǒng)的功能是由大量的微服務組成,例如:一個電商購物平臺下單環(huán)節(jié)就需要訂單服務、庫存服務、短信服務和物流服務等逐級調(diào)用。但是每個服務是由不同的研發(fā)團隊負責的,部署在成百上千臺服務器上。

          示例

          在這么復雜的數(shù)據(jù)傳遞過程中最怕發(fā)生系統(tǒng)故障,因為很難去快速定位到問題。所以就要引入服務間的鏈路追蹤。

          在技術(shù)調(diào)研過程中大致有以下幾種方案:
          1、基于 Sleuth + Zipkin 方案
          2、通過 SkyWalking 實施鏈路追蹤
          3、自建鏈路追蹤

          這里選擇了自建鏈路追蹤的方式,至于為啥不用1、2 就不多講了,這次的坑是在自建過程中采用的是通過 OpenFeign 來作為服務間遠程數(shù)據(jù)交換,通過在HTTP請求的Header 總增加TraceId 參數(shù)來作為服務間的鏈路追蹤。

          OpenFeign調(diào)用傳遞Header方案

          import feign.RequestInterceptor;
          import lombok.extern.slf4j.Slf4j;
          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Configuration;
          import org.springframework.web.context.request.RequestContextHolder;
          import org.springframework.web.context.request.ServletRequestAttributes;
          
          import javax.servlet.http.HttpServletRequest;
          import java.util.Enumeration;
          
          @Configuration
          @Slf4j
          public class FeignClientConfig {
              @Bean
              public RequestInterceptor headerInterceptor() {
                  return template -> {
                      ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                      if (null !=attributes) {
                          HttpServletRequest request=attributes.getRequest();
                          Enumeration<String> headerNames=request.getHeaderNames();
                          if (headerNames !=null) {
                              while (headerNames.hasMoreElements()) {
                                  String name=headerNames.nextElement();
                                  String values=request.getHeader(name);
                                  template.header(name, values);
                              }
                          }
                      }
                  };
              }
          }
          

          問題

          上面說到有些服務是其他團隊負責研發(fā)的,有自己的網(wǎng)關(guān)、鑒權(quán)等。那么在通過OpenFeign調(diào)用的時候出現(xiàn)了返回亂碼,具體如下:

          {
          	"code": "200",
          	"message": "請求成功",
          	"result": "\u0015\u0013\u0001\u0000??Y[???3Y????\u000E??H?GHВ?????Y\u0018H??%?@?@?m??\u001BL%???\u0019u\u000Ev-+??8&t???\t<?\u001EW0002?\t?eZ?\u0004?Xk,??lt5\u0010\u0004V\u0000*???D?*?0??\u0000[???\u0005????y???\u001B\b?,r?C\u0012\u000G?3?m??<?v\"?]?m??`??p1^?J??h\u00M#?$\u001F?<?\r?Hf[?\u0002"
          }

          比較奇怪的是只有個別服務是有問題的,也沒有辦法去看對方的代碼。

          原因分析

          最終定位到的原因是Request 的Header 中設置Accept-Encoding:gzip, deflate, br;的問題,如果加上就會返回亂碼。

          最開始的時候以為是編碼的問題,所以小編嘗試了各種編碼,但是始終無法解決問題。

          后來想到 Accept-Encoding 不參與數(shù)據(jù)傳遞就OK啦!

          增加代碼:

          總結(jié):

          之所以添加:"Accept-Encoding"="gzip, deflate, br"

          是因為,瀏覽器對于從服務器中返回的對應的gzip壓縮的網(wǎng)頁,會自動解壓縮,所以Request的時候,添加對應的Header信息,表示接收壓縮后的數(shù)據(jù)。

          而此代碼中,如果也添加此頭信息,結(jié)果就是,返回的壓縮后的數(shù)據(jù),由于沒有解碼,客戶端將壓縮后的數(shù)據(jù)當做普通的html文本來處理,當前顯示出來的內(nèi)容,是亂碼了。

          小編選擇的是排除掉 Accept-Encoding ,當然也可以只去掉 gzip參數(shù)。

          文轉(zhuǎn)自與博客園一杯涼茶的博客.

          Servlet是一種古老的Java Web技術(shù),在開發(fā)中除了祖?zhèn)鞯捻椖?已經(jīng)很少見到它的身影,但是作為Java Web的重要組成部分,Servlet還是值得深入學習的,形形色色框架再好用,底層終歸還是Servlet,Service ,JDBC這些基礎(chǔ)的東西,學好Servlet有助于大家審理理解框架的底層源碼深入學習,也為大家在面試過程中取得一線生機,但是在servlet經(jīng)常會遇到一些亂碼問題,今天我們來聊聊解決Servlet中的亂碼問題。

          一、request請求參數(shù)出現(xiàn)的亂碼問題

          get請求:

          get請求的參數(shù)是在url后面提交過來的,也就是在請求行中,

          MyServlet是一個普通的Servlet,瀏覽器訪問它時,使用get請求方式提交了一個name=小明的參數(shù)值,在doGet中獲取該參數(shù)值,并且打印到控制臺,發(fā)現(xiàn)出現(xiàn)亂碼

          出現(xiàn)亂碼的原因:

          前提知識:需要了解碼表,編碼,解碼這三個名詞的意思。我簡單說一下常規(guī)的,

          碼表:是一種規(guī)則,用來讓我們看得懂的語言轉(zhuǎn)換為電腦能夠認識的語言的一種規(guī)則,有很多中碼表,IS0-8859-1,GBK,UTF-8,UTF-16等一系列碼表,比如GBK,UTF-8,UTF-16都可以標識一個漢字,而如果要標識英文,就可以用IS0-8859-1等別的碼表。

          編碼:將我們看得懂的語言轉(zhuǎn)換為電腦能夠認識的語言。這個過程就是編碼的作用

          解碼:將電腦認識的語言轉(zhuǎn)換為我們能看得懂得語言。這個過程就是解碼的作用

          詳細請參考這篇博文。

          這里只能夠代表經(jīng)過一次編碼例子,有些程序中,會將一個漢字或者一個字母用不同的碼表連續(xù)編碼幾次,那么第一次編碼還是上面所說的作用,第二次編碼的話,就是將電腦能夠認識的語言轉(zhuǎn)換為電腦能夠認識的語言(轉(zhuǎn)換規(guī)則不同),那么該解碼過程,就必須要經(jīng)過兩次解碼,也就是編碼的逆過程,下面這個例子就很好的說明了這個問題。

          瀏覽器使用的是UTF-8碼表,通過http協(xié)議傳輸,http協(xié)議只支持IS0-8859-1,到了服務器,默認也是使用的是IS0-8859-1的碼表,看圖

          也就是三個過程,經(jīng)歷了兩次編碼,所以就需要進行兩次解碼,

          1、瀏覽器將"小明"使用UTF-8碼表進行編碼(因為小明這個是漢字,所以使用能標識中文的碼表,這也是我們可以在瀏覽器上可以手動設置的,如果使用了不能標識中文的碼表,那么就將會出現(xiàn)亂碼,因為碼表中找不到中文對應的計算機符號,就可能會用??等其他符號表示),編碼后得到的為 1234 ,將其通過http協(xié)議傳輸。

          2、在http協(xié)議傳輸,只能用ISO-8859-1碼表中所代表的符號,所以會將我們原先的1234再次進行一次編碼,這次使用的是ISO-8859-1,得到的為 ???? ,然后傳輸?shù)椒掌?/p>

          3、服務器獲取到該數(shù)據(jù)是經(jīng)過了兩次編碼后得到的數(shù)據(jù),所以必須跟原先編碼的過程逆過來解碼,先是UTF-8編碼,然后在ISO-8859-1編碼,那么解碼的過程,就必須是先ISO-8859-1解碼,然后在用UTF-8解碼,這樣就能夠得到正確的數(shù)據(jù)。????.getBytes("ISO-8859-1");//第一次解碼,轉(zhuǎn)換為電腦能夠識別的語言, new String(1234,"UTF-8");//第二次解碼,轉(zhuǎn)換為我們認識的語言

          解決代碼

          Post請求:

          post請求方式的參數(shù)是在請求體中,相對于get請求簡單很多,沒有經(jīng)過http協(xié)議這一步的編碼過程,所以只需要在服務器端,設置服務器解碼的碼表跟瀏覽器編碼的碼表是一樣的就行了,在這里瀏覽器使用的是UTF-8碼表編碼,那么服務器端就設置解碼所用碼表也為UTF-8就OK了

          設置服務器端使用UTF-8碼表解碼

          request.setCharacterEncoding("UTF-8"); //命令Tomcat使用UTF-8碼表解碼,而不用默認的ISO-8859-1了。

          所以在很多時候,在doPost方法的第一句,就是這句代碼,防止獲取請求參數(shù)時亂碼。

          總結(jié)請求參數(shù)亂碼問題

          get請求和post請求方式的中文亂碼問題處理方式不同

          get:請求參數(shù)在請求行中,涉及了http協(xié)議,手動解決亂碼問題,知道出現(xiàn)亂碼的根本原因,對癥下藥,其原理就是進行兩次編碼,兩次解碼的過程

          new String(xxx.getBytes("ISO-8859-1"),"UTF-8");

          post:請求參數(shù)在請求體中,使用servlet API解決亂碼問題,其原理就是一次編碼一次解碼,命令tomcat使用特定的碼表解碼。

          request.setCharaterEncoding("UTF-8");

          二、response響應回瀏覽器出現(xiàn)的中文亂碼。

          首先介紹一下,response對象是如何向瀏覽器發(fā)送數(shù)據(jù)的。兩種方法,一種getOutputStream,一種getWrite。

          ServletOutputStream getOutputStream(); //獲取輸出字節(jié)流。提供write() 和 print() 兩個輸出方法

          PrintWriter getWrite(); //獲取輸出字符流 提供write() 和 print()兩個輸出方法

          print()方法底層都是使用write()方法的,相當于print()方法就是將write()方法進行了封裝,使開發(fā)者更方便快捷的使用,想輸出什么,就直接選擇合適的print()方法,而不用考慮如何轉(zhuǎn)換字節(jié)。

          1、ServeltOutputStream getOutputStream();

          不能直接輸出中文,直接輸出中文會報異常,

          報異常的源代碼

          解決:

          resp.getoutputStream().write("哈哈哈,我要輸出到瀏覽器".getBytes("UTF-8"));

          將要輸出的漢字先用UTF-8進行編碼,而不用讓tomcat來進行編碼,這樣如果瀏覽器用的是UTF-8碼表進行解碼的話,那么就會正確輸出,如果瀏覽器用的不是UTF-8,那么還是會出現(xiàn)亂碼,所以說這個關(guān)鍵要看瀏覽器用的什么碼表,這個就不太好,這里還要注意一點,就是使用的是write(byte)方法,因為print()方法沒有輸出byte類型的方法。

          2、PrintWriter getWrite();

          直接輸出中文,不會報異常,但是肯定會報異常,因為用ISO-8859-1的碼表不能標識中文,一開始就是錯的,怎么解碼編碼讀沒用了

          有三種方法來讓其正確輸出中文

          1、使用Servlet API response.setCharacterEncoding()

          response.setCharacterEncoding("UTF-8"); //讓tomcat將我們要響應到瀏覽器的中文用UTF-8進行編碼,而不使用默認的ISO-8859-1了,這個還是要取決于瀏覽器是不是用的UTF-8的碼表,跟上面的一樣有缺陷

          2、通知tomcat和瀏覽器都使用同一張碼表

          response.setHeader("content-type","text/html;charset=uft-8"); //手動設置響應內(nèi)容,通知tomcat和瀏覽器使用utf-8來進行編碼和解碼。

          charset=uft-8就相當于response.setCharacterEncoding("UTF-8");//通知tomcat使用utf-8進行編碼

          response.setHeader("content-type","text/html;charset=uft-8");//合起來,就是既通知tomcat用utf-8編碼,又通知瀏覽器用UTF-8進行解碼。

          response.setContentType("text/html;charset=uft-8"); //使用Servlet API 來通知tomcaat和強制瀏覽器使用UTF-8來進行編碼解碼,這個的底層代碼就是上一行的代碼,進行了簡單的封裝而已。

          3、通知tomcat,在使用html<meta>通知瀏覽器 (html源碼),注意:<meta>建議瀏覽器應該使用編碼,不能強制要求

          進行兩步

          所以response在響應時,只要通知tomcat和瀏覽器使用同一張碼表,一般使用第二種方法,那么就可以解決響應的亂碼問題了

          三、總結(jié)

          在上面講解的時候總是看起來很繁瑣,其實知道了其中的原理,很簡單,現(xiàn)在來總結(jié)一下,

          請求亂碼

          get請求:

          經(jīng)過了兩次編碼,所以就要兩次解碼

          第一次解碼:xxx.getBytes("ISO-8859-1");得到y(tǒng)yy

          第二次解碼:new String(yyy,"utf-8");

          連續(xù)寫:new String(xxx.getBytes("ISO-8859-1"),"UTF-8");

          post請求:

          只經(jīng)過一次編碼,所以也就只要一次解碼,使用Servlet API request.setCharacterEncoding();

          request.setCharacterEncoding("UTF-8"); //不一定解決,取決于瀏覽器是用什么碼表來編碼,瀏覽器用UTF-8,那么這里就寫UTF-8。

          響應亂碼

          getOutputStream();

          使用該字節(jié)輸出流,不能直接輸出中文,會出異常,要想輸出中文,解決方法如下

          解決:getOutputStream().write(xxx.getBytes("UTF-8")); //手動將中文用UTF-8碼表編碼,變成字節(jié)傳輸,變成字節(jié)后,就不會報異常,并且tomcat也不會在編碼,因為已經(jīng)編碼過了,所以到瀏覽器后,如果瀏覽器使用的是UTF-8碼表解碼,那么就不會出現(xiàn)中文亂碼,反之則出現(xiàn)中文亂碼,所以這個方法,不能完全保證中文不亂碼

          getWrite();

          使用字符輸出流,能直接輸出中文,不會出異常,但是會出現(xiàn)亂碼。能用三種方法解決,一直使用第二種方法

          解決:通知tomcat和瀏覽器使用同一張碼表。

          response.setContentType("text/html;charset=utf-8"); //通知瀏覽器使用UTF-8解碼

          通知tomcat和瀏覽器使用UTF-8編碼和解碼。這個方法的底層原理是這句話:response.setHeader("contentType","text/html;charset=utf-8");

          注意:getOutputStream()和getWrite() 這兩個方法不能夠同時使用,一次只能使用一個,否則報異常。

          上一篇:深入學習Java Web(一):深入了解Servlet

          文將介紹一種Java Web/Api 開發(fā)常見的亂碼問題。

          前提摘要:在學習Java Web的過程中,亂碼問題是經(jīng)常遇到的,無論是頁面亂碼還是數(shù)據(jù)庫亂碼。本文將羅列筆者在開發(fā)過程中常常遇到幾種亂碼場景。

          一、JSP頁面亂碼

          因為網(wǎng)頁默認的編碼格式為ISO-8859-1,該編碼格式不支持漢字,所以在網(wǎng)頁上顯示為亂碼???.

          解決方案

          在文件頂部添加header上添加

          <pre>

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

          </pre>

          二、ajax請求時 request.getParams亂碼

          在你的tomcat server.xml中配置

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

          </pre>

          即添加

          如果你想學習java可以來這個群,五三二,二五九,九五二,里面有大量的學習資料可以下載。 URIEconding="UTF-8" useBodyEncodingForURI="true"

          三、ajax請求時 response出去為亂碼

          在使用Spring MVC時 須在web.xml 配置

          <filter>

          mvc注釋 RequestMapping 聲明 增加utf-8聲明如

          @RequestMapping(method=RequestMethod.POST, produces="application/json; charset=utf-8")

          如果是普通的servlet時,則須代碼編碼之后輸出

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

          三、文件亂碼

          經(jīng)常在拿到別人的工程文件時,由于他不同的編碼例如GBK之類的編碼,需要在IDE中將文件編碼統(tǒng)一成UTF-8 即可.

          window平臺下,可以實用notepad++進行編轉(zhuǎn)化替換即可。

          四、終端亂碼

          如果是 System.out.println 打印顯示亂碼 則 VM options 里 添加 -Dfile.encoding=UTF-8 參數(shù)

          五、數(shù)據(jù)庫亂碼

          • jdbc鏈接utf-8聲明

          jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8

          • 新建數(shù)據(jù)庫時,選擇utf-8/utf-8mb4編碼

          六、emoji亂碼支持

          • 新建數(shù)據(jù)庫選擇utf-8mb4

          • 數(shù)據(jù)庫的字符集配置 參考mysql/Java服務端對emoji的支持

          • mysql-connector-java 版本升級至 5.1.22,此版本筆者親測 Ok!

          如果你想學習java可以來這個群 532259952


          主站蜘蛛池模板: 久久国产精品视频一区| 日韩精品人妻一区二区三区四区| 久久久久人妻一区精品性色av| 国产精品一区二区资源| 久久国产精品无码一区二区三区 | 国产福利91精品一区二区| 中文乱码精品一区二区三区| 日韩精品一区二区三区中文版| 亚洲av乱码一区二区三区| 亚州日本乱码一区二区三区| 国产成人精品无人区一区| 日韩精品一区二区三区视频| 日韩视频在线一区| 午夜DV内射一区区| 精品久久久中文字幕一区| 亚洲AV日韩AV一区二区三曲| 99久久无码一区人妻a黑| 精品国产一区二区三区久久久狼| 亚洲国产精品一区二区久久hs| 一区二区三区影院| 日韩精品无码一区二区三区四区 | 久久久无码一区二区三区| 色狠狠色噜噜Av天堂一区| 本免费AV无码专区一区| 国产综合一区二区在线观看| 久久国产三级无码一区二区| 国产精品一区二区av不卡| 制服中文字幕一区二区| 波多野结衣AV无码久久一区| 农村人乱弄一区二区| 久久精品国产一区| 老熟妇仑乱视频一区二区| 亚洲AV成人精品一区二区三区| 国模精品一区二区三区视频| 国产一区二区三区播放| 中文日韩字幕一区在线观看| 精品少妇一区二区三区视频| 最新欧美精品一区二区三区| 四虎在线观看一区二区| 亚洲福利视频一区二区| 久久精品视频一区二区三区|