Java Web 编码问题三:URL和URI以及QueryString的编码问题

在问题之前我们先来了解一下什么是URL,URI以及QueryString,如下图1所示:

图1:URL-URI-QueryString

URL:是全球资源定位符的英文缩写,如上 其中localhost:是指Domain(IP或者主机名),8080:是端口
Web服务一般是80,8080是自己测试是候用的,避免和和浏览器的端口冲突。
ROOT:是ContentPath,就是虚拟路径,如果是tomcat服务器对象的是servlet.xml配置文件中的<Context path=”/ROOT” />
如果没有配置这一个tomcat默认的是path就是ROOT。
Servlet:就是ServletPath的信息,就是和web.xml中的<url-pattern>相对应的,用来查找Servlet。
GetSpecialInfos:就是要请求的文件了。
category=土特产:就是QueryString,相当于用get提交的参数。
URI(Universal Resource Identifier, 简称"URI"):是Web上可用的每种资源。通过URI进行定位。一般是服务器自己使用。

知道了URL,URI和QueryString,我们就可以来试一试他们的编码问题了,看下面一个Java Servlet程序:

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.wl.util.SpecialInfoToJson;
import org.wl.util.StringUtils;
 
/**
 * Servlet implementation class GetSpecialInfo
 */
public class GetSpecialInfos extends HttpServlet {
         private static final long serialVersionUID = 1L;
    private static final Logger log = LogManager.getLogger(); 
    /**
     * @see HttpServlet#HttpServlet()
     */
    public GetSpecialInfos() {
        super();
        // TODO Auto-generated constructor stub
    }
 
         /**
          * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
          */
         protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                   doPost(request, response);
         }
 
         /**
          * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
          */
         protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                   response.setContentType("text/html;charset=utf-8");
                  
                   log.info(request.getCharacterEncoding());
                   request.setCharacterEncoding("utf-8");
                   log.info(request.getCharacterEncoding());
                  log.info(request.getQueryString());
                   System.out.println();
                   String category = request.getParameter("category");
                   if(StringUtils.isNullOrEmpty(category))
                   {
                            response.getWriter().append("category is null");
                            return;
                   }
                   log.info(category);
//               category = new String(category.getBytes("iso-8859-1"),"utf-8");
//               category = new String(category.getBytes("iso-8859-1"),"gbk");
//               log.info(category);
                   response.getWriter().append(SpecialInfoToJson.getCategoryInfo(category));
         }
}

我用的是tomcat服务器,如果要进行简单测试,可以把log语句换为System.out.println();输出直接到控制台,避免配置log4j2。可以把最后的response.getWriter().append(SpecialInfoToJson.getCategoryInfo(category));去掉。

直接通过浏览器访问:http://localhost:8080/market/GetSpecialInfos?category=土特产

把market换为您的工程名字。

通过IE浏览器访问控制台的输出:

null

22:02:58.492 INFO  org.wl.app.GetSpecialInfos 44 doPost - utf-8

22:02:58.492 INFO  org.wl.app.GetSpecialInfos 45 doPost - category=íáì?2ú

22:02:58.492 INFO  org.wl.app.GetSpecialInfos 52 doPost - íáì?2ú

通过Firefox或者Google浏览器访问控制台的输出(忽略了部分输出):

null

utf-8

category=%E5%9C%9F%E7%89%B9%E4%BA%A7

?????1?o§

现在还暂时猜测不出是什么意思,没有关系我们先把把被注释掉的代码

category = new String(category.getBytes("iso-8859-1"),"utf-8");去掉注释,在重新运行。

发现用Firefox或者Google浏览器访问的控制台的输出为:

null

utf-8

category=%E5%9C%9F%E7%89%B9%E4%BA%A7

?????1?o§

土特产

用IE访问控制台的输出为:

null

22:43:56.614 INFO  org.wl.app.GetSpecialInfos 44 doPost - utf-8

22:43:56.614 INFO  org.wl.app.GetSpecialInfos 45 doPost - category=íáì?2ú

22:43:56.614 INFO  org.wl.app.GetSpecialInfos 53 doPost - íáì?2ú

22:43:56.614 INFO  org.wl.app.GetSpecialInfos 56 doPost - ?????

说明Firefox和Google对于QueryString的编码格式是utf-8。而IE对于QueryString的编码肯定不是utf-8。

我们在把category = new String(category.getBytes("iso-8859-1"),"utf-8");注释掉。

把 category = new String(category.getBytes("iso-8859-1"),"gbk");的注释去掉。重新运行,然后通过IE

Firefox、Google浏览器来访问。

控制台的输出为IE正常了,Firefox和Google乱码了。说明IE用的是gbk或者以其兼容的编码方式(gb2312等)

对QueryString进行编码的。

下面我们重新来看一看这一句:category = new String(category.getBytes("iso-8859-1"),"utf-8");

我们为什么要category.getBytes("iso-8859-1"),用iso-8859-1这一编码来得到字节数组。是因为对于QueryString来说,如果没有中请求头(header)中设置contentType,在tomcat的servlet.xml配置文件中也没有设置<Connector URIEncoding=”utf-8” uesBodyEncodingForURI=”true” />这样的配置。那么就会使用iso-8859-1对QueryString进行编码。我们的request.setCharacterEncoding("utf-8");这一句一直输出的是null,说明浏览器并没有设置contentType。我们也没有配置服务器,所以就使用的是iso-8859-1对QueryString进行的编码。

同时我们发现request.setCharacterEncoding("utf-8");这一句好像没有用,对于get方式提交的(包括,url参数,和表单通过get方法提交)的确没有作用,但是对于post提交的是用用的。如果有兴趣可以试一试。

注意:必须同时设定了contentType和uesBodyEncodingForURI=”true”才会使用contentType的方式对QueryString就像解码。

时间: 2024-10-13 13:38:18

Java Web 编码问题三:URL和URI以及QueryString的编码问题的相关文章

Java Web高性能开发(三)

今日要闻: Clarifai:可识别视频中物体 最近几年,得益于深度学习技术的发展,谷歌和Facebook等企业的研究人员在图形识别软件领域取得了重大突破.现在,一家名为Clarifai的创业公司则提供了一项新服务,利用深度学习技术来理解视频内容. 深度学习需要借助一个模拟"神经元"的网络来处理数据,并且利用实例数据对其进行训练.Clarifai的技术源自纽约大学的研究,该公司2013年在一项著名的图片内容识别软件竞赛中取得前五名. 今日英文: http://docs.oracle.c

Java web基础总结三之—— java web 服务器

Java web基础总结三之-- java web 服务器 一.什么是java web服务器 首先来看一下什么是web服务器,它一般指网站服务器,是指一个再互联网一个主机上的一个程序.它可以解析客户端发送来的遵循http协议的请求,并且经过逻辑业务处理后,以http协议向浏览器等Web客户端提供文档. 互联网上供外界访问的Web资源可以分为两种:一个是静态web资源(如html 页面),指web页面中供人们浏览的数据始终是不变.另一个动态web资源,指web页面中供人们浏览的数据是由程序动态产生

Java Web基础(三)(HttpServletRequest-请求基础)

之前已经详细讲解了Servlet/JSP的基础知识,包括Servlet和JSP的关系.Servlet基本的编写和配置,以及一个请求/响应过程中,HTTP服务器.web容器.Servlet是如何配合工作的. 对于一个web应用程序来说,请求/响应是其工作工程的基础,我们这里只考虑基于HTTP协议的请求/响应模型,HttpServletRequest代表请求及相关参数,HttpServletResponse代表响应及相关参数,这两个对象会随着一个请求的发起而建立,随着一个响应的结束而销毁被回收.当一

Java Web学习(三)数据加密方式详解

本文借鉴:chengbinbbs,FKNIGHT0X,Central-Perk(特此感谢!) 对称加密 定义:加密和解密使用相同密钥的算法. 常见的有DES.3DES.AES.PBE等加密算法,这几种算法安全性依次是逐渐增强的. DES加密 特点:简便.密钥长度比较短. /** * DES加密介绍 * DES是一种对称加密算法,所谓对称加密算法即:加密和解密使用相同密钥的算法.DES加密算法出自IBM的研究, * 后来被美国政府正式采用,之后开始广泛流传,但是近些年使用越来越少,因为DES使用5

java web开发入门三(Hibernate)基于intellig idea

Hibernate 1.开发流程 项目配置好后的结构: 1.下载源码: 版本:hibernate-distribution-3.6.0.Final 2.引入hibernate需要的开发包(3.6版本),如果没有引用成功,在jar包上右键执行:add as library 3.编写实体对象及对象的映射xml文件 实体类: package com.eggtwo.test; import java.util.Date; public class Student { private int id; pr

使用Eclipse + Maven 构建Java Web 项目(三)

使用Jetty Maven 插件和Tomcat Maven 插件 1. Jetty Maven 插件 pom配置如下 <build> <finalName>webapp</finalName> <plugins> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <

Java Web学习(三)Maven的配置与使用国内仓库

一.Maven下载与配置 下载好的压缩包,压缩到D盘,或者其他盘符. 新建系统环境变量 MAVEN_HOME  值是压缩好的Maven目录. 比如: D:\apache-maven-3.3.9 在path环境变量中添加 %MAVEN_HOME%\bin; 到这里配置完毕,测试一下,打开命令窗口 mvn -v 出现如上信息就是配置正确. 二.使用国内仓库 路径: D:\apache-maven-3.3.9\conf\settings.xml 将mirrors部分内容替换如下: <mirrors>

java web hibernate自学三

查询方式 OID查询 根据对象的OID主键检索. session.get(Customer.class,1L) session.load(Customer.class,1L) 对象导航检索 根据一个已经查询到的对象,获得关联的对象的一种查询 A a = session.get(A,1L) B b = a.getB() HQL检索 通过session.createQuery()接受一个HQL查询方式 简单查询 Query query = session.createQuery("from Cust

Java Web 涉及到的编码

对于使用中文来说,有 I/O 的地方就会涉及到编码,前面已经提到了 I/O 操作会引起编码,而大部分 I/O 引起的乱码都是网络 I/O,因为现在几乎所有的应用程序都涉及到网络操作,而数据经过网络传输都是以字节为单位的,所以所有的数据都必须能够被序列化为字节.在 Java 中数据被序列化必须继承 Serializable 接口. 这里有一个问题,你是否认真考虑过一段文本它的实际大小应该怎么计算,我曾经碰到过一个问题:就是要想办法压缩 Cookie 大小,减少网络传输量,当时有选择不同的压缩算法,