随笔 - 81  文章 - 1033  trackbacks - 0
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

在浮躁的年代里,我们进取心太切,患得患失;虚荣心太强,战战兢兢。一心争强好胜,惟恐榜上无名。
I think I can fly , and flying like a bird !
程序员一名,已售出,缺货中!

我的邮件联系方式

用且仅用于MSN

博客点击率
free web counter
free web counter

常用链接

留言簿(36)

随笔档案

搜索

  •  

积分与排名

  • 积分 - 185617
  • 排名 - 308

最新评论

阅读排行榜

评论排行榜

      前两天刚发了一篇关于Resin3下Spring的启动问题的文章(在Resin3下配置SpringSide的HelloWorld示例程序碰到的问题和解决方法),我把持久层框架换成iBATIS后又出现了解析SqlMap文件的新问题,并且花了很长时间才找到解决方法(也可能是我了解的太少,还要加强修炼,呵呵),不管怎么样还是写出来和大家分享,希望对大家有所帮助。

      Struts+Spring+Hibernate是目前J2EE企业级开发绝对Killer级的框架组合,相当轻量,优雅,但毫不影响它的强大。虽然因为现在各种表示层框架发展异常活跃,Struts受到了前所未有的挑战和冲击,但是就目前使用面而言这三种框架的组合是JAVA程序员不得不深入的经典。他们相关的资料也比较多,实际运用中也最成熟。但是诸如JSF,iBATIS等后起之秀(说他们后起并不代表他们的历史,只是流行程度)也渐渐的占据自己的一席之地成为某些场合下开发的不二选择。在web服务器方面也是一样,除了Tomcat我们还有了更多好的选择(ResinJetty等)。虽然各种框架都声称自己可以无缝集成各种其他框架,不需要任何修改运行在各种服务器上面,但是我在我最近的一些经验发现把一些平时比较少组合在一起的东西放在一起后确实存在很多想不到的意外,排除起来也颇费一些周折。这可能也是开源和商业的差距,不完善的文档,没有足够覆盖面和严格的测试等,不过我们都要以一个宽容的态度对待开源,因为开源需要我们每个人的参与和贡献,从而真正达到Richard. M. Stallman心中的软件自由。

      我会不断的把在各种非常用的组合使用中遇到的的问题贴出来与大家分享,总有人会需要,呵呵。

      言归正传,今天的主题是在Resin3下使用Spring和iBATIS的组合开发时碰到的SqlMap文件解析问题,和开头提到的我的另一篇文章一样,也是一个xml配置文件的解析问题。使用的仍然是SpringSide的HelloWorld示例,这里顺便说个题外话SpringSide是一个我比较欣赏和推荐的国人自己打造的企业级快速开发框架,特别是他的wiki真是一个非常好的各种相关技术的学习资料,但是他发布的示例中含有不少的错误,特别是“非主流的”(非Tomcat下,iBATIS等)模式下有很多问题,希望SpringSide的大侠们能够更加完善。我是你们忠实的支持者。

      上篇文章  中提到了Resin3下使用Spring必须要更换默认的xml解析器,换成xerces后就可以正常启动了,然后把持久层框架由Hibernate换为iBATIS后又出现了新的问题,启动时一切正常,Spring和Struts的初始化都没有问题,但是当第一次需要连接数据库时就出现了问题,因为这个时候需要解析SqlMap文件来提供对应的Sql语句进行查询RDB,从异常信息来判断问题出在文件解析的时候,错误信息如下(因为很长,所以只贴了最底层的异常):

 1Caused by: 
 2org.xml.sax.SAXParseException: Content is not allowed in prolog.
 3    at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
 4    at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(Unknown Source)
 5    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
 6    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
 7    at org.apache.xerces.impl.XMLScanner.reportFatalError(Unknown Source)
 8    at org.apache.xerces.impl.XMLDocumentScannerImpl$PrologDispatcher.dispatch(Unknown Source)
 9    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
