0%

URL乱码

URL只能使用英文字母、阿拉伯数字和某些标点符号,不能使用其他文字和符号。这是因为网络标准RFC1738做了硬性规定:
1581572958(1)
通过下图我们可以了解在javaWeb中有哪些地方有转码:
1582610127(1)

二、HTML页面(response乱码)

响应给客户端浏览器,Tomcat默认以ISO-8859-1编码

  • 网页中html的编码:HTTP header 、meta、user-agent(浏览器) 权重越来越低,也就是说http头会覆盖meta头信息。
  • 可以在后台设置编码方式:response.setContentType(“text/html; charset=utf-8”);在响应头中有Content-Type
  • 可以在前端设置编码方式:meta content=”text/html; charset=utf-8” http-equiv=”Content-Type”
    HTML5简化成meta charset=”utf-8”
    css文件顶部:@charset utf-8
  • 若前两者均没有,浏览器一般有默认编码。
    Content-Type:是Http的实体首部字段,用于说明请求或返回的消息主体是用何种方式编码,在request header和response header里都存在。

  当浏览器请求一个静态的html页面时,服务器会将html页面的字节流通过网络传输给浏览器。浏览器再将字节流解码成相应的html文本字符,然后将html元素渲染出来。在这个流程中浏览器有一个解码html字节流的过程。浏览器如何判断用什么编码格式去解码呢?在html页面的head标签中通常会包含一个指定页面编码的标签,如果指定的是utf-8编码,浏览器就用utf-8解码html页面。问题是在浏览器解析标签获得页面编码之前,浏览器是用什么编码来解析标签的呢?因为html开头都是字母,基本不会存在ASCII码之外的字符,所以识别起来还是没有难度的。

  • 查看页面编码方式(也就是浏览器查看应该用什么方式解码)如下图:
    1582089687(1)

  • 一个html页面可以有多种编码:
    与html页面编码相关的还有js(css)文件编码,默认是采用html的编码格式去解析js(css)文件。如果js(css)文件与html页面编码方式不同,则script标签有一个charset属性来指定编码方式。
    script type=”text/javascript” src=”myscripts.js” charset=”UTF-8”/

三、Web后台编码(request乱码)

服务器端获取客户端传递过来的数据出现乱码的问题
html页面是utf-8格式的, 页面编码也指定为utf-8。

  • 表单POST
      对于POST方式,它采用的编码也是由页面来决定的即contentType。当我通过点击页面的submit按钮来提交表单时,浏览器首先会根据contentType的charset编码格式来对POST表单的参数进行编码然后提交给服务器,在服务器端同样也是用contentType中设置的字符集来进行解码。
    1582092789
      html提交普通表单时,参数以字节流的方式传输到web服务器,web服务器解码字节流得到参数。tomcat默认采用ISO-8859-1编解码,所以直接获取参数是乱码,以ISO-8859-1编码回原本的字节流再用utf-8重新解码就可以得到正确的参数。
      可以在获取任何参数前调用 request.setCharacterEncoding(“utf-8”) ,即可用utf-8解码参数,就不用那么麻烦了。其他语言在原理上也都是相同的。
  • 表单GET
      当用户点击submit提交表单时,浏览器会根据设定的编码来编码数据传递给服务器。通过GET方式提交的数据都是拼接在URL后面(可以当做query String??)来提交的,所以tomcat服务器在进行解码过程中URIEncoding就起到作用了。tomcat服务器会根据设置的URIEncoding来进行解码,如果没有设置则会使用默认的ISO-8859-1来解码。假如我们在页面将编码设置为UTF-8,而URIEncoding设置的不是或者没有设置,那么服务器进行解码时就会产生乱码。这个时候我们一般可以通过new String(request.getParameter(“name”).getBytes(“iso-8859-1”),”utf-8”) 的形式来获取正确数据。

有两种方法:
①Tomcat中配置(用的较多)
connectionTimeout=”20000”
redirectPort=”8443”
URIEncoding=”UTF-8”
②String username = request.getParameter(“username”);
username = new String(username.getBytes(“ISO-8859-1”),”UTF-8”);

  • URL

方法一:javascript
encodeURI()和encodeURIComponent()都是Javascript中对URL编码的函数。
但是区别在于:
encodeURI()着眼于对整个URL进行编码,特殊含义的符号”; / ? : @ & = + $ , #“不进行编码
encodeURIComponent()对URL的组成部分进行个别编码,所以”; / ? : @ & = + $ , #”在这里是可以进行编码
1582610974(1)
可以在javascript中get、post提交数据,但要先将不合法字符转码。
1582612709
  常见的URL编码函数主要有encodeURIComponent()和encodeURI(),两者的区别如下:
前者假定它的参数是URL的一部分(比如协议、主机名、路径或查询字符串)。因此 encodeURIComponent() 函数将转义用于分隔 URL各个部分的标点符号。
encodeURI() 用于编码整个URL,因为URL中的合法字符都不会被编码转换。encodeURIComponent方法在编码单个URIComponent(指请求参数)应当是最常用的,它可以将参数中的中文、特殊字符进行转义,而不会影响整个URL。
若用encodeURL不会对特殊符号处理,而在后端解码时会处理,所有有时会造成解码错误。
方法二:过滤器
参考:https://teakki.com/p/57df76f11201d4c1629b9605

四、哪些字符需要转码

  • ASCII的控制字符
    ASCII表上的数字0–31分配给了控制字符,用于控制像打印机等一些外围设备。例如,12代表换页/新页功能,指示打印机跳到下一页的开头。这些字符是不可打印的,自然需要转化。
  • 一些非ASCII字符
    比如中文,阿拉伯字符等。
  • 一些保留字符
    比如最常见的连接符“&”。(&是看成普通字符还是参数分隔符)
  • 一些不安全的字符
    比如空格,为了防止引起歧义,需要转化成“+”。

字符编码:ASCII Unicode UTF-8
参考:https://www.cnblogs.com/luguo3000/p/3627027.html