Rory's Blog
          Happy study,Happy work,Happy life
          posts - 22,  comments - 46,  trackbacks - 0
          xstream是個(gè)好東西。對(duì)于配置文件的讀取很方便。在mybog中我就用到了。不過(guò)今天打算用yupoo的api來(lái)做相冊(cè)。發(fā)現(xiàn)xstream對(duì)于xmlnode的attribute解析支持不是那么的好。
          對(duì)于這種節(jié)點(diǎn)格式的非常的簡(jiǎn)單
          <result>
          ????
          <page>1</page>
          ????
          <pages>1</pages>
          ????
          <perpage>100</perpage>
          ????
          <total>19</total>
          ????
          <photos>
          ????????
          <photo>
          ????????????
          <id>ff8080810fc8ac78010fd3f158d40a52</id>
          ????????????
          <owner>ff8080810f1a387b010f1a83d6530dfc</owner>
          ????????????
          <title>Gmail-2</title>
          ????????????
          <host>4</host>
          ????????????
          <dir>20061230</dir>
          ????????????
          <filename>231905_1463411198</filename>
          ????????
          </photo>
          ????
          </photos>
          </result>

          簡(jiǎn)單的alias一下就可以讀到值了
          File?file?=?new?File("src/test/java/com/jdkcn/test/result.xml");
          BufferedReader?reader?
          =?new?BufferedReader(new?InputStreamReader(new?FileInputStream(file),?"UTF-8"));
          XStream?stream?
          =?new?XStream();
          stream.alias(
          "result",?YupooResult.class);
          stream.alias(
          "photo",YupooPhoto.class);
          YupooResult?result?
          =?(YupooResult)stream.fromXML(reader);
          可是Yupoo的api返回的xmlrpc的結(jié)果是這樣的
          <result?page="1"?pages="1"?perpage="100"?total="19">
          ????
          <photos>
          ????????
          <photo?id="ff8080810fc8ac78010fd3f158d40a52"
          ????????????owner
          ="ff8080810f1a387b010f1a83d6530dfc"?title="Gmail-2"?host="4"
          ????????????dir
          ="20061230"?filename="231905_1463411198"?/>
          ????
          </photos>
          </result>
          這樣就load不到值了。沒(méi)法去mailist里面找答案,果然有人問(wèn)。
          Hello,
          
          I am not sure about the subject but here is what I needed help for:
          
          XML:
          
          <field name="value">I am a Field.</field>
          
          I have already tried several structures and nothing seem to work.
          
          Is this possible for XStream? :)
          
          How is the Java class form to support this?
          
          Thanks!




          有人回答是看Converter的文檔。果然找到答案了。
          自己寫(xiě)一個(gè)converter就可以了。
          下面是我的converter
          package?com.jdkcn.xstream;

          import?java.util.ArrayList;
          import?java.util.List;

          import?com.jdkcn.yupoo.YupooPhoto;
          import?com.jdkcn.yupoo.YupooResult;
          import?com.thoughtworks.xstream.converters.Converter;
          import?com.thoughtworks.xstream.converters.MarshallingContext;
          import?com.thoughtworks.xstream.converters.UnmarshallingContext;
          import?com.thoughtworks.xstream.io.HierarchicalStreamReader;
          import?com.thoughtworks.xstream.io.HierarchicalStreamWriter;

          /**
          ?*?
          @author?<a?href="mailto:rory.cn@gmail.com">somebody</a>
          ?*?
          @since?Jan?16,?2007?6:12:35?PM
          ?*?
          @version?$Id?YupooResultConverter.java$
          ?
          */
          public?class?YupooResultConverter?implements?Converter?{
          ????
          /*?(non-Javadoc)
          ?????*?@see?com.thoughtworks.xstream.converters.Converter#marshal(java.lang.Object,?com.thoughtworks.xstream.io.HierarchicalStreamWriter,?com.thoughtworks.xstream.converters.MarshallingContext)
          ?????
          */
          ????
          public?void?marshal(Object?obj,?HierarchicalStreamWriter?writer,?MarshallingContext?context)?{
          ????????
          //?FIXME?unfinish.
          ????}

          ????
          /*?(non-Javadoc)
          ?????*?@see?com.thoughtworks.xstream.converters.Converter#unmarshal(com.thoughtworks.xstream.io.HierarchicalStreamReader,?com.thoughtworks.xstream.converters.UnmarshallingContext)
          ?????
          */
          ????
          public?Object?unmarshal(HierarchicalStreamReader?reader,?UnmarshallingContext?context)?{
          ????????YupooResult?result?
          =?new?YupooResult();
          ????????result.setPage(
          new?Integer(reader.getAttribute("page")));
          ????????result.setPages(
          new?Integer(reader.getAttribute("pages")));
          ????????result.setPerpage(
          new?Integer(reader.getAttribute("perpage")));
          ????????result.setTotal(
          new?Integer(reader.getAttribute("total")));
          ????????reader.moveDown();
          ????????List
          <YupooPhoto>?photos?=?new?ArrayList<YupooPhoto>();
          ????????
          while(reader.hasMoreChildren())?{
          ????????????reader.moveDown();
          ????????????YupooPhoto?photo?
          =?new?YupooPhoto();
          ????????????photo.setDir(reader.getAttribute(
          "dir"));
          ????????????photo.setFilename(reader.getAttribute(
          "filename"));
          ????????????photo.setHost(reader.getAttribute(
          "host"));
          ????????????photo.setId(reader.getAttribute(
          "id"));
          ????????????photo.setOwner(reader.getAttribute(
          "owner"));
          ????????????photo.setTitle(reader.getAttribute(
          "title"));
          ????????????photos.add(photo);
          ????????????reader.moveUp();
          ????????}
          ????????result.setPhotos(photos);
          ????????
          return?result;
          ????}
          ????
          /*?(non-Javadoc)
          ?????*?@see?com.thoughtworks.xstream.converters.ConverterMatcher#canConvert(java.lang.Class)
          ?????
          */
          ????
          public?boolean?canConvert(Class?clazz)?{
          ????????
          return?clazz.equals(YupooResult.class);
          ????}
          }

          然后調(diào)用的地方修改一下就ok了。
          XStream?stream?=?new?XStream();
          stream.registerConverter(
          new?YupooResultConverter());
          stream.alias(
          "result",?YupooResult.class);



          參考:
          http://xstream.codehaus.org/converter-tutorial.html

          2007年1月18日更新。
          這里感謝網(wǎng)友 Ivan Chen(西濱)?的提示。原來(lái)新版的xstream可以簡(jiǎn)單的解決了。在1.2.1的doc里面找到了這個(gè)兩個(gè)方法。

          useAttributeFor

          public void useAttributeFor(java.lang.String?fieldName,
                                      java.lang.Class?type)
          Use an XML attribute for a field or a specific type.

          Parameters:
          fieldName - the name of the field
          type - the Class of the type to be rendered as XML attribute
          Throws:
          XStream.InitializationException - if no AttributeMapper is available
          Since:
          1.2

          useAttributeFor

          public void useAttributeFor(java.lang.Class?type)
          Use an XML attribute for an arbotrary type.

          Parameters:
          type - the Class of the type to be rendered as XML attribute
          Throws:
          XStream.InitializationException - if no AttributeMapper is available
          Since:
          1.2

          這兩個(gè)方法都是從1.2開(kāi)始支持的。
          也不用自己寫(xiě)converter了。這樣就可以了
          ????????stream.alias("result",?YupooResult.class);
          ????????stream.useAttributeFor(
          "page",?Integer.class);
          ????????stream.useAttributeFor(
          "pages",?Integer.class);
          ????????stream.useAttributeFor(
          "perpage",?Integer.class);
          ????????stream.useAttributeFor(
          "total",?Integer.class);
          ????????stream.alias(
          "photo",?YupooPhoto.class);
          ????????stream.useAttributeFor(
          "id",?String.class);
          ????????stream.useAttributeFor(
          "owner",?String.class);
          ????????stream.useAttributeFor(
          "title",?String.class);
          ????????stream.useAttributeFor(
          "host",?String.class);
          ????????stream.useAttributeFor(
          "dir",?String.class);
          ????????stream.useAttributeFor(
          "filename",?String.class);

          創(chuàng)造共用協(xié)議:署名,非商業(yè),保持一致
          ?? 除經(jīng)特別注明外,本文章版權(quán)歸莫多泡泡所有.
          署名,非商業(yè)用途,保持一致.???somebody(莫多)
          posted @ 2007-01-17 18:24 莫多 閱讀(8008) | 評(píng)論 (2)編輯 收藏

          ? 上周更新了一下myblog,添加了一個(gè)Filter,做統(tǒng)計(jì)訪問(wèn)用。可是后來(lái)發(fā)現(xiàn)出現(xiàn)亂碼問(wèn)題了。找了很久都沒(méi)有找到問(wèn)題。debug的時(shí)候看到 CharacterEncodingFilter確實(shí)是執(zhí)行了。不過(guò)就是沒(méi)有效果。執(zhí)行之前是ISO-8859-1編碼的,執(zhí)行之后還是, CharacterEncodingFilter就沒(méi)有起到作用。后來(lái)終于找到問(wèn)題的原因了。原來(lái)是Filter配置先后順序的原因。
          ?????? 剛開(kāi)始的配置是這樣的:

          ???? < filter-mapping >
          ????????
          < filter-name > requestCounterFilter </ filter-name >
          ????????
          < url-pattern > *.jhtml </ url-pattern >
          ????
          </ filter-mapping >
          ??
          ????
          < filter-mapping >
          ????????
          < filter-name > encodingFilter </ filter-name >
          ????????
          < url-pattern > /dwr/* </ url-pattern >
          ????
          </ filter-mapping >
          ????
          ????
          < filter-mapping >
          ????????
          < filter-name > encodingFilter </ filter-name >
          ????????
          < url-pattern > *.jhtml </ url-pattern >
          ????
          </ filter-mapping >
          ????
          ????
          < filter-mapping >
          ????????
          < filter-name > encodingFilter </ filter-name >
          ????????
          < url-pattern > *.jsp </ url-pattern >
          ????
          </ filter-mapping >

          ? 先經(jīng)過(guò)那個(gè)統(tǒng)計(jì)的filter然后再經(jīng)過(guò)編碼的filter。這樣的話編碼的filter就不起作用了。只要吧編碼的filter放到最前面就沒(méi)有問(wèn)題了。改成這樣就好。

          ???? < filter-mapping >
          ????????
          < filter-name > encodingFilter </ filter-name >
          ????????
          < url-pattern > /dwr/* </ url-pattern >
          ????
          </ filter-mapping >
          ????
          ????
          < filter-mapping >
          ????????
          < filter-name > encodingFilter </ filter-name >
          ????????
          < url-pattern > *.jhtml </ url-pattern >
          ????
          </ filter-mapping >
          ????
          ????
          < filter-mapping >
          ????????
          < filter-name > encodingFilter </ filter-name >
          ????????
          < url-pattern > *.jsp </ url-pattern >
          ????
          </ filter-mapping >
          ????
          ????
          < filter-mapping >
          ????????
          < filter-name > requestCounterFilter </ filter-name >
          ????????
          < url-pattern > *.jhtml </ url-pattern >
          ????
          </ filter-mapping >


          以后大家一定要注意啊。順序問(wèn)題也是很重要的。
          創(chuàng)造共用協(xié)議:署名,非商業(yè),保持一致?? 除經(jīng)特別注明外,本文章版權(quán)歸莫多泡泡所有.
          署名,非商業(yè)用途,保持一致.???somebody(莫多)

          posted @ 2006-12-27 10:37 莫多 閱讀(2700) | 評(píng)論 (3)編輯 收藏
          昨天晚上配置myblog的rewrite。發(fā)現(xiàn)一個(gè)奇怪的問(wèn)題。由于現(xiàn)在使用的這個(gè)pjblog,為了讓搜索引擎收錄的連接有效。我想把原來(lái)的asp連接rewrite到我的新程序上面。所以有這樣一條規(guī)則。

          ????<rule>
          ????????
          <from>^/article.asp\?id=(.*)$</from>
          ????????
          <to?type="redirect">/entry/$1.jhtml</to>
          ????
          </rule>
          ???? 但是我這樣的連接總是匹配不到,只要去掉那個(gè)?就可以了。這個(gè)正則表達(dá)式是沒(méi)有問(wèn)題的。/article.asp?id=64是可以匹配的到的。
          ??? 后來(lái)看3.0的manual (http://tuckey.org/urlrewrite/manual/3.0/)才發(fā)現(xiàn)原來(lái)是這個(gè)的問(wèn)題。

          <urlrewrite> element

          The top level element.

          AttributePossible ValueExplanation
          default-match-type
          (optional)
          regex (default)All rules and thier conditions will be processed using the Java Regular Expression engine (unless match-type is specified on a rule).
          wildcardAll rules and thier conditions will be processed using the Wildcard Expression engine (unless match-type is specified on a rule).
          decode-using
          (optional)
          utf8 (default)When URL is decoded UTF-8 will be used.
          nullDo not decode.
          [encoding]Any string representing a supported character encoding eg, ISO-8859-1. See Java Charset Object for more info.
          use-query-string
          (optional)
          false (default)The query string will not be appended to the url that the "from" element matches against.
          trueThe query string will be appended to the url that the "from" element matches against.
          use-context
          (optional)
          false (default)The context path will not be added to the url that the "from" element matches against.
          trueThe context path will be added to the url that the "from" element matches against.

          就是那個(gè)use-query-string 的問(wèn)題,默認(rèn)的是不使用query-string就是把?后面的都忽略了。所以就不能匹配到了。只要在<urlrewrite>里面加一個(gè)屬性就可以了。
          <urlrewrite?use-query-string="true">
          ????
          </urlrewrite>

          創(chuàng)造共用協(xié)議:署名,非商業(yè),保持一致?? 除經(jīng)特別注明外,本文章版權(quán)歸莫多泡泡所有.
          署名,非商業(yè)用途,保持一致.???somebody(莫多)

          posted @ 2006-12-12 10:33 莫多 閱讀(2355) | 評(píng)論 (0)編輯 收藏

          ??????我們的項(xiàng)目用到了xmlrpc,不過(guò)還是用的2.x版本的。由于xmlrpc3.x地推出。提供了NULL,Serializable等的支持,將原來(lái)的Hashtable改成了Map,Vector改成了List。都是不錯(cuò)的進(jìn)步。所以我們決定從xmlrpc2.x升級(jí)到xmlrpc3.x.
          ??????在spring里面有幾個(gè)ServiceExporter,org.springframework.remoting.rmi.RmiServiceExporter、org.springframework.remoting.caucho.HessianServiceExporter、org.springframework.remoting.caucho.BurlapServiceExporter。不過(guò)沒(méi)有xmlrpc的serviceExporter,原來(lái)我們是自己封裝的XmlRpcServer,用servlet提供服務(wù)。(eg:http://localhost:8080/community/service/xmlrpc)沒(méi)有和spring集成雖然用了spring。
          ??? 考慮到spring的便利以及配置的同意我決定將xmlrpcService放入spring中。xmlrpc3.x和xmlrpc2.x的代碼基本上沒(méi)有一樣的。改了很多東西。除了類(lèi)型變化之外,還添加了對(duì)異常的支持。詳細(xì)信息請(qǐng)參照xmlrpc3.x源代碼。
          XmlRpcServiceExporter.java

          package ?com.jdkcn.xmlrpc;

          import ?javax.servlet.ServletException;

          /**
          ?*?
          @author ?<a?href="mailto:rory.cn@gmail.com">somebody</a>
          ?*?
          @since ?2006-9-27?03:59:22?pm
          ?*?
          @version ?$Id?XmlRpcServiceExporter.java$
          ?
          */
          public ? class ?XmlRpcServiceExporter? extends ?RemoteExporter? implements
          ????????Controller,?InitializingBean?{
          ????
          ????
          private ?XmlRpcServletServer?server;
          ????
          ????
          public ?String?serviceName;
          ????
          ????
          public ?Resource?configFile;
          ????
          ????
          public ?Boolean?enabledForExtensions;
          ????
          ????
          public ? void ?setEnabledForExtensions(Boolean?enabledForExtensions)?{
          ????????
          this .enabledForExtensions? = ?enabledForExtensions;
          ????}

          ????
          public ? void ?setConfigFile(Resource?configFile)?{
          ????????
          this .configFile? = ?configFile;
          ????}

          ????
          public ?String?getServiceName()?{
          ????????
          return ?serviceName;
          ????}

          ????
          public ? void ?setServiceName(String?serviceName)?{
          ????????
          this .serviceName? = ?serviceName;
          ????}

          ????
          public ?XmlRpcServletServer?getXmlRpcServletServer()?{
          ????????
          return ?server;
          ????}
          ????
          ????
          /* ?(non-Javadoc)
          ?????*?@see?org.springframework.web.servlet.mvc.Controller#handleRequest(javax.servlet.http.HttpServletRequest,?javax.servlet.http.HttpServletResponse)
          ?????
          */
          ????
          public ?ModelAndView?handleRequest(HttpServletRequest?request,
          ????????????HttpServletResponse?response)?
          throws ?Exception?{
          ????????
          if ?( ! WebContentGenerator.METHOD_POST.equals(request.getMethod()))?{
          ????????????
          throw ? new ?ServletException( " XmlRpcServiceExporter?only?supports?POST?requests " );
          ????????}
          ????????server.execute(request,?response);
          ????????
          return ? null ;
          ????}

          ????
          /* ?(non-Javadoc)
          ?????*?@see?org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
          ?????
          */
          ????
          public ? void ?afterPropertiesSet()? throws ?Exception?{
          ????????server?
          = ? new ?XmlRpcServletServer();
          ????????server.setHandlerMapping(newXmlRpcHandlerMapping());
          ????????
          if ?(enabledForExtensions != null )?{
          ????????????((XmlRpcServerConfigImpl)?server.getConfig()).setEnabledForExtensions(enabledForExtensions.booleanValue());
          ????????}
          ????????
          ????}

          ????
          /** ?Creates?a?new?handler?mapping.?The?default?implementation?loads
          ?????*?a?property?file?from?the?resource
          ?????*?
          ?????
          */
          ????
          protected ?XmlRpcHandlerMapping?newXmlRpcHandlerMapping()? throws ?XmlRpcException?{
          ????????
          ????????SpringHandlerMapping?mapping?
          = ? new ?SpringHandlerMapping(getServiceInterface());
          ????????mapping.addHandler(getServiceName(),?getServiceInterface());
          ????????mapping.setTagetObject(getProxyForService());
          ????????
          return ?mapping;
          ????}
          ????
          }

          spring配置文件
          ????<bean?id="accountService"??class="com.jdkcn.service.impl.AccountServiceImpl">
          ????
          </bean>
          ????????
          <bean?name="rpcAccountService"?class="com.jdkcn.xmlrpc.XmlRpcServiceExporter">
          ????????
          <property?name="service">
          ????????????
          <ref?bean="accountService"/>
          ????????
          </property>
          ????????
          <property?name="serviceName">
          ????????????
          <value>jdkcn.accountService</value>
          ????????
          </property>
          ????????
          <property?name="enabledForExtensions">
          ????????????
          <value>true</value>
          ????????
          </property>
          ????????
          <property?name="serviceInterface">
          ????????????
          <value>com.jdkcn.service.AccountService</value>
          ????????
          </property>
          ????
          </bean>
          然后映射一個(gè)地址就可以通過(guò)xmlrpc訪問(wèn)服務(wù)了
          ????<bean?id="urlMapping"?class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
          ????????
          <property?name="mappings">
          ????????????
          <props>?
          ????????????????
          <prop?key="/account">rpcAccountService</prop>
          ????????????
          </props>
          ????????
          </property>
          ????
          </bean>
          web.xml
          ????<context-param>
          ????????
          <param-name>contextConfigLocation</param-name>
          ????????
          <param-value>
          ????????????classpath:spring/global.xml
          ????????
          </param-value>
          ????
          </context-param>
          ????
          ????
          <listener>
          ????????
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
          ????
          </listener>

          ????????
          <servlet>
          ????????????
          <servlet-name>service</servlet-name>
          ????????????
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          ????????
          </servlet>

          ????????
          <servlet-mapping>
          ????????????
          <servlet-name>service</servlet-name>
          ????????????
          <url-pattern>/service/xmlrpc3/*</url-pattern>
          ????????
          </servlet-mapping>
          然后我們的service地址就是這樣的http://localhost:8080/service/xmlrpc3/account

          希望對(duì)大家有用,這里提供project下載。包含一個(gè)client程序。com.jdkcn.xmlrpc.Client

          點(diǎn)擊下載完整代碼

          創(chuàng)造共用協(xié)議:署名,非商業(yè),保持一致?? 除經(jīng)特別注明外,本文章版權(quán)歸莫多泡泡所有.
          署名,非商業(yè)用途,保持一致.???somebody(莫多)
          posted @ 2006-10-22 16:12 莫多 閱讀(2192) | 評(píng)論 (0)編輯 收藏
          不知道大家有沒(méi)有碰到,還是沒(méi)有這種需求。就是用like來(lái)查詢,我們沒(méi)有用Lucene,Compass這種全文索引的方案,我們只是簡(jiǎn)單的添加%進(jìn)行l(wèi)ike查詢。用戶搜索的時(shí)候就使用*和?來(lái)代表任意和一個(gè)。所以要對(duì)"%"和"_"進(jìn)行轉(zhuǎn)義,我們使用的是oracle數(shù)據(jù)庫(kù)。sql語(yǔ)句看起來(lái)可能是這樣的。
          SELECT?*?FROM?t_user?where?nickname?like?'%Goo\_D'?escape?'\'
          這里對(duì)_進(jìn)行轉(zhuǎn)義了。因?yàn)橛脩絷欠Q(chēng)包含下劃線,如果不進(jìn)行轉(zhuǎn)義就表示一個(gè)任意字符。有時(shí)候我們可能還需要對(duì)%進(jìn)行轉(zhuǎn)義。同樣的方法在%前加\% 但是比起普通的like語(yǔ)句。多了一個(gè)聲明轉(zhuǎn)義符的語(yǔ)句。所以我們會(huì)想到這樣的語(yǔ)句
          DetachedCriteria?criteria?=?DetachedCriteria.forClass(User.class);
          criteria.add(Restrictions.like(
          "nickname",?user.getNickname()+"'?escape'\"));
          但是這樣是不管用的。
          接下來(lái)可能會(huì)想到使用Hibernate3的原生sql查詢,其實(shí)我們不需要這樣做。我們還是使用Criteria條件查詢。
          criteria.add(Restrictions.sqlRestriction("{alias}.nickname?like???escape'/'",?StringUtil.escapeSQLLike(user.getNickname()),?Hibernate.STRING));
          這樣Hibernate產(chǎn)生的語(yǔ)句就是我們想要的語(yǔ)句了。
          ????/**
          ?????*?轉(zhuǎn)義like語(yǔ)句中的
          ?????*?<code>'_'</code><code>'%'</code>
          ?????*?將<code>'?'</code>轉(zhuǎn)成sql的<code>'/_'</code>
          ?????*?將<code>'%'</code>轉(zhuǎn)成sql的<code>'/%'</code>
          ?????*?<p>
          ?????*???例如搜索<code>?aa*bb?c_d%f</code>將轉(zhuǎn)化成<br/>
          ?????*???<code>_aa%bb_c/_d/%f</code>
          ?????*?</p>
          ?????*?
          @param?likeStr
          ?????*?
          @return
          ?????*?
          @author?<a?href="http://jdkcn.com">somebody</a>
          ?????
          */
          ????
          public?static?String?escapeSQLLike(String?likeStr)?{
          ????????String?str?
          =?StringUtils.replace(likeStr,?"_",?"/_");
          ????????str?
          =?StringUtils.replace(str,?"%",????"/%");
          ????????str?
          =?StringUtils.replace(str,?"?",?"_");
          ????????str?
          =?StringUtils.replace(str,?"*",?"%");
          ????????
          return?str;
          ????}

          創(chuàng)造共用協(xié)議:署名,非商業(yè),保持一致?? 除經(jīng)特別注明外,本文章版權(quán)歸莫多泡泡所有.
          署名,非商業(yè)用途,保持一致.???somebody(莫多)
          posted @ 2006-10-16 23:29 莫多 閱讀(2502) | 評(píng)論 (1)編輯 收藏

          ? jspark 的這篇文章《開(kāi)發(fā)階段eclipse下面的spring容器的啟動(dòng)優(yōu)化 》講到如何加快spring的啟動(dòng)速度。非常感謝jspark. 一下是引用的原文:

          ? 最近在負(fù)責(zé)一個(gè)大項(xiàng)目,項(xiàng)目組成員包括項(xiàng)目經(jīng)理大概10個(gè)人左右。項(xiàng)目技術(shù)用struts+spring+hibernate實(shí)現(xiàn)。項(xiàng)目的規(guī)模相對(duì)來(lái)說(shuō)是比較大的,總共有10大模塊,每個(gè)大模塊又分為有十幾個(gè)、甚至幾十個(gè)小模塊。開(kāi)發(fā)工具用eclipse,由于在開(kāi)發(fā)階段,項(xiàng)目開(kāi)發(fā)成員需要頻繁重啟服務(wù)器。在啟動(dòng)服務(wù)器的時(shí)候,每次啟動(dòng)時(shí)間總是會(huì)超過(guò)1分鐘。記得以前在做另外一個(gè)項(xiàng)目時(shí),啟動(dòng)時(shí)間不到5秒鐘,相差了10倍,而且項(xiàng)目規(guī)模是差不多的。

          ??? 從初步分析來(lái)說(shuō),應(yīng)該是hibernate解釋hbm.xml時(shí)花費(fèi)時(shí)間,或者可能是spring容器啟動(dòng)并解釋所有的bean配置文件。診斷了一下,發(fā)現(xiàn)1分鐘消耗的時(shí)間主要分布在hibernate解釋hbm.xml花費(fèi)5秒;spring容器從啟動(dòng)到解釋bean配置文件竟然花了58秒,真是太囂張了。當(dāng)時(shí)非常懷疑spring的效率問(wèn)題。企圖從網(wǎng)上搜索相關(guān)資料,看看有什么優(yōu)化措施。

          ??? 首先是找到了hibernate的啟動(dòng)優(yōu)化 http://www.hibernate.org/194.html? 里面的主要思想是通過(guò)將xml序列花到本地的文件里,每次讀取的時(shí)候根據(jù)情況,從本地文件讀取并反序列化,節(jié)省了hibernate xml的解析時(shí)間。按照這個(gè)方式測(cè)試了一下,發(fā)現(xiàn)hibernate的啟動(dòng)時(shí)間從5秒降低到3秒,但是這個(gè)優(yōu)化對(duì)于整個(gè)啟動(dòng)過(guò)程是杯水車(chē)薪的,毫無(wú)用處。

          ??? 沒(méi)辦法,又仔細(xì)查看了spring的資料,終于發(fā)現(xiàn)spring的容器是提供了lazy-load的,即默認(rèn)的缺省設(shè)置是bean沒(méi)有l(wèi)azy- load,該屬性處于false狀態(tài),這樣導(dǎo)致spring在啟動(dòng)過(guò)程導(dǎo)致在啟動(dòng)時(shí)候,會(huì)默認(rèn)加載整個(gè)對(duì)象實(shí)例圖,從初始化ACTION配置、到 service配置到dao配置、乃至到數(shù)據(jù)庫(kù)連接、事務(wù)等等。這么龐大的規(guī)模,難怪spring的啟動(dòng)時(shí)間要花將近1分鐘。嘗試了一下,把beans的 default-lazy-init改為true就,再次啟動(dòng),速度從原來(lái)的55秒,降到8秒鐘!!Great!雖然是非常小一個(gè)改動(dòng),但是影響確實(shí)非常大。一個(gè)項(xiàng)目組10個(gè)人,假若每個(gè)人一天平均需要在eclipse下啟動(dòng)測(cè)試服務(wù)器50次。那么一天項(xiàng)目組需要重啟500次,每次節(jié)省50秒的話,就是 25000秒,將近幾個(gè)小時(shí),差不多一個(gè)工作日,多么可觀的數(shù)字!

          ?? 不過(guò)在運(yùn)行期間第一次點(diǎn)頁(yè)面的時(shí)候,由于spring做了lazy-load,現(xiàn)在就需要啟動(dòng)一部分需要的beans,所以稍微慢2-3秒鐘,但是明顯比等幾十秒要快很多,值得一鑒。

          ??? 以上是針對(duì)開(kāi)發(fā)階段的spring容器啟動(dòng)優(yōu)化,在部署到實(shí)際環(huán)境中,倒是沒(méi)必要設(shè)置為lazy-load。畢竟部署到實(shí)際環(huán)境中不是經(jīng)常的事,每次啟動(dòng)1分鐘倒不是大問(wèn)題。

          我這里要提醒的是不是說(shuō)有的beans都能設(shè)置default-lazy-init成為true.對(duì)于scheduler的bean不能用lazy-init

          < beans? default-lazy-init ="true" >
          ????
          ????
          < bean? class ="org.springframework.scheduling.quartz.SchedulerFactoryBean" >
          ????????
          < property? name ="triggers" >
          ????????????
          < list >
          ????????????????
          < ref? bean ="buildHtmlTrigger" />
          ????????????????
          < ref? bean ="askTrigger" />
          ????????????????
          < ref? bean ="mailSenderTrigger" />
          ????????????????
          < ref? bean ="topicDetailBuildTrigger" />
          ????????????????
          < ref? bean ="forumBuildTrigger" />
          ????????????????
          < ref? bean ="topicBuildTrigger" />
          ????????????
          </ list >
          ????????
          </ property >
          ????
          </ bean >
          </ beans >




          這樣的話。所有的scheduler就都不管用了。所以請(qǐng)大家要注意。

          < beans >
          ????
          ????
          < bean? class ="org.springframework.scheduling.quartz.SchedulerFactoryBean" >
          ????????
          < property? name ="triggers" >
          ????????????
          < list >
          ????????????????
          < ref? bean ="buildHtmlTrigger" />
          ????????????????
          < ref? bean ="askTrigger" />
          ????????????????
          < ref? bean ="mailSenderTrigger" />
          ????????????????
          < ref? bean ="topicDetailBuildTrigger" />
          ????????????????
          < ref? bean ="forumBuildTrigger" />
          ????????????????
          < ref? bean ="topicBuildTrigger" />
          ????????????
          </ list >
          ????????
          </ property >
          ????
          </ bean >
          </ beans >


          ?

          posted @ 2006-08-10 10:59 莫多 閱讀(3329) | 評(píng)論 (2)編輯 收藏

          ???? 雖然項(xiàng)目全部采用了UTF-8編碼,所有的源文件*.java,*.jsc,*.html,*.ftl都采用了UTF-8編碼。可是還是出現(xiàn)了亂碼問(wèn)題。很是不爽,后來(lái)找到了tomcat,和resin的配置。

          1. Tomcat的配置。(conf/server.xml)
            ????<!--?Define?a?non-SSL?HTTP/1.1?Connector?on?port?8080?-->
            ????
            <Connector?port="80"?maxHttpHeaderSize="8192"
            ???????????????maxThreads
            ="150"?minSpareThreads="25"?maxSpareThreads="75"
            ???????????????enableLookups
            ="false"?redirectPort="8443"?acceptCount="100"
            ???????????????connectionTimeout
            ="20000"?disableUploadTimeout="true"?URIEncoding="UTF-8"/>
          2. Resin的配置。(conf/resin.conf)

            character-encoding

            Resin 1.1
            child of: resin, server, host-default, host, web-app-default, web-app
            default: The default value is ISO-8859-1.

            Specifies the default character encoding for the environment.

            <web-app id='/'>
              <character-encoding>shift_jis</character-encoding>
              ...
            
            </web-app>
            

          ???? 這個(gè)是resin doc里面的我是在web-app-default里面加上了encoding的配置

          ???? < web-app-default >
          ??????
          < character-encoding > UTF-8 </ character-encoding >
          ??????
          ????
          </ web-app-default >

          希望對(duì)你的項(xiàng)目有幫助。

          創(chuàng)造共用協(xié)議:署名,非商業(yè),保持一致 ?? 除經(jīng)特別注明外,本文章版權(quán)歸莫多泡泡所有.
          署名,非商業(yè)用途,保持一致.???somebody(莫多)??

          posted @ 2006-07-22 18:13 莫多 閱讀(1857) | 評(píng)論 (4)編輯 收藏
          項(xiàng)目中多個(gè)項(xiàng)目需要同時(shí)引用一個(gè)靜態(tài)資源,所以就想到配置不同的虛擬目錄指到同一個(gè)目錄。于是有下面的配置:
          ????<!--?configures?the?default?host,?matching?any?host?name?-->
          ????
          <host?id=""?root-directory=".">
          ??????
          <!--
          ?????????-?configures?an?explicit?root?web-app?matching?the
          ?????????-?webapp's?ROOT
          ????????
          -->
          ??????
          <web-app?id="/"?document-directory="webapps/ROOT"/>
          ??????
          <web-app?id="/community/jsvm2"?document-directory="D:\\projects\\FelooComponents\\jsvm2"/>
          ??????
          <web-app?id="/passport/jsvm2"?document-directory="D:\\projects\\FelooComponents\\jsvm2"/>
          ????
          </host>

          ?????? 但是發(fā)現(xiàn)這樣只有后面一個(gè)管用(http://localhost:8080/passport/jsvm2)這個(gè)是可以,可是(http://localhost:8080/community/jsvm2)就不行,很是郁悶。只要后面的document-directory不是同一個(gè)目錄就成。
          ?????? 后來(lái)在resin的doc里面看到path的配置

          path-mapping

          child of: web-app-default, web-app

          Maps url patterns to real paths. If using a server like IIS, you may need to match the server's path aliases.

          AttributeMeaningdefault
          url-patternA pattern matching the url: /foo/*, /foo, or *.foo
          url-regexpA regular expression matching the url
          real-pathThe prefix of the real path. When used with url-regexp, allows substitution variables like $1.

          <web-app id='/'>
                      <path-mapping url-pattern='/resin/*'
                      real-path='e:\resin'/>
                      <path-mapping url-regexp='/~([^/]*)'
                      real-path='e:\home$1'/>
                      </web-app>
                      

          改正這樣的配置就ok了。

          ????????<web-app?id="/community"?document-directory="D:\\projects\\FelooCommunityWeb">
          ??????????
          <path-mapping?url-pattern='jsvm2/*'
          ??????????????
          real-path='D:\\projects\\FelooComponents\\jsvm2'/>
          ??????
          </web-app>
          ??????
          ????????????
          <web-app?id="/passport"?document-directory="D:\\projects\\FelooPassportWeb">
          ??????????
          <path-mapping?url-pattern='jsvm2/*'
          ??????????????
          real-path='D:\\projects\\FelooComponents\\jsvm2'/>
          ??????
          </web-app>
          創(chuàng)造共用協(xié)議:署名,非商業(yè),保持一致?? 除經(jīng)特別注明外,本文章版權(quán)歸莫多泡泡所有.
          署名,非商業(yè)用途,保持一致.???somebody(莫多)
          posted @ 2006-07-18 19:41 莫多 閱讀(2910) | 評(píng)論 (0)編輯 收藏

          自從換工作之后就沒(méi)有研究過(guò)DWR了。下載了最新的DWR2.0M2版本。2.0加了很多東西,也有不少變化的地方。最容易看到的變化就是包名的變化了,由 uk.ltd.getahead 變成了 org.directwebremoting
          ?????? ?換上了新的配置

          ???? < servlet >
          ????????
          < servlet-name > dwr-invoker </ servlet-name >
          ????????
          < servlet-class > org.directwebremoting.servlet.DwrServlet </ servlet-class >
          ????????
          < init-param >
          ??????????
          < param-name > debug </ param-name >
          ??????????
          < param-value > true </ param-value >
          ????????
          </ init-param >
          ????????
          < load-on-startup > 1 </ load-on-startup >
          ????
          </ servlet >

          啟動(dòng)服務(wù),抱錯(cuò)了。

          java.lang.IllegalArgumentException: DefaultContainer can't find a classes
          ? ? ? ?at org.directwebremoting.impl.DefaultContainer.getBean(DefaultContainer.java:216)
          ? ? ? ?at org.directwebremoting.annotations.AnnotationsConfigurator.configure(AnnotationsConfigurator.java:50)
          ? ? ? ?at org.directwebremoting.servlet.DwrServlet.init(DwrServlet.java:121)

          ????? 在DWR的Maillist里面搜索了一下,還有答案,原來(lái)DWR2.0 加入了JDK5的注釋(annotations).DwrServlet初始化的時(shí)候會(huì)去檢查注釋的類(lèi),找不到就抱錯(cuò)了。如果你不用annotations也可以忽略掉這個(gè)錯(cuò)誤。不過(guò)看起來(lái)總是不爽。有人提出了方案。這樣就ok了。

          ???? < servlet >
          ????????
          < servlet-name > dwr-invoker </ servlet-name >
          ????????
          < servlet-class > org.directwebremoting.servlet.DwrServlet </ servlet-class >
          ????????
          < init-param >
          ??????????
          < param-name > debug </ param-name >
          ??????????
          < param-value > true </ param-value >
          ????????
          </ init-param >
          ????????
          < init-param >
          ???????????
          < param-name > classes </ param-name >
          ???????????
          < param-value > java.lang.Object </ param-value >
          ????????
          </ init-param >
          ????????
          < load-on-startup > 100 </ load-on-startup >
          ????
          </ servlet >

          創(chuàng)造共用協(xié)議:署名,非商業(yè),保持一致 ?? 除經(jīng)特別注明外,本文章版權(quán)歸莫多泡泡所有.
          署名,非商業(yè)用途,保持一致.???somebody(莫多)??

          posted @ 2006-07-17 02:11 莫多 閱讀(2886) | 評(píng)論 (0)編輯 收藏
          首先感謝JScud提供的好文章。《使用FreeMarker生成Html靜態(tài)文件(實(shí)例)
          ????? 在我們的項(xiàng)目中也用到了Freemarker生成靜態(tài)文件。不過(guò)這里我要說(shuō)的是編碼的問(wèn)題。我們的項(xiàng)目使用的都是UTF-8編碼,我直接使用 飛云小俠 提供的方法生成的文件在UTF-8編碼下察看是亂碼,而GBK正常(后來(lái)發(fā)現(xiàn)因?yàn)槲矣玫闹形牟僮飨到y(tǒng)所以用GBK查看正常)。
          ????? 當(dāng)然我把Freemarker的配置都改成了UTF-8,我的模版文件也是UTF-8編碼的。下面是原來(lái)的代碼
          ????public?void?setTemplatePath(Resource?templatePath)?{
          ????????
          this.templatePath?=?templatePath;
          ????????
          //設(shè)置freemarker的參數(shù)
          ????????freemarkerCfg?=?new?Configuration();
          ????????
          try?{
          ????????????freemarkerCfg.setDirectoryForTemplateLoading(
          this.templatePath.getFile());
          ????????????freemarkerCfg.setObjectWrapper(
          new?DefaultObjectWrapper());
          ????????????freemarkerCfg.setDefaultEncoding(
          "UTF-8");
          ????????}?
          catch?(IOException?ex)?{
          ????????????
          throw?new?SystemException("No?Directory?found,please?check?you?config.");
          ????????}
          ????}
          ????/**
          ?????*?生成靜態(tài)文件
          ?????*?
          @param?templateFileName?模版名稱(chēng)eg:(biz/order.ftl)
          ?????*?
          @param?propMap?用于處理模板的屬性O(shè)bject映射?
          ?????*?
          @param?htmlFilePath?要生成的靜態(tài)文件的路徑,相對(duì)設(shè)置中的根路徑,例如?"/biz/2006/5/"?
          ?????*?
          @param?htmlFileName?要生成的文件名,例如?"123.htm"?
          ?????*?
          @return
          ?????
          */
          ????
          private?boolean?buildHtml(String?templateFileName,Map?propMap,?String?htmlFilePath,String?htmlFileName){
          ????????
          try?{
          ????????????Template?template?
          =?freemarkerCfg.getTemplate(templateFileName);
          ????????????template.setEncoding(
          "UTF-8");
          ????????????
          //創(chuàng)建生成文件目錄
          ????????????creatDirs(buildPath.getFilename(),htmlFilePath);
          ????????????File?htmlFile?
          =?new?File(buildPath?+?htmlFilePath?+?htmlFileName);
          ????????????Writer?out?
          =?new?BufferedWriter(new?OutputStreamWriter(new?FileOutputStream(htmlFile)));
          ????????????template.process(propMap,out);
          ????????????out.flush();
          ????????????
          return?true;
          ????????}?
          catch?(TemplateException?ex){
          ????????????log.error(
          "Build?Error"+templateFileName,ex);
          ????????????
          return?false;
          ????????}?
          catch?(IOException?e)?{
          ????????????log.error(
          "Build?Error"+templateFileName,e);
          ????????????
          return?false;
          ????????}
          ????????
          ????}
          下面是修改之后的代碼
          ????/**
          ?????*?生成靜態(tài)文件
          ?????*?
          @param?templateFileName?模版名稱(chēng)eg:(biz/order.ftl)
          ?????*?
          @param?propMap?用于處理模板的屬性O(shè)bject映射?
          ?????*?
          @param?htmlFilePath?要生成的靜態(tài)文件的路徑,相對(duì)設(shè)置中的根路徑,例如?"/biz/2006/5/"?
          ?????*?
          @param?htmlFileName?要生成的文件名,例如?"123.htm"?
          ?????*?
          @return
          ?????
          */
          ????
          private?boolean?buildHtml(String?templateFileName,Map?propMap,?String?htmlFilePath,String?htmlFileName){
          ????????
          try?{
          ????????????Template?template?
          =?freemarkerCfg.getTemplate(templateFileName);
          ????????????template.setEncoding(
          "UTF-8");
          ????????????
          //創(chuàng)建生成文件目錄
          ????????????creatDirs(buildPath.getFilename(),htmlFilePath);
          ????????????File?htmlFile?
          =?new?File(buildPath?+?htmlFilePath?+?htmlFileName);
          ????????????Writer?out?
          =?new?BufferedWriter(new?OutputStreamWriter(new?FileOutputStream(htmlFile),"UTF-8"));
          ????????????template.process(propMap,out);
          ????????????out.flush();
          ????????????
          return?true;
          ????????}?
          catch?(TemplateException?ex){
          ????????????log.error(
          "Build?Error"+templateFileName,ex);
          ????????????
          return?false;
          ????????}?
          catch?(IOException?e)?{
          ????????????log.error(
          "Build?Error"+templateFileName,e);
          ????????????
          return?false;
          ????????}
          ????????
          ????}
          原因就在于OutputStreamWriter的不同構(gòu)造方法

          OutputStreamWriter(OutputStream?out)
          ??????????創(chuàng)建使用默認(rèn)字符編碼的 OutputStreamWriter。
          OutputStreamWriter(OutputStream?out, String?charsetName)
          ??????????創(chuàng)建使用指定字符集的 OutputStreamWriter。

          ?
          這個(gè)是中文JDK的文檔說(shuō)明,剛開(kāi)始我使用默認(rèn)的構(gòu)造函數(shù),所以使用了系統(tǒng)默認(rèn)的編碼,GBK,所以在生成靜態(tài)文件的時(shí)候把UTF-8內(nèi)容用GBK編碼寫(xiě)入了,所以在UTF-8下瀏覽就有問(wèn)題。

          還有關(guān)于修改模版文件同樣也要注意這個(gè)問(wèn)題。
          ????public?String?loadTemplate(String?templateName)?{
          ????????StringBuffer?sb?
          =?new?StringBuffer();
          ????????
          try?{
          ????????????File?file?
          =?new?File(templatePath+"/"+templateName);
          ????????????BufferedReader?reader?
          =?new?BufferedReader(new?InputStreamReader(new?FileInputStream(file),"UTF-8"));
          ????????????String?line?
          =?reader.readLine();
          ????????????
          while(line?!=?null)????{
          ????????????????sb.append(line);
          ????????????????sb.append(
          "\r\n");
          ????????????????line?
          =?reader.readLine();
          ????????????}
          ????????????reader.close();
          ????????}?
          catch?(IOException?e)?{
          ????????????
          throw?new?SystemException("Loading?template?Error:",e);
          ????????}
          ????????
          return?sb.toString();
          ????}
          ????public?void?saveTemplate(String?templateName,?String?templateContent)?{
          ????????
          try?{
          ????????????File?file?
          =?new?File(templatePath?+?"/"?+?templateName);
          ????????????Writer?out?
          =?new?BufferedWriter(new?OutputStreamWriter(new?FileOutputStream(file),"UTF-8"));
          ????????????out.write(templateContent);
          ????????????out.flush();
          ????????????
          //扔出templatesave事件
          ????????????TemplateSaveEvent?evt?=?new?TemplateSaveEvent();
          ????????????evt.setTemplateName(templateName);
          ????????????dispatchTemplateEvent(evt);
          ????????}?
          catch?(IOException?e)?{
          ????????????
          throw?new?SystemException("Write?template?Error",e);
          ????????}
          ????}

          posted @ 2006-06-21 10:46 莫多 閱讀(2870) | 評(píng)論 (0)編輯 收藏
          在以前的項(xiàng)目中對(duì)于一些資源的配置基本上都是通過(guò)spring的IOC注入一個(gè)目錄的地址字符串。而這樣的問(wèn)題是,對(duì)于開(kāi)發(fā)中的團(tuán)隊(duì)來(lái)說(shuō)還是很有問(wèn)題的,因?yàn)槊總€(gè)可能都配置一個(gè)不同的本地目錄,而發(fā)布到服務(wù)器之后又有不同的目錄。這樣造成每個(gè)人提交了配置文件之后其他人都可能需要修改配置文件才能正確啟動(dòng)服務(wù)。這確實(shí)很令人煩勞。
          ???? 最近看《Professional Java Development with the Spring Framework》時(shí)看到了spring對(duì)底層資源的抽象,才找到了完美解決方案。
          ???? 原來(lái)的代碼:
          ????private?String?templatePath;
          ????
          public?void?setTemplatePath(String?templatePath)?{
          ????????
          this.templatePath?=?templatePath;
          ????}
          ????
          public?void?initListener()?{
          ????????TemplateEventListener?templateListener?
          =?new?TemplateEventListener(){
          ????????????
          public?void?handleTemplateEvent(TemplateEventSupport?evt)?{
          ????????????????
          //?添加事件到隊(duì)列中
          ????????????????queue.offer(evt);
          ????????????????
          if(log.isDebugEnabled()){
          ????????????????????log.debug(
          "Add?Template?about:"?+?evt.getTemplateName());
          ????????????????}
          ????????????}
          ????????????
          ????????};
          ????????
          ????????
          //注冊(cè)模版監(jiān)聽(tīng)事件
          ????????templateManager.addEventListener(Constants.TEMPLATE_SAVE_EVENT,?templateListener,false);
          ????????
          ????????
          ????????
          //設(shè)置freemarker的參數(shù)
          ????????freemarkerCfg?=?new?Configuration();
          ????????
          try?{
          ????????????freemarkerCfg.setDirectoryForTemplateLoading(
          new?File(templatePath));
          ????????????freemarkerCfg.setObjectWrapper(
          new?DefaultObjectWrapper());
          ????????????freemarkerCfg.setDefaultEncoding(
          "UTF-8");
          ????????}?
          catch?(IOException?ex)?{
          ????????????
          throw?new?SystemException("No?Directory?found,please?check?you?config.");
          ????????}
          ????}
          配置文件

          ????
          <bean?id="buildHtmlService"?class="cn.jdk.leaf.service.impl.BuildHtmlServiceImpl"?init-method="initListener">
          ????????
          <property?name="templatePath"><value>${templatePath}</value></property>
          ????
          </bean>
          templatePath.path=D:/template
          使用spring對(duì)底層資源的抽象只要把templatePath改成Resource就可以了
          ????private?Resource?templatePath;
          ????
          public?void?setTemplatePath(Resource?templatePath)?{
          ????????
          this.templatePath?=?templatePath;
          ????}
          ????
          public?void?initListener()?{
          ????????????TemplateEventListener?templateListener?
          =?new?TemplateEventListener(){
          ????????????
          public?void?handleTemplateEvent(TemplateEventSupport?evt)?{
          ????????????????
          //?添加事件到隊(duì)列中
          ????????????????queue.offer(evt);
          ????????????????
          if(log.isDebugEnabled()){
          ????????????????????log.debug(
          "Add?Template?about:"?+?evt.getTemplateName());
          ????????????????}
          ????????????}
          ????????????
          ????????};????
          ????????
          //注冊(cè)模版監(jiān)聽(tīng)事件
          ????????templateManager.addEventListener(Constants.TEMPLATE_SAVE_EVENT,?templateListener,false);
          ????????
          ????????
          ????????
          //設(shè)置freemarker的參數(shù)
          ????????freemarkerCfg?=?new?Configuration();
          ????????
          try?{
          ????????????freemarkerCfg.setDirectoryForTemplateLoading(templatePath.getFile());
          ????????????freemarkerCfg.setObjectWrapper(
          new?DefaultObjectWrapper());
          ????????????freemarkerCfg.setDefaultEncoding(
          "UTF-8");
          ????????}?
          catch?(IOException?ex)?{
          ????????????
          throw?new?SystemException("No?Directory?found,please?check?you?config.");
          ????????}
          ????}
          bean的配置不變,只要修改properties文件就可以了。
          ????<bean?id="buildHtmlService"?class="cn.jdk.leaf.service.impl.BuildHtmlServiceImpl"?init-method="initListener">
          ????????
          <property?name="templatePath"><value>${templatePath}</value></property>
          ????
          </bean>
          把properties文件修改成
          templatePath.path=template
          在webcontext目錄下面建立一個(gè)template目錄就可以了。在部署到服務(wù)器的時(shí)候需要部署到一個(gè)特定的目錄只要修改這個(gè)配置文件為
          templatePath.path=file:/D:/template
          這樣就可以了。

          創(chuàng)造共用協(xié)議:署名,非商業(yè),保持一致??除經(jīng)特別注明外,本文章版權(quán)歸莫多泡泡所有.
          署名,非商業(yè)用途,保持一致.???somebody(莫多)???
          posted @ 2006-06-11 23:01 莫多 閱讀(1879) | 評(píng)論 (2)編輯 收藏
          上篇文章:《今天發(fā)現(xiàn)一個(gè)hibernate的bug,或者說(shuō)一個(gè)應(yīng)該注意的地方比較合適 》里面我提到了Hibernate查詢需要注意的一個(gè)問(wèn)題。今天發(fā)現(xiàn)了一個(gè)最好的解決辦法。如果大家現(xiàn)在用Hibernate,相信大家都回用到DetachedCriteria.關(guān)于DetachedCriteria查詢請(qǐng)查看http://dev.yesky.com/241/2033241.shtml
          ????? DetachedCriteria給我們的Hibernate查詢帶來(lái)了很多方便,但是如果你帶上排序信息就會(huì)出現(xiàn)我的上一篇文章里面說(shuō)的那種錯(cuò)誤,今天發(fā)現(xiàn)一個(gè)很好的解決方法,其實(shí)也很簡(jiǎn)單。就是先把傳入的帶Order信息的DetachedCriteria去掉order信息查詢數(shù)據(jù)總條數(shù),然后再把Order加回來(lái)查詢滿足條件的對(duì)象。通過(guò)查看Hibernate的源代碼發(fā)現(xiàn)Criteria的實(shí)現(xiàn)CriteriaImpl發(fā)現(xiàn)其實(shí)addOrder是給private List orderEntries = new ArrayList();這個(gè)List加值。這個(gè)List里面放的是OrderEntry對(duì)象。這個(gè)OrderEntry里面放了一個(gè)criteria 和 order.

          ????
          ????public?PaginationSupport?findPageByCriteria(final?DetachedCriteria?detachedCriteria,?final?int?pageSize,?final?int?startIndex)?{
          ????????
          return?(PaginationSupport)?getHibernateTemplate().execute(new?HibernateCallback()?{
          ????????????
          public?Object?doInHibernate(Session?session)?throws?HibernateException?{
          ????????????????Criteria?criteria?
          =?detachedCriteria.getExecutableCriteria(session);
          ????????????????CriteriaImpl?impl?
          =?(CriteriaImpl)?criteria;
          ????????????????List?orderEntrys?
          =?new?ArrayList();
          ????????????????
          try{
          ????????????????????Field?field?
          =?CriteriaImpl.class.getDeclaredField("orderEntries");
          ????????????????????
          //Get?orders
          ????????????????????orderEntrys?=?(List)?field.get(impl);
          ????????????????????
          //Remove?orders
          ????????????????????field.set(criteria,new?ArrayList());
          ????????????????}
          catch(Exception?ex){
          ????????????????????ex.printStackTrace();
          ????????????????????
          //TODO?xxxx
          ????????????????}
          ????????????????
          int?totalCount?=?((Integer)?criteria.setProjection(Projections.rowCount())
          ????????????????????????.uniqueResult()).intValue();
          ????????????????criteria.setProjection(
          null);
          ????????????????
          ????????????????
          try{
          ????????????????????Field?field?
          =?CriteriaImpl.class.getDeclaredField("orderEntries");
          ????????????????????
          //Add?orders?return
          ????????????????????for(int?i=0;?i<orderEntrys.size();?i++){
          ????????????????????????List?innerOrderEntries?
          =?(List)?field.get(criteria);
          ????????????????????????innerOrderEntries.add(orderEntrys.get(i));
          ????????????????????}
          ????????????????}
          catch(Exception?ex){
          ????????????????????ex.printStackTrace();
          ????????????????????
          //TODO?cccc
          ????????????????}
          ????????????????List?items?
          =?criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();
          ????????????????PaginationSupport?ps?
          =?new?PaginationSupport(items,?totalCount,?pageSize,
          ????????????????????????startIndex);
          ????????????????
          return?ps;
          ????????????}
          ????????},?
          true);
          ????}
          希望大家多多交流
          posted @ 2006-05-29 23:29 莫多 閱讀(5064) | 評(píng)論 (12)編輯 收藏
          現(xiàn)在的系統(tǒng)中雖然使用了。Hibernate但是沒(méi)有使用Hibernate的關(guān)聯(lián)關(guān)系來(lái)進(jìn)行數(shù)據(jù)庫(kù)操作。所有的管理操作都是單獨(dú)實(shí)現(xiàn)的。所以也不能用Criteria.add()這種方式去查詢關(guān)聯(lián)的一方。所以只能用Native SQL去查詢結(jié)果返回對(duì)象了。按照Hibernate3的reference里面說(shuō)的

          16.1.?使用SQLQuery

          對(duì)原生SQL查詢執(zhí)行的控制是通過(guò)SQLQuery接口進(jìn)行的,通過(guò)執(zhí)行Session.createSQLQuery()獲取這個(gè)接口。最簡(jiǎn)單的情況下,我們可以采用以下形式:

          List cats = sess.createSQLQuery("select * from cats")
              .addEntity(Cat.class)
              .list();

          這個(gè)查詢指定了:

          • SQL查詢字符串

          • 查詢返回的實(shí)體

          這里,結(jié)果集字段名被假設(shè)為與映射文件中指明的字段名相同。對(duì)于連接了多個(gè)表的查詢,這就可能造成問(wèn)題,因?yàn)榭赡茉诙鄠€(gè)表中出現(xiàn)同樣名字的字段。下面的方法就可以避免字段名重復(fù)的問(wèn)題:

          List cats = sess.createSQLQuery("select {cat.*} from cats cat")
              .addEntity("cat", Cat.class)
              .list();

          這個(gè)查詢指定了:

          • SQL查詢語(yǔ)句,它帶一個(gè)占位符,可以讓Hibernate使用字段的別名.

          • 查詢返回的實(shí)體,和它的SQL表的別名.

          addEntity()方法將SQL表的別名和實(shí)體類(lèi)聯(lián)系起來(lái),并且確定查詢結(jié)果集的形態(tài)。

          addJoin()方法可以被用于載入其他的實(shí)體和集合的關(guān)聯(lián).

          List cats = sess.createSQLQuery(
                  "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
              )
              .addEntity("cat", Cat.class)
              .addJoin("kitten", "cat.kittens")
              .list();

          原生的SQL查詢可能返回一個(gè)簡(jiǎn)單的標(biāo)量值或者一個(gè)標(biāo)量和實(shí)體的結(jié)合體。

          Double max = (Double) sess.createSQLQuery("select max(cat.weight) as maxWeight from cats cat")
                  .addScalar("maxWeight", Hibernate.DOUBLE);
                  .uniqueResult();

          除此之外,你還可以在你的hbm文件中描述結(jié)果集映射信息,在查詢中使用。

          List cats = sess.createSQLQuery(
                  "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
              )
              .setResultSetMapping("catAndKitten")
              .list();

          后來(lái)我使用了命名SQL查詢方式。

          16.3.?命名SQL查詢

          可以在映射文檔中定義查詢的名字,然后就可以象調(diào)用一個(gè)命名的HQL查詢一樣直接調(diào)用命名SQL查詢.在這種情況下,我們 需要調(diào)用addEntity()方法.

          <sql-query name="persons">
              <return alias="person" class="eg.Person"/>
              SELECT person.NAME AS {person.name},
                     person.AGE AS {person.age},
                     person.SEX AS {person.sex}
              FROM PERSON person
              WHERE person.NAME LIKE :namePattern
          </sql-query>
          List people = sess.getNamedQuery("persons")
              .setString("namePattern", namePattern)
              .setMaxResults(50)
              .list();

          我覺(jué)得這種發(fā)式比較好。這樣寫(xiě)出來(lái)的sql可以很整齊。我們的數(shù)據(jù)庫(kù)使用的是oracle,不過(guò)按照這上面的寫(xiě)法發(fā)現(xiàn)sql語(yǔ)句有錯(cuò)誤。
          后來(lái)拿到控制臺(tái)執(zhí)行也抱錯(cuò)。因?yàn)樵瓉?lái)都用sqlserver,而sqlserver都是可以的。后來(lái)發(fā)現(xiàn)是表不能有別名改成這樣就好了。
          ????????????SELECT?T_PAY.sys_id?as?{pay.sysId},
          ???????????????????T_PAY.sys_flag?
          as?{pay.sysFlag},
          ???????????????????T_PAY.sys_domain?
          as?{pay.sysDomain},
          ???????????????????T_PAY.sys_owner?
          as?{pay.sysOwner},
          ???????????????????T_PAY.sys_create_date?
          as?{pay.sysCreateDate},
          ???????????????????T_PAY.sys_update_date?
          as?{pay.sysUpdateDate},
          ???????????????????T_PAY.pay_id?
          as?{pay.payId},
          ???????????????????T_PAY.pay_name?
          as?{pay.payName},
          ???????????????????T_PAY.pay_type_id?
          as?{pay.payTypeId},
          ???????????????????T_PAY.pay_date?
          as?{pay.payDate},
          ???????????????????T_PAY.money_type_id?
          as?{pay.moneyTypeId},
          ???????????????????T_PAY.amount?
          as?{pay.amount},
          ???????????????????T_PAY.payer_id?
          as?{pay.payerId},
          ???????????????????T_PAY.payer_name?
          as?{pay.payerName},
          ???????????????????T_PAY.accept_id?
          as?{pay.acceptId},
          ???????????????????T_PAY.accept_name?
          as?{pay.acceptName},
          ???????????????????T_PAY.pay_state_id?
          as?{pay.payStateId},
          ???????????????????T_PAY.remark?
          as?{pay.remark}
          ????????????
          FROM???T_PAY
          ????????????
          JOIN???T_BIZ_PAY
          ????????????
          ON???????T_PAY.pay_id?=?T_BIZ_PAY.pay_id
          ????????????
          WHERE??T_BIZ_PAY.biz_id?=?:bizId
          ? 這里要特別的提醒一下大家千萬(wàn)不要把主鍵忘了。剛開(kāi)始我就忘了主鍵,后來(lái)調(diào)試了半天才找出原因來(lái)。

          這樣在sping里面用回調(diào)查詢一下就ok了。真的很方便.
          ????public?List?getPaysByBizId(final?String?bizId)?{
          ????????
          return?(List)getHibernateTemplate().execute(new?HibernateCallback(){
          ????????????
          public?Object?doInHibernate(Session?session)throws?HibernateException{
          ????????????????Query?query?
          =?session.getNamedQuery("find.pays.by.bizid");
          ????????????????query.setParameter(
          "bizId",bizId);
          ????????????????
          return?query.list();
          ????????????}
          ????????},
          true);
          ????}
          posted @ 2006-05-26 10:33 莫多 閱讀(3792) | 評(píng)論 (0)編輯 收藏
          今天把myblog用sql server部署了一下,可是發(fā)現(xiàn)分頁(yè)查詢的時(shí)候出現(xiàn)錯(cuò)誤,看控制臺(tái)報(bào)錯(cuò)說(shuō)語(yǔ)句有錯(cuò),由來(lái)發(fā)現(xiàn)分頁(yè)的時(shí)候先查詢總記錄數(shù)目的那條語(yǔ)句出錯(cuò)了
          select?count(*)?as?y0_?from?myblog_Blog?this_?inner?join?myblog_Blog_Category?categories3_?on?this_.id=categories3_.blogId?inner?join?myblog_Category?category1_?on?categories3_.categoryId=category1_.id?where?category1_.id=??order?by?this_.postTime?desc
          ????? 原來(lái)開(kāi)發(fā)的時(shí)候我是用的mysql,沒(méi)有任何問(wèn)題。原因就在最后面的order by 語(yǔ)句,sql server 在select count(*)里面不能用 order by。然后跟蹤代碼發(fā)現(xiàn):
          ????public?PaginationSupport?getBlogsByCategoryByPage(final?String?categoryId,?final?int?startIndex,?final?int?pageSize)?{
          ????????
          return?(PaginationSupport)?getHibernateTemplate().execute(new?HibernateCallback()?{
          ????????????
          public?Object?doInHibernate(Session?session)?throws?HibernateException?{
          ????????????????Criteria?criteria?
          =?session.createCriteria(Blog.class);
          ????????????????Criteria?cateCriteria?
          =?criteria.createCriteria("categories");
          ????????????????cateCriteria.add(Expression.eq(
          "id",categoryId));
          ????????????????criteria.addOrder(Order.desc(
          "postTime"));
          ????????????????
          int?totalCount?=?((Integer)?criteria.setProjection(Projections.rowCount())
          ????????????????????????.uniqueResult()).intValue();
          ????????????????criteria.setProjection(
          null);
          ????????????????
          ????????????????List?items?
          =?criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();
          ????????????????List?blogs?
          =?new?ArrayList();
          ????????????????
          for(Iterator?ite?=?items.iterator();?ite.hasNext();)?{
          ????????????????????Object[]?objs?
          =?(Object[])ite.next();
          ????????????????????blogs.add(objs[
          1]);
          ????????????????}
          ????????????????PaginationSupport?ps?
          =?new?PaginationSupport(blogs,?totalCount,?pageSize,?startIndex);
          ????????????????
          return?ps;
          ????????????}
          ????????},?
          true);
          ????}
          原來(lái)問(wèn)題就在Criteria.addOrder(Order.desc("postTime"));這句話的位置上面,int totalCount = ((Integer) criteria.setProjection(Projections.rowCount())
          ??????.uniqueResult()).intValue();
          這句話的時(shí)候就會(huì)生成上面那句話,如果在這之前addOrder就會(huì)出現(xiàn)問(wèn)題,如果你用mysql不會(huì)出現(xiàn)問(wèn)題,如果你用sql server就會(huì)報(bào)錯(cuò)。解決方法就是把a(bǔ)ddOrder語(yǔ)句放到totalCount下面就可以了。
          ????public?PaginationSupport?getBlogsByCategoryByPage(final?String?categoryId,?final?int?startIndex,?final?int?pageSize)?{
          ????????
          return?(PaginationSupport)?getHibernateTemplate().execute(new?HibernateCallback()?{
          ????????????
          public?Object?doInHibernate(Session?session)?throws?HibernateException?{
          ????????????????Criteria?criteria?
          =?session.createCriteria(Blog.class);
          ????????????????Criteria?cateCriteria?
          =?criteria.createCriteria("categories");
          ????????????????cateCriteria.add(Expression.eq(
          "id",categoryId));
          ????????????????
          int?totalCount?=?((Integer)?criteria.setProjection(Projections.rowCount())
          ????????????????????????.uniqueResult()).intValue();
          ????????????????criteria.setProjection(
          null);
          ????????????????
          ????????????????
          /*
          ?????????????????*?Fix?a?bug?,Order?must?add?after?get?the?totalCount,
          ?????????????????*?beacuse?SqlServer?not?support?order?by?in?the?select?count(*).
          ?????????????????
          */
          ????????????????criteria.addOrder(Order.desc(
          "postTime"));
          ????????????????List?items?
          =?criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();
          ????????????????List?blogs?
          =?new?ArrayList();
          ????????????????
          for(Iterator?ite?=?items.iterator();?ite.hasNext();)?{
          ????????????????????Object[]?objs?
          =?(Object[])ite.next();
          ????????????????????blogs.add(objs[
          1]);
          ????????????????}
          ????????????????PaginationSupport?ps?
          =?new?PaginationSupport(blogs,?totalCount,?pageSize,?startIndex);
          ????????????????
          return?ps;
          ????????????}
          ????????},?
          true);
          ????}

          這樣生成的sql語(yǔ)句就是這樣的。
          select?count(*)?as?y0_?from?myblog_Blog?this_?inner?join?myblog_Blog_Category?categories3_?on?this_.id=categories3_.blogId?inner?join?myblog_Category?category1_?on?categories3_.categoryId=category1_.id?where?category1_.id=?

          以后大家也要注意了。呵呵。
          posted @ 2006-05-21 22:49 莫多 閱讀(6449) | 評(píng)論 (4)編輯 收藏

          <2006年5月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          常用鏈接

          留言簿(1)

          隨筆分類(lèi)(27)

          隨筆檔案(22)

          Friends

          搜索

          •  

          積分與排名

          • 積分 - 62467
          • 排名 - 845

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 大埔县| 南和县| 承德县| 桦甸市| 铁岭县| 安乡县| 肇东市| 栾城县| 深圳市| 双江| 平阴县| 富源县| 德阳市| 神木县| 岳池县| 洪江市| 轮台县| 且末县| 城固县| 福泉市| 东明县| 沐川县| 界首市| 云阳县| 宜城市| 沁水县| 昌都县| 湘潭县| 广宗县| 潢川县| 衢州市| 镇巴县| 张家口市| 岑巩县| 循化| 泸西县| 墨江| 尤溪县| 沾化县| 永胜县| 正宁县|