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)友 ?的提示。原來(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);

?? 除經(jīng)特別注明外,本文章版權(quán)歸
莫多泡泡所有.
署名,非商業(yè)用途,保持一致.???
somebody(莫多)
? 上周更新了一下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)題也是很重要的。
?? 除經(jīng)特別注明外,本文章版權(quán)歸莫多泡泡所有.
署名,非商業(yè)用途,保持一致.???somebody(莫多)
昨天晚上配置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.
Attribute | Possible Value | Explanation |
---|
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). |
wildcard | All 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. |
null | Do 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. |
true | The 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. |
true | The 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>
?? 除經(jīng)特別注明外,本文章版權(quán)歸莫多泡泡所有.
署名,非商業(yè)用途,保持一致.???somebody(莫多)
??????我們的項(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)擊下載完整代碼
?? 除經(jīng)特別注明外,本文章版權(quán)歸
莫多泡泡所有.
署名,非商業(yè)用途,保持一致.???
somebody(莫多)
不知道大家有沒(méi)有碰到,還是沒(méi)有這種需求。就是用like來(lái)查詢(xún),我們沒(méi)有用Lucene,Compass這種全文索引的方案,我們只是簡(jiǎn)單的添加%進(jìn)行l(wèi)ike查詢(xún)。用戶(hù)搜索的時(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)橛脩?hù)昵稱(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查詢(xún),其實(shí)我們不需要這樣做。我們還是使用Criteria條件查詢(xún)。
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;
????}

?? 除經(jīng)特別注明外,本文章版權(quán)歸
莫多泡泡所有.
署名,非商業(yè)用途,保持一致.???
somebody(莫多)
? 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
>
?