10    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
11    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
12    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
13    at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
14    at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
15    at com.ibatis.common.xml.NodeletParser.createDocument(NodeletParser.java:150)
16    at com.ibatis.common.xml.NodeletParser.parse(NodeletParser.java:50)
17    at com.ibatis.sqlmap.engine.builder.xml.SqlMapParser.parse(SqlMapParser.java:45)
18    at com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser$11.process(SqlMapConfigParser.java:347)
19    at com.ibatis.common.xml.NodeletParser.processNodelet(NodeletParser.java:112)
20    at com.ibatis.common.xml.NodeletParser.process(NodeletParser.java:75)
21    at com.ibatis.common.xml.NodeletParser.process(NodeletParser.java:93)
22    at com.ibatis.common.xml.NodeletParser.parse(NodeletParser.java:63)
23    at com.ibatis.common.xml.NodeletParser.parse(NodeletParser.java:51)
24    at com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser.parse(SqlMapConfigParser.java:78)
25    at com.ibatis.sqlmap.client.SqlMapClientBuilder.buildSqlMapClient(SqlMapClientBuilder.java:62)
26    at org.springframework.orm.ibatis.SqlMapClientFactoryBean.afterPropertiesSet(SqlMapClientFactoryBean.java:255)
27    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1062)
28    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1029)
29    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:420)
30    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:245)
31    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:141)
32    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:242)
33    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:156)
34    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(AbstractAutowireCapableBeanFactory.java:749)
35    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:704)
36    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:416)
37    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:245)
38    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:141)
39    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:242)
40    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:223)
41    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:156)
42    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(AbstractAutowireCapableBeanFactory.java:749)
43    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:704)
44    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:416)
45    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:245)
46    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:141)
47    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:242)
48    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
49    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:646)
50    at org.springframework.web.struts.DelegatingRequestProcessor.getDelegateAction(DelegatingRequestProcessor.java:168)
51    at org.springframework.web.struts.DelegatingRequestProcessor.processActionCreate(DelegatingRequestProcessor.java:146)
52    at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:230)
53    at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
54    at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
55    at javax.servlet.http.HttpServlet.service(HttpServlet.java:115)
56    at javax.servlet.http.HttpServlet.service(HttpServlet.java:92)
57    at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:106)
58    at org.extremecomponents.table.filter.AbstractExportFilter.doFilter(AbstractExportFilter.java:49)
59    at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
60    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:78)
61    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:77)
62    at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
63    at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:178)
64    at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:229)
65    at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:268)
66    at com.caucho.server.port.TcpConnection.run(TcpConnection.java:389)
67    at com.caucho.util.ThreadPool.runTasks(ThreadPool.java:507)
68    at com.caucho.util.ThreadPool.run(ThreadPool.java:433)
69    at java.lang.Thread.run(Thread.java:595)


      异常提示是Content is not allowed in prolog.意思就是说文件开头的时候有问题。。。我E文不好不能解释的“信,雅,达”,见谅,呵呵。还是跟我为了Spring而换上的xerces有关。。。狂晕,google了一番发现是一个叫BOM的东西搞的鬼,而xerces确实有BOM的问题,在Apache的论坛里看到一个帖子也提到xerces的BOM问题(可是借助灵格斯 一个单词一个单词翻译的看的。。。,顺便吐血推荐“灵格斯”,一款比金山词霸好用X倍速度快Y倍资源占用少Z倍的免费软件,注意是无插件,无广告,完全免费!!!金山现在为了反D版,所有装了D版金山的XP老是无缘无故死机,大家应该都很郁闷吧。被我推荐用灵格斯的人都说好,群众的眼睛是雪亮的啊。支持面向个人用户的软件免费!靠好质量好服务赚钱才是王道!!!),回帖是说换掉xerces用其他解析器,可是我不能换,换了Spring还指望它呢,我也不知道换成什么比它更好。。。,还有的说给xerces的如果是stream就可以接受BOM,如果是reader就不行(我默认大家都对JAVA的IO有一定了解能够理解stream和reader啊),难道我跑去把iBATIS里的源代码改了,然后重新编译???这样也不好吧,总有简单点的方式解决吧。

      于是继续google,随着对BOM进一步的了解发现把SqlMap文件里的BOM给删除调应该是最快最方便的方式,因为BOM在UTF-8里面并不起什么作用,本来是可有可无的。下面先让大家对BOM有个大概的认识(细节可以参考官方网站 ),然后告诉大家怎么样快捷的删掉文件里的BOM。

      我们这里提到的BOM并不是制造业管理中料表(Bill of Material)的概念,而是UCS(Unicode的学名是"Universal Multiple-Octet Coded Character Set",简称为UCS)编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。这样如果接收者收到FEFF,就表明这个字节流是Big-Endian(big endian和little endian是CPU处理多字节数的不同方式。例如“汉”字的Unicode编码是6C49。那么写到文件里时,究竟是将6C写在前面,还是将49写在前面?如果将6C写在前面,就是big endian。还是将49写在前面,就是little endian。我们一般将endian翻译成“字节序”,将big endian和little endian称作“大尾”和“小尾”。)的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。

      UTF-8是以8位为单位来表示UCS,其实不存在什么尾序的问题,其实BOM是没有什么作用的,不过可以用BOM来表示编码方式,字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB BF,所以如果接受到以EF BB BF开头的字节流就可以判断是UTF-8编码了。

      如果上面提到的一些名词你不是很清楚可以google一下,找到相关的解释。追根究底是个好习惯。如果对BOM的概念还不清楚或者想了解更多也可以搜索相关资料来研究。

      下面重点来说一下怎么去掉BOM:
      首先windows自带的记事本会在保存UTF-8编码的文件时不管是否含有BOM一律加上BOM,所以千万别用记事本。我的程序跑不起来也是因为用记事本打开过。。。有段时间非常流行的“联通”问题就是跟windows记事本处理BOM的机制有关,就是把“联通”两字写进记事本保存后再打开时就会是黑点。。。如果你有兴趣可以到网上找到相关文章详细解释给你听,呵呵。

      比较新版本的UltraEdit(以下简称UE,大家都是这么叫的)都对BOM支持比较好,所以推荐使用新版本的UE来解决这个问题。我用的版本是UltraEdit-32 10.20d+中文版(网上可以下的到,如果你比较懒可以联系我,留下邮箱,呵呵)。首先打开UE,选择菜单栏“高级”-“配置”,出现一个选项卡窗口,在“常规”选项卡中找到“保存时对所有UTF-8文件头标记(BOM)”和“对在UltraEdit里创建的新文件写入UTF-8文件头标记(如上面)”,把它们的复选框都取消不选,然后确定。这个时候UE默认情况下就不会对没有BOM的文件加入BOM,注意如果不执行上述操作UE默认也是会加的!那已经含有BOM的文件如何清除BOM呢?下面演示给大家。首先打开文件,选择菜单栏“文件”-“格式转换”-“UTF-8 转 ASCII”,这样文件会被转为ASCII编码,BOM就不会存在了,因为上面说过BOM是在UCS编码的头部的,然后再选择菜单栏“文件”-“格式转换”-“ASCII 转 UTF-8(Unicode编辑)”,这个时候文件会被转回为UTF-8编码,因为我们上面选了不自动加BOM,所以这个时候的文件是不带BOM的,然后保存文件。整个操作过程就完毕了。(如果仍然有什么疑问给我留言吧)

      我去掉BOM后重新启动服务器,访问数据库一切正常,问题果然解决了。当然在我碰到的这个问题中干脆把文件转成ASCII直接用也可以,汗!不知道为什么,请大家指教!
