亚洲精品亚洲人成在线观看麻豆,在线欧美视频一区,亚洲国产精品一区二区动图,色综合久久丁香婷婷

              當前位置:首頁 > IT技術 > Web編程 > 正文

              Servlet請求轉發(fā)至html頁面中文亂碼問題與分析
              2021-09-23 06:48:51

              起因

              在編寫servlet代碼的時候,練習重定向和請求轉發(fā),發(fā)現(xiàn)重定向至html頁面時,頁面顯示中文正常,使用請求轉發(fā)至html頁面時,顯示中文亂碼,兩個servlet都在doGet()方法內首先使用了resp.setCharacterEncoding("UTF-8");設置編碼為UTF-8。

              核心代碼

              各部分核心代碼如下:

              重定向repRedirect代碼:

              @WebServlet("/repTest")
              public class repRedirect extends HttpServlet {
                  @Override
                  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                      doGet(req,resp);
                  }
              
                  @Override
                  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                      resp.setContentType("text/html;charset=utf-8");
                      String username=req.getParameter("username");
                      String password=req.getParameter("password");
              
                      if(username.equals("admin")&&password.equals("123456")){
                          resp.sendRedirect("/Unit7/welcome.html");
                      }else{
                          resp.sendRedirect("/Unit7/fail.html");
                      }
                  }
              }
              

              請求轉發(fā)repForward.java代碼:

              @WebServlet("/repForward")
              public class repForward extends HttpServlet {
              
                  @Override
                  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //        resp.setContentType("text/html;charset=utf-8");
                      resp.setCharacterEncoding("UTF-8");
                      resp.setHeader("Content-Type","text/html;charset=UTF-8");
                      String username=req.getParameter("username");
                      String password=req.getParameter("password");
              //        if(username.isEmpty()&&password.isEmpty()){
              //            resp.sendRedirect("/Unit/welcome.html");
              //        }
                      if(username.equals("admin")&&password.equals("123456")){
                          req.getRequestDispatcher("/Unit7/welcome.html").forward(req,resp);
                      }else{
                          req.getRequestDispatcher("/Unit7/fail.html").forward(req,resp);
                      }
                  }
              
                  @Override
                  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                      doGet(req,resp);
                  }
              }
              

              跳轉的html頁面代碼

              welcome.html

              <!DOCTYPE html>
              <html>
              <head>
                  <meta charset="UTF-8">
                  <title>Title</title>
              </head>
              <body>
                  <h3>歡迎登陸</h3>
              </body>
              </html>
              fail.html
              <!DOCTYPE html>
              <html lang="en">
              <head>
                  <meta charset="UTF-8">
                  <title>Title</title>
              </head>
              <body>
                  <h3>登陸失敗</h3>
              </body>
              </html>
              

              訪問效果

              訪問重定向頁面

              http://127.0.0.1:8080/repTest?username=admin&password=123456
              

              img

              訪問請求轉發(fā)頁面

              http://127.0.0.1:8080/repForward?username=admin&password=123456
              

              img

              可以看出請求轉發(fā)出現(xiàn)了亂碼

              我們再故意輸錯密碼,測試一下請求轉發(fā)失敗的頁面fail.html

              http://127.0.0.1:8080/repForward?username=admin&password=1234
              

              img

              同樣亂碼

              解決方法(1)

              網(wǎng)上已經(jīng)有人給出了解決方法,即將請求轉發(fā)跳轉的html編碼設置為GBK,如下

              img

              重新訪問請求轉發(fā)頁面

              http://127.0.0.1:8080/repForward?username=admin&password=123456
              

              img

              此時亂碼恢復正常

              fail.html頁面并沒有修改為GBK,我們訪問它試試,進行對照比較

              http://127.0.0.1:8080/repForward?username=admin&password=1234
              

              img

              依舊亂碼,可以看出是設置GBK生效

              原因分析

              雖然這樣設置能夠讓頁面的亂碼正常,但是我們實際上是在servlet里面設置了UTF-8編碼,為什么頁面上還需要改為GBK,而為什么請求轉發(fā)和重定向都設置了UTF-8但只有請求轉發(fā)的頁面顯示亂碼了

              在這篇博文中提到

              因此,我認為一個HTML文件在集成開發(fā)創(chuàng)建時是UTF-8的格式,這個格式在IDE上應該可以設置,但在打開時是更具默認編碼格式打開的(即ANSI),因此會產(chǎn)生亂碼

              而在我們的討論+猜測下,請求轉發(fā)的過程類似于

              img

              圖中的GBK指的是servlet默認讀取文件的編碼方式,不同地區(qū)的電腦可能默認不一樣

              在另一篇博文對請求轉發(fā)詳細流程的介紹中也提到:

              forward() 方法的處理流程:
                ● 清空用于存放響應正文(響應體)數(shù)據(jù)的緩沖區(qū)。
                ● 如果目標組件為Servlet 或JSP,就調用它們的service() 方法,把該方法產(chǎn)生的響應結果發(fā)送到客戶端,如果目標組件為文件系統(tǒng)中的靜態(tài) html 文檔,就讀去文檔中的數(shù)據(jù)并把它發(fā)送到客戶端。

              也就是說,請求轉發(fā)是有一個讀文檔數(shù)據(jù)的過程,側面論證了圖示

              讀文檔數(shù)據(jù)涉及到了文檔原來的編碼和讀取文件的編碼方式,分析可得,出現(xiàn)亂碼的原因是,文檔本身的編碼是UTF-8,但servlet讀取時是使用默認編碼方式GBK讀取的。

              而我們在servlet中設置編碼的過程,也就是圖中的第二部分,所以不管我們用什么樣的方式設置UTF-8,都只會讓只能使用GBK解析的頁面亂碼

              當然這一部分還是猜測,所以我們用另外兩種方法來驗證我們的觀點

              論證1

              不管編碼解碼的結果如何,我們想要傳遞的數(shù)據(jù)字節(jié)流是不變的,它不會因為亂碼字符就從登陸成功變成登陸失敗,換一句話說,不管用中文還是英文表達同一件事情,其內核都是表達的這件事,并不會因為使用的語言而改變

              既然文檔本身的編碼是UTF-8,servlet讀取方式為GBK,我們把文檔本身編碼修改為GBK,如果上面的推斷是正確的,這樣做應該就能夠讓亂碼正常

              流程為:

              GBK -> GBK -> 字符流 -> UTF-8 ->UTF-8頁面顯示

              打開VScode,方便轉換編碼

              img

              可以看到文件此時保存的編碼為UTF-8

              我們修改其為GBK,點擊通過編碼保存

              img

              設置成GBK

              img

              可以見到此時文件保存編碼修改為了 GBK

              img

              這個時候再啟動servlet請求轉發(fā)

              訪問 http://127.0.0.1:8080/repForward?username=admin&password=123456

              顯示正常

              img

              側面反映了我們思考的過程是正確的

              論證2

              配置XML文件

              <jsp-config>
                  <jsp-property-group>
                      <url-pattern>*.html</url-pattern>
                      <page-encoding>UTF-8</page-encoding>
                  </jsp-property-group>
              </jsp-config>
              

              意思是,任何以html結尾的URL請求的資源,都以UTF-8格式打開,這里也就是修改servlet的讀取文件編碼方式,此時將welcome.html文件的編碼修改回UTF-8

              img

              img

              重啟服務,訪問請求轉發(fā)頁面

              http://127.0.0.1:8080/repForward?username=admin&password=123456
              

              此時訪問的頁面編碼依舊沒有亂碼,說明jsp-config起了作用,同時確實是因為servlrt默認讀取html文件的編碼方式為GBK

              img

              為了驗證真的是jsp-config的作用,將其刪除再試一次

              刪除后訪問亂碼

              img

              證明確實servlet默認讀取html文件編碼方式為GBK,這個默認方式不同的地區(qū)應該是不同的,例如美國應該是ASCII

              總結

              兩個論證中的方法也都能解決請求轉發(fā)至html頁面亂碼的問題

              亂碼出現(xiàn)的原因是文件本身編碼和servlet默認讀取文件編碼方式不一樣而導致的

              至于為什么重定向的頁面顯示中文是正常的,我們認為是請求轉發(fā)和重定向這兩個功能的實現(xiàn)在servlet中不一樣,比如請求轉發(fā)是需要讀取轉發(fā)的html文件,重定向是讓用戶自己重新去訪問html頁面,缺少了默認讀取的部分,具體的實現(xiàn)區(qū)別需要看servlet的源代碼才能知道

              參考鏈接

              END

              建了一個微信的安全交流群,歡迎添加我微信備注進群,一起來聊天吹水哇,以及一個會發(fā)布安全相關內容的公眾號,歡迎關注 ??

              GIF GIF

              本文摘自 :https://www.cnblogs.com/

              開通會員,享受整站包年服務立即開通 >