分享
 
 
 

J2EE Web组件中中文及相关的问题(四)

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

5. 使用过滤器

实际中我们处理客户端数据时,大多数时候都是在JavaBean中实现的,我们当然可以在会话Bean中把decoding掺合进去,但没有谁愿意这么做,而事实上我们可能会有很多的Bean,这种做法是维护和更新所不能容许的。我们还可以在JSPs/Servlets中通过ServletRequest.setCharaterEncoding(String encoding)来设置,但在众多JSPs/Servlets中这么做也是件令人讨厌的事。最理想的办法是一劳永逸——只在一个地方进行编码和解码的处理,那就是在过滤器(Filter)中。我们只要在过滤器中对客户提交的数据正确解码了,就不用JSPs/Servlets/JavaBeans来操心了。我们的客户可能是大陆的,也可能是台湾省的,也就是说我们至少还得为区分GB2312和Big5来操心了,最理想的就是让它们提交上来的数据都是UTF-8编码的,那就不用决定decoding了,这里我们可以通过第四种方法来让服务器影响浏览器选择encoding,即设置响应头中的Content-Type,让所有的JSP和Servlet的响应实体的编码都是UTF-8,那么浏览器也就会选择我们所使用的UTF-8来编码提交的数据。

package filters;

import java.io.IOException;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

public class EncodingFilter implements Filter

{

private FilterConfig config;

private String defalutEncodeing;

public void init(FilterConfig config)

{

this.config = config;

defalutEncodeing = config.getInitParameter("encoding");

}

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException,ServletException

{

request.setCharacterEncoding(defalutEncodeing);

String uri = ((HttpServletRequest)request).getRequestURI();

if(uri.indexOf(".jsp") != -1 || uri.indexOf("servlet") != -1)

response.setContentType("text/html;charset=" + defalutEncodeing);

System.out.println("Filter set the encoding of the response to " +

response.getCharacterEncoding());

chain.doFilter(request, response);

}

public void destroy()

{

//...

}

}

在Context的web.xml中进行如下配置:

<filter>

<filter-name>Encoding Filter</filter-name>

<filter-class>filters.EncodingFilter</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>UTF-8</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>Encoding Filter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

可用一个test.jsp测试却发现,浏览器的输出并没有像我们预想的那样好,test.jsp源代码如下:

<%@ page pageEncoding="GBK"%>

<%String str = "在JSP中,编码已经被过滤器设置成:" + response.getCharacterEncoding();

System.out.println(str);%>

<%=str%>

它的输出如图3-3和图3-4,在客户端出现了乱码是没办法的事,因为通过服务器的输出我们可以发现在过滤器中,编码的确已经被设置成UTF-8,但在JSP中,编码又被设置成了ISO-8859-1。用过滤器对JSP编码设置失败,所以JSP的输出也失败了,我们看到了乱码。

图 3-3 对过滤器对JSP文件预设置编码失败

图 3-4 服务器输出说明在JSP中编码又被设置为ISO8859-1

但一段Servlet代码却证明了过滤器本来已经成功进行了设置。

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.ServletException;

import java.io.IOException;

import java.io.PrintWriter;

public class encoding extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

PrintWriter out = response.getWriter();

String str = "在Servlet中,编码是:" + response.getCharacterEncoding();

System.out.println(str);

out.println(str);

out.flush();

}

}

你可以在有过滤器和没有过滤器的情况下做实验,结果应该发现在有过滤器状态下,服务器端和客户端均正确得到了UTF-8的输出,在没有过滤器的状态下,服务器端正确输出编码为ISO-8859-1,客户端却输出了乱码,不管是JSP时的乱码还是无过滤器Servlet的乱码,这些都是可以理解的,因为当没有对JSP明确设置page的contentType指令,JSP引擎自动把它设置为ISO-8859-1,而用ISO-8859-1来编码中文,当然只有得到乱码了。

现在可以说利用过滤器来设置响应实体编码,以达到控制浏览器提交数据的编码的希望是没有意义了,没有谁会用Servlet来输出含Form的HTML页。但在过滤器中设置用户提交的数据的编码码还是有意义的。对于JSP我们还是可以妥协到在每个JSP中来定义contentType,也许在一JSP文件中定义contentType,而其他JSP文件对这个文件使用静态包含是可行的。

<%--encoding.jsp--%>

<%@ page contentType=”text/html;charset=UTF-8”%>

静态包含

<%--form.jsp--%>

<%@ page pageEncoding="GBK"%>

<%@ include file="encoding.jsp"%>

<%String name = request.getParameter("name");%>

<html>

<head>

<title>Form</title>

</head>

<body>

<form method="POST" action="test.jsp">

<label>请输入您的姓名</label>

<input type="text" name="name" size="20">

<input type="submit" value="提交">

</form>

<%if(name != null && !name.equals("")){

//%><p>您的姓名是:<%=name%></p><%

}%>

</body>

</html>

在这里,我们对客户提交的数据的解码是在过滤器Encoding Filter中完成的。form.jsp中的<%@ page pageEncoding="GBK"%>是不能省略到encoding.jsp中去,很明显它只对使用了它的JSP文件有效,而且不会在include指令中传递到包含文件中去的。

6. URI的中文字符串

通常情况下,我们都会尽力避免在URI(Uniform Resource Indentifier,统一资源标识符,定义在RFC2396中)中出现非英文字符,但不是所有的时候都能避免,而且这种避免可能加大我们的开发成本或运行效率。如果想直接用含中文的URL(Uniform Resource Locator,统一资源定位符,定义在RFC1738中,是URI的子集)对服务器上的Web资源进行访问,那是不行的。比如:

http://localhost/我是中国人.html

是不能访问到服务器上的“我是中国人.html”,因为浏览器(我使用的是MSIE6.0b)会无条件对该URL用UTF-8来编码:

http://localhost/%E6%88%91%E6%98%AF%E4%B8%AD%E5%9B%BD%E4%BA%BA.

html

而服务器却用系统缺省编码来解码这个URL,即相当于执行了

java.net.URLDecoder.decoder(url);

这个动作。不过这个方法已经不被赞成使用了(Deprecated),而应该使用新的方法

public String decode(String url, String charset)

服务器使用缺省的GBK来解码URI,而浏览器却很难做到使用GBK来编码URI,JavaScript中有三个用来编码URI的全局函数

l encodeURI(uri)

l encodeURIComponent(uri)

l escape(uri)

前面两个函数出现在IE5.5+中,它们用UTF-8来对参数uri编码,并返回编码的字符串;最后那个函数已经不被赞成使用了(Deprecated),它直接使用“%”加字符的Unicode内码来表示字符,如

escape(“我是中国人”)=%u6211%u662F%u4E2D%u56FD%u4EBA

这样,我们只好借助java.net.URLEncoder来编码URI了,如

<%-- encodeURL.jsp--%>

<%String file = “我是中国人.html”;

url = java.net.URLEncoder.encode(file, "GBK");%>

<a href=”<%=url%>”><%=file%></a>

这样,我们就实现了访问文件名中含中文字符的Web文件。其实这种即增加开发成本,又牺牲服务器效率的做法是没有多大意义的,没有谁会故意非用个中文文件名不可。

在HttpServletRequest中,请求查询字符串(通过方法getQueryString()获得)即不是URI(通过方法getRequestURI()获得)的一部份,也不是URL(通过方法getRequestURIL()获得)的一部份,服务器使用URLDecoder解码URL时,丝毫不对它产生影响,可以说它是被独处理的,而我们前面所使用的过滤器Encoding Filter里面的

request.setCharacterEncoding(defalutEncodeing);

却会对它产生影响。让我们来看一个实验,该实验加载了过滤器Encoding Filter:

<script>

//浏览不会自动编码查询字符串中的非英文字符

function encodingHref(obj)

{

obj.href = encodeURI(obj.href);

}

</script>

<a href="test.jsp?name=胡洲" onclick="encodingHref(this)">go</a>

test.jsp的源代码如下:

<%@ page contentType="text/html;charset=GBK"%>

pathInfo = <%=request.getPathInfo()%><br>

pathTranslated = <%=request.getPathTranslated()%><br>

contextPath = <%=request.getContextPath()%><br>

queryString = <%=request.getQueryString()%><br>

requestURI = <%=request.getRequestURI()%><br>

requestURL = <%=request.getRequestURL()%><br>

servletPath = <%=request.getServletPath()%><br>

name = <%=request.getParameter("name")%>

输出如图3-5:

图3-5

输出的结果是我们希望的。我们还可以在服务器端使用JSP代码:

<a href=”test.jsp?name=<%=URLEncoder.encode(“胡洲”, “UTF-8”)%>”>go</a>

事先编码好请求的URI,使用JavaScript代码编码查询字符串和使用JSP代码比起来,两者各有所长。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有