posted on 2007-01-28 00:24 cresposhi 阅读(3036) 评论(14)  编辑  收藏

FeedBack:
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2007-01-30 17:37 梅颖
怎么没有人回复你啊,造也,我来沙发一哈  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2007-01-30 20:21 施伟
呵呵,没关系,我是写给能欣赏的人看。比如说老婆你啊  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2007-01-31 09:12 梅颖
呵呵我也看不懂列,呵呵主要是你写的洒,我就来关照一下,免得没有人气洒,哈哈  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2007-01-31 21:01 施伟
呵呵,多谢多谢  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2007-02-02 12:04 小祝
写的不错,我欣赏,其实我也看不懂,呵呵.  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2007-02-02 12:15 梅颖
啊,呵呵原来不只我一个  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2007-02-02 20:37 施伟
我越是学习越觉得不懂的东西多
大家都要努力提高自己啊  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2007-03-06 20:18 crazyld
太好了。
看到这篇文章,帮我解决的一个问。
嗷嗷感谢!  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2007-03-19 21:58 maurice
thanks  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2007-10-07 11:57 qixoo.com 企讯网--5000万企业速查|求职参考|企业点评|企业从业者与企业的桥梁
企讯网创立于2005年10月,创办之初,受到了众多企业从业者的鼎立支持。但在创办网站的过程中我们也经历了重重磨难,并且因为某些原因,网站曾于2007年1月到6月期间停办。直到2007年7月,企讯网重新开办,并且拥有新域名www.qixoo.com 与 www.qixoo.net 。

企讯网是一个沟通平台。我们建立本站的初衷是为了建立企业从业者与企业的桥梁,使得员工能与企业更好的沟通,我们希望员工能在此平台为企业提出一些好的发展建议,同时企业也能倾听员工的声音,为员工创造一个更好的环境。

企讯网是一个参考平台。通过本站,可以帮助企业人员在求职过程中能有一个参考,并且查询相关的企业信息,以便企业人员能找到符合自身发展的企业。当然,本站的参考信息都是由网友添加,我们不可能验证每一条信息的可靠性,对于部分企业的评价,也许会比较片面和失实。大家在求职过程中,还是应以实际出发,毕竟这里只代表部分声音。

企讯网是一个监督平台。诚然,作为一个普普通通的网站并没有资格与权利去监督一个企业的行为。但作为一个网络媒体,虽然还是那么的微小,但我们希望能通过网络的声音能改变一些企业不恰当的做法,哪怕只是一点点。我们期望能有一个良好的企业大环境,以利于我们国家企业业的发展。


  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2008-02-23 23:47 蕲春人
为什么我使用resin3.0,我的struts1.2采用自定义映射,就是将.do改成其它的,
访问action,发生404错误.

如果你知道问题的解决办法,可否告诉我?
我的邮箱是boy.365@126.com

我的网站是20zone.cn
就是由于在resin上的这个问题,导致网站不能进一步开发啊.
  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2008-10-13 14:00 neusoft_fool
我看懂拉 谢谢  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法 2009-02-20 16:30 jan.yan
按照你的转了 怎么还不行呢?  回复  更多评论
  
# re: Resin3下Spring+iBATIS组合SqlMap文件解析错误的问题和解决方法[未登录] 2010-07-05 13:54 nothing

---
首先windows自带的记事本会在保存UTF-8编码的文件时不管是否含有BOM一律加上BOM,所以千万别用记事本。我的程序跑不起来也是因为用记事本打开过。。。
---

如果一开始你的编码方式保存没有包含BOM,你用记事本打开修改编译是不会对编码方式有影响的,所以请不要说 "所以千万别用记事本"  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: