假设我有:
Yahoo!
我已经确认external_title
将编码Yahoo!%E2%84%A2
并传递给SERVLET
.如果SERVLET
我在做:
Writer writer = response.getWriter(); writer.write(request.getParameter("external_title"));
我在浏览器中获得了Yahoo!¢.如果我手动将浏览器字符编码切换为UTF-8,它将更改为Yahoo! TM(这就是我想要的).
所以我认为我发送到浏览器的编码是错误的(确实如此Content-type: text/html; charset=ISO-8859-1
).我改为SERVLET
:
response.setContentType("text/html; charset=utf-8"); Writer writer = response.getWriter(); writer.write(request.getParameter("external_title"));
现在浏览器字符编码是UTF-8,但它输出Yahoo!但我无法让浏览器呈现正确的字符.
我的问题是:是否存在某些组合Content-type
和/或new String(request.getParameter("external_title").getBytes(), "UTF-8");
和/或其他会导致Yahoo! TM出现在SERVLET
输出中?
你快到了.EncodeURIComponent正确编码为UTF-8,这是您今天应该始终在URL中使用的.
问题是提交的查询字符串在进入服务器端脚本的过程中变得很残缺,因为getParameter()使用ISO-8559-1而不是UTF-8.这源于古代时代之前,网站以UTF-8为URI/IRI确定,但Servlet规范尚未更新以匹配现实,或至少为其提供可靠的支持选项,这是相当可悲的.
(Servlet 2.3中有request.setCharacterEncoding,但它不影响查询字符串解析,如果之前已经读过一个参数,可能是其他一些框架元素,它根本不起作用.)
因此,您需要使用特定于容器的方法来获取正确的UTF-8,通常涉及server.xml中的内容.这对于分发应该在任何地方工作的Web应用程序来说非常糟糕 对于Tomcat,请参阅http://wiki.apache.org/tomcat/FAQ/CharacterEncoding以及Tomcat 的"URIEncoding",编码过滤器和request.setCharacterEncoding之间的区别.
我得到了同样的问题,并通过Request.getQueryString()
使用URLDecoder()解码,并在提取我的参数后解决了它.
String[] Parameters = URLDecoder.decode(Request.getQueryString(), 'UTF-8') .splitat('&');
有办法在java中做(没有摆弄server.xml
)
不工作 :
protected static final String CHARSET_FOR_URL_ENCODING = "UTF-8"; String uname = request.getParameter("name"); System.out.println(uname); // ÏηγÏÏÏÏη uname = request.getQueryString(); System.out.println(uname); // name=%CF%84%CE%B7%CE%B3%CF%81%CF%84%CF%83%CF%82%CE%B7 uname = URLDecoder.decode(request.getParameter("name"), CHARSET_FOR_URL_ENCODING); System.out.println(uname); // ÏηγÏÏÏÏη // !!!!!!!!!!!!!!!!!!!!!!!!!!! uname = URLDecoder.decode( "name=%CF%84%CE%B7%CE%B3%CF%81%CF%84%CF%83%CF%82%CE%B7", CHARSET_FOR_URL_ENCODING); System.out.println("query string decoded : " + uname); // query string decoded : name=???????? uname = URLDecoder.decode(new String(request.getParameter("name") .getBytes()), CHARSET_FOR_URL_ENCODING); System.out.println(uname); // ÏηγÏÏÏÏη // !!!!!!!!!!!!!!!!!!!!!!!!!!!
作品:
final String name = URLDecoder .decode(new String(request.getParameter("name").getBytes( "iso-8859-1")), CHARSET_FOR_URL_ENCODING); System.out.println(name); // ????????
工作但如果默认编码会中断!= utf-8 - 尝试这样做(省略对decode()的调用,不需要):
final String name = new String(request.getParameter("name").getBytes("iso-8859-1"), CHARSET_FOR_URL_ENCODING);
正如我上面所说,如果server.xml
被搞砸了如下:
(注意URIEncoding="UTF-8"
)上面的代码会中断(导致getBytes("iso-8859-1")
应该读取getBytes("UTF-8")
).因此,对于防弹解决方案,您必须获取URIEncoding
属性的值.遗憾的是,这似乎是容器特定的 - 甚至更糟糕的容器版本.对于tomcat 7,您需要以下内容:
import javax.management.AttributeNotFoundException; import javax.management.InstanceNotFoundException; import javax.management.MBeanException; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.management.ReflectionException; import org.apache.catalina.Server; import org.apache.catalina.Service; import org.apache.catalina.connector.Connector; public class Controller extends HttpServlet { // ... static String CHARSET_FOR_URI_ENCODING; // the `URIEncoding` attribute static { MBeanServer mBeanServer = MBeanServerFactory.findMBeanServer(null).get( 0); ObjectName name = null; try { name = new ObjectName("Catalina", "type", "Server"); } catch (MalformedObjectNameException e1) { e1.printStackTrace(); } Server server = null; try { server = (Server) mBeanServer.getAttribute(name, "managedResource"); } catch (AttributeNotFoundException | InstanceNotFoundException | MBeanException | ReflectionException e) { e.printStackTrace(); } Service[] services = server.findServices(); for (Service service : services) { for (Connector connector : service.findConnectors()) { System.out.println(connector); String uriEncoding = connector.getURIEncoding(); System.out.println("URIEncoding : " + uriEncoding); boolean use = connector.getUseBodyEncodingForURI(); // TODO : if(use && connector.get uri enc...) CHARSET_FOR_URI_ENCODING = uriEncoding; // ProtocolHandler protocolHandler = connector // .getProtocolHandler(); // if (protocolHandler instanceof Http11Protocol // || protocolHandler instanceof Http11AprProtocol // || protocolHandler instanceof Http11NioProtocol) { // int serverPort = connector.getPort(); // System.out.println("HTTP Port: " + connector.getPort()); // } } } } }
而且你还需要为多个连接器调整它(检查注释掉的部分).然后你会使用类似的东西:
new String(parameter.getBytes(CHARSET_FOR_URI_ENCODING), CHARSET_FOR_URL_ENCODING);
如果使用CHARSET_FOR_URI_ENCODING进行解码,则可能会失败(IIUC)parameter = request.getParameter("name");
,因此使用getBytes()得到的字节不是原始字节(这就是为什么默认使用"iso-8859-1" - 它将保留字节).您可以通过手动解析以下行中的查询字符串来解决所有问题:
URLDecoder.decode(request.getQueryString().split("=")[1], CHARSET_FOR_URL_ENCODING);
我仍然在寻找在那里提到,在文档中的位置request.getParameter("name")
并调用URLDecoder.decode()
返回而不是%CF%84%CE%B7%CE%B3%CF%81%CF%84%CF%83%CF%82%CE%B7
字符串?源中的链接将非常感激.
另外,我怎样才能将字符串作为参数的值传递 =>看评论: %CE
?parameter=%25CE