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

原创 2003年10月27日 02:10:00
 

5.        使用过滤器<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

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

       {

              //...

       }

}

Contextweb.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的输出也失败了,我们看到了乱码。

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />CSDN_Dev_Image_2003-10-241634470.png

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

CSDN_Dev_Image_2003-10-241634472.png

  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明确设置pagecontentType指令,JSP引擎自动把它设置为ISO-8859-1,而用ISO-8859-1来编码中文,当然只有得到乱码了。

现在可以说利用过滤器来设置响应实体编码,以达到控制浏览器提交数据的编码的希望是没有意义了,没有谁会用Servlet来输出含FormHTML页。但在过滤器中设置用户提交的数据的编码码还是有意义的。对于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的中文字符串

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

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

是不能访问到服务器上的“我是中国人.html”,因为浏览器(我使用的是MSIE6.0b)会无条件对该URLUTF-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来编码URIJavaScript中有三个用来编码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

CSDN_Dev_Image_2003-10-241634474.png

3-5

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

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

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

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

“与C/C++不同,Java中的字符数据是16位无符号型数据,它表示Unicode集,而不仅仅是ASCII集”①。这是一个很好的做法,它解决了www上更多的程序设计问题,比如说低成本的国际化(Inte...
  • whodsow
  • whodsow
  • 2003年10月27日 02:10
  • 1953

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

四、        国际化在前面第五小节中的form.jsp里,也许台湾省的客户更喜欢中的提示信息是“請輸入您的姓名”,而美国客户喜欢“Please input your name”,我们可以通过国际...
  • whodsow
  • whodsow
  • 2003年10月27日 02:10
  • 997

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

   三、        向服务器发送中文虽然大家一般都不用JSP甚至Servlet来处理处理客户提交的数据或访问请求参数,但JSP的使用或更新总是比Servlet或 JavaBean来得方便(至少在...
  • whodsow
  • whodsow
  • 2003年12月30日 10:11
  • 1003

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

   3.        Java文件与编码Java运用得如此广泛,以致于Java文件可能是采用任意一种字符编码的,如果不知道Java文件的编码标准是什么,就可能给我们的javac MyClass.j...
  • whodsow
  • whodsow
  • 2003年10月27日 02:10
  • 1315

怎样在J2EE组件中引用和查找Web服务

怎样在J2EE组件中引用和查找Web服务   作者:陈亚强  来源:http://www.java-cn.com本文将讨论怎么在J2EE组件中引用Web服务、并且通过JNDI来查找Web服务。在内容组...
  • tiewen
  • tiewen
  • 2005年08月05日 10:09
  • 1130

J2EE系列开发帮助文档/电子书籍/史上最全API集汇/开发必备工具

【文档资源一栏表】    【文档详细列表】                【友情提示】   在打开CHM/chm格式的文档的时候,如果您遇到如下情况:                不...
  • xh16319
  • xh16319
  • 2014年01月16日 19:12
  • 1263

J2EE--Servlet生命周期与原理

Servlet是在服务器上运行的小程序.而在java中应用程序多是在容器中进行生命周期的管理(这里指Tomact容器). Servlet基本的架构图   首先是  web页面通过提交表...
  • han_yankun2009
  • han_yankun2009
  • 2014年06月08日 16:27
  • 3722

J2EE 层次 模型 组件 服务

J2EE的层次结构         早期的网络系统设计常常采用三层结构。最常见的结构,就是表示( presentation )层 , 领域( domain )层 , 以及基础架构( infrastr...
  • liaoqianwen123
  • liaoqianwen123
  • 2014年03月10日 22:17
  • 2477

J2EE——XML

XML(Extensible Markup   Language)可扩展标记语言,这个基础知识在早些已经学习过,看我的这篇博客:XML基础介绍 。而这篇博客为什么把它放在J2EE下边呢,因为他也是J...
  • liujiahan629629
  • liujiahan629629
  • 2014年02月12日 22:53
  • 3254

升级java1.8及ssh版本中碰到的问题(三)

……再接前文 六、Not an managed type: class java.lang.Object。解决方法:自己定义的泛型非实现的Dao类前,加@NoRepositoryBean 这个是参考了...
  • YYZhQ
  • YYZhQ
  • 2016年04月07日 18:31
  • 535
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:J2EE Web组件中中文及相关的问题(四)
举报原因:
原因补充:

(最多只允许输入30个字)