xstream是個好東西。對于配置文件的讀取很方便。在mybog中我就用到了。不過今天打算用yupoo的api來做相冊。發現xstream對于xmlnode的attribute解析支持不是那么的好。
對于這種節點格式的非常的簡單
<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>
簡單的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的結果是這樣的
<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不到值了。沒法去mailist里面找答案,果然有人問。
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的文檔。果然找到答案了。
自己寫一個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);
????}
}
然后調用的地方修改一下就ok了。
XStream?stream?=?new?XStream();
stream.registerConverter(new?YupooResultConverter());
stream.alias("result",?YupooResult.class);
參考:
http://xstream.codehaus.org/converter-tutorial.html
2007年1月18日更新。
這里感謝網友 ?的提示。原來新版的xstream可以簡單的解決了。在1.2.1的doc里面找到了這個兩個方法。
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
這兩個方法都是從1.2開始支持的。
也不用自己寫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);

?? 除經特別注明外,本文章版權歸
莫多泡泡所有.
署名,非商業用途,保持一致.???
somebody(莫多)
posted @
2007-01-17 18:24 莫多 閱讀(7999) |
評論 (2) |
編輯 收藏
? 上周更新了一下myblog,添加了一個Filter,做統計訪問用。可是后來發現出現亂碼問題了。找了很久都沒有找到問題。debug的時候看到 CharacterEncodingFilter確實是執行了。不過就是沒有效果。執行之前是ISO-8859-1編碼的,執行之后還是, CharacterEncodingFilter就沒有起到作用。后來終于找到問題的原因了。原來是Filter配置先后順序的原因。
?????? 剛開始的配置是這樣的:
????
<
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
>
? 先經過那個統計的filter然后再經過編碼的filter。這樣的話編碼的filter就不起作用了。只要吧編碼的filter放到最前面就沒有問題了。改成這樣就好。
????
<
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
>
以后大家一定要注意啊。順序問題也是很重要的。
?? 除經特別注明外,本文章版權歸莫多泡泡所有.
署名,非商業用途,保持一致.???somebody(莫多)
posted @
2006-12-27 10:37 莫多 閱讀(2690) |
評論 (3) |
編輯 收藏
昨天晚上配置myblog的rewrite。發現一個奇怪的問題。由于現在使用的這個pjblog,為了讓搜索引擎收錄的連接有效。我想把原來的asp連接rewrite到我的新程序上面。所以有這樣一條規則。
????<rule>
????????<from>^/article.asp\?id=(.*)$</from>
????????<to?type="redirect">/entry/$1.jhtml</to>
????</rule>
???? 但是我這樣的連接總是匹配不到,只要去掉那個?就可以了。這個正則表達式是沒有問題的。/article.asp?id=64是可以匹配的到的。
??? 后來看3.0的manual (http://tuckey.org/urlrewrite/manual/3.0/)才發現原來是這個的問題。
<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. |
就是那個use-query-string 的問題,默認的是不使用query-string就是把?后面的都忽略了。所以就不能匹配到了。只要在<urlrewrite>里面加一個屬性就可以了。
<urlrewrite?use-query-string="true">
????
</urlrewrite>
?? 除經特別注明外,本文章版權歸莫多泡泡所有.
署名,非商業用途,保持一致.???somebody(莫多)
posted @
2006-12-12 10:33 莫多 閱讀(2346) |
評論 (0) |
編輯 收藏
??????我們的項目用到了xmlrpc,不過還是用的2.x版本的。由于xmlrpc3.x地推出。提供了NULL,Serializable等的支持,將原來的Hashtable改成了Map,Vector改成了List。都是不錯的進步。所以我們決定從xmlrpc2.x升級到xmlrpc3.x.
??????在spring里面有幾個ServiceExporter,org.springframework.remoting.rmi.RmiServiceExporter、org.springframework.remoting.caucho.HessianServiceExporter、org.springframework.remoting.caucho.BurlapServiceExporter。不過沒有xmlrpc的serviceExporter,原來我們是自己封裝的XmlRpcServer,用servlet提供服務。(eg:http://localhost:8080/community/service/xmlrpc)沒有和spring集成雖然用了spring。
??? 考慮到spring的便利以及配置的同意我決定將xmlrpcService放入spring中。xmlrpc3.x和xmlrpc2.x的代碼基本上沒有一樣的。改了很多東西。除了類型變化之外,還添加了對異常的支持。詳細信息請參照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>然后映射一個地址就可以通過xmlrpc訪問服務了
????<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
希望對大家有用,這里提供project下載。包含一個client程序。com.jdkcn.xmlrpc.Client
點擊下載完整代碼
?? 除經特別注明外,本文章版權歸
莫多泡泡所有.
署名,非商業用途,保持一致.???
somebody(莫多)
posted @
2006-10-22 16:12 莫多 閱讀(2181) |
評論 (0) |
編輯 收藏
不知道大家有沒有碰到,還是沒有這種需求。就是用like來查詢,我們沒有用Lucene,Compass這種全文索引的方案,我們只是簡單的添加%進行like查詢。用戶搜索的時候就使用*和?來代表任意和一個。所以要對"%"和"_"進行轉義,我們使用的是oracle數據庫。sql語句看起來可能是這樣的。
SELECT?*?FROM?t_user?where?nickname?like?'%Goo\_D'?escape?'\'
這里對_進行轉義了。因為用戶昵稱包含下劃線,如果不進行轉義就表示一個任意字符。有時候我們可能還需要對%進行轉義。同樣的方法在%前加\% 但是比起普通的like語句。多了一個聲明轉義符的語句。所以我們會想到這樣的語句
DetachedCriteria?criteria?=?DetachedCriteria.forClass(User.class);
criteria.add(Restrictions.like("nickname",?user.getNickname()+"'?escape'\"));
但是這樣是不管用的。
接下來可能會想到使用Hibernate3的原生sql查詢,其實我們不需要這樣做。我們還是使用Criteria條件查詢。
criteria.add(Restrictions.sqlRestriction("{alias}.nickname?like???escape'/'",?StringUtil.escapeSQLLike(user.getNickname()),?Hibernate.STRING));
這樣Hibernate產生的語句就是我們想要的語句了。
????/**
?????*?轉義like語句中的
?????*?<code>'_'</code><code>'%'</code>
?????*?將<code>'?'</code>轉成sql的<code>'/_'</code>
?????*?將<code>'%'</code>轉成sql的<code>'/%'</code>
?????*?<p>
?????*???例如搜索<code>?aa*bb?c_d%f</code>將轉化成<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;
????}

?? 除經特別注明外,本文章版權歸
莫多泡泡所有.
署名,非商業用途,保持一致.???
somebody(莫多)
posted @
2006-10-16 23:29 莫多 閱讀(2491) |
評論 (1) |
編輯 收藏
? jspark 的這篇文章《開發階段eclipse下面的spring容器的啟動優化 》講到如何加快spring的啟動速度。非常感謝jspark. 一下是引用的原文:
? 最近在負責一個大項目,項目組成員包括項目經理大概10個人左右。項目技術用struts+spring+hibernate實現。項目的規模相對來說是比較大的,總共有10大模塊,每個大模塊又分為有十幾個、甚至幾十個小模塊。開發工具用eclipse,由于在開發階段,項目開發成員需要頻繁重啟服務器。在啟動服務器的時候,每次啟動時間總是會超過1分鐘。記得以前在做另外一個項目時,啟動時間不到5秒鐘,相差了10倍,而且項目規模是差不多的。
??? 從初步分析來說,應該是hibernate解釋hbm.xml時花費時間,或者可能是spring容器啟動并解釋所有的bean配置文件。診斷了一下,發現1分鐘消耗的時間主要分布在hibernate解釋hbm.xml花費5秒;spring容器從啟動到解釋bean配置文件竟然花了58秒,真是太囂張了。當時非常懷疑spring的效率問題。企圖從網上搜索相關資料,看看有什么優化措施。
??? 首先是找到了hibernate的啟動優化 http://www.hibernate.org/194.html? 里面的主要思想是通過將xml序列花到本地的文件里,每次讀取的時候根據情況,從本地文件讀取并反序列化,節省了hibernate xml的解析時間。按照這個方式測試了一下,發現hibernate的啟動時間從5秒降低到3秒,但是這個優化對于整個啟動過程是杯水車薪的,毫無用處。
??? 沒辦法,又仔細查看了spring的資料,終于發現spring的容器是提供了lazy-load的,即默認的缺省設置是bean沒有lazy- load,該屬性處于false狀態,這樣導致spring在啟動過程導致在啟動時候,會默認加載整個對象實例圖,從初始化ACTION配置、到 service配置到dao配置、乃至到數據庫連接、事務等等。這么龐大的規模,難怪spring的啟動時間要花將近1分鐘。嘗試了一下,把beans的 default-lazy-init改為true就,再次啟動,速度從原來的55秒,降到8秒鐘!!Great!雖然是非常小一個改動,但是影響確實非常大。一個項目組10個人,假若每個人一天平均需要在eclipse下啟動測試服務器50次。那么一天項目組需要重啟500次,每次節省50秒的話,就是 25000秒,將近幾個小時,差不多一個工作日,多么可觀的數字!
?? 不過在運行期間第一次點頁面的時候,由于spring做了lazy-load,現在就需要啟動一部分需要的beans,所以稍微慢2-3秒鐘,但是明顯比等幾十秒要快很多,值得一鑒。
??? 以上是針對開發階段的spring容器啟動優化,在部署到實際環境中,倒是沒必要設置為lazy-load。畢竟部署到實際環境中不是經常的事,每次啟動1分鐘倒不是大問題。
我這里要提醒的是不是說有的beans都能設置default-lazy-init成為true.對于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就都不管用了。所以請大家要注意。
<
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 莫多 閱讀(3319) |
評論 (2) |
編輯 收藏
???? 雖然項目全部采用了UTF-8編碼,所有的源文件*.java,*.jsc,*.html,*.ftl都采用了UTF-8編碼。可是還是出現了亂碼問題。很是不爽,后來找到了tomcat,和resin的配置。
- 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"/>
- 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>
|
???? 這個是resin doc里面的我是在web-app-default里面加上了encoding的配置
????
<
web-app-default
>
??????
<
character-encoding
>
UTF-8
</
character-encoding
>
??????
????
</
web-app-default
>
希望對你的項目有幫助。
?? 除經特別注明外,本文章版權歸莫多泡泡所有.
署名,非商業用途,保持一致.???somebody(莫多)??
posted @
2006-07-22 18:13 莫多 閱讀(1842) |
評論 (4) |
編輯 收藏
項目中多個項目需要同時引用一個靜態資源,所以就想到配置不同的虛擬目錄指到同一個目錄。于是有下面的配置:
????<!--?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>
?????? 但是發現這樣只有后面一個管用(http://localhost:8080/passport/jsvm2)這個是可以,可是(http://localhost:8080/community/jsvm2)就不行,很是郁悶。只要后面的document-directory不是同一個目錄就成。
?????? 后來在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.
Attribute | Meaning | default |
---|
url-pattern | A pattern matching the url: /foo/*, /foo, or *.foo |
url-regexp | A regular expression matching the url |
real-path | The 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>

?? 除經特別注明外,本文章版權歸
莫多泡泡所有.
署名,非商業用途,保持一致.???somebody(莫多)
posted @
2006-07-18 19:41 莫多 閱讀(2902) |
評論 (0) |
編輯 收藏
自從換工作之后就沒有研究過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
>
啟動服務,抱錯了。
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里面搜索了一下,還有答案,原來DWR2.0 加入了JDK5的注釋(annotations).DwrServlet初始化的時候會去檢查注釋的類,找不到就抱錯了。如果你不用annotations也可以忽略掉這個錯誤。不過看起來總是不爽。有人提出了方案。這樣就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
>
?? 除經特別注明外,本文章版權歸莫多泡泡所有.
署名,非商業用途,保持一致.???somebody(莫多)??
posted @
2006-07-17 02:11 莫多 閱讀(2876) |
評論 (0) |
編輯 收藏
首先感謝JScud提供的好文章。《
使用FreeMarker生成Html靜態文件(實例)》
????? 在我們的項目中也用到了Freemarker生成靜態文件。不過這里我要說的是編碼的問題。我們的項目使用的都是UTF-8編碼,我直接使用 飛云小俠 提供的方法生成的文件在UTF-8編碼下察看是亂碼,而GBK正常(后來發現因為我用的中文操作系統所以用GBK查看正常)。
????? 當然我把Freemarker的配置都改成了UTF-8,我的模版文件也是UTF-8編碼的。下面是原來的代碼
????public?void?setTemplatePath(Resource?templatePath)?{
????????this.templatePath?=?templatePath;
????????//設置freemarker的參數
????????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.");
????????}
????}
????/**
?????*?生成靜態文件
?????*?@param?templateFileName?模版名稱eg:(biz/order.ftl)
?????*?@param?propMap?用于處理模板的屬性Object映射?
?????*?@param?htmlFilePath?要生成的靜態文件的路徑,相對設置中的根路徑,例如?"/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");
????????????//創建生成文件目錄
????????????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;
????????}
????????
????}
下面是修改之后的代碼
????/**
?????*?生成靜態文件
?????*?@param?templateFileName?模版名稱eg:(biz/order.ftl)
?????*?@param?propMap?用于處理模板的屬性Object映射?
?????*?@param?htmlFilePath?要生成的靜態文件的路徑,相對設置中的根路徑,例如?"/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");
????????????//創建生成文件目錄
????????????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的不同構造方法
OutputStreamWriter(OutputStream?out)
??????????創建使用默認字符編碼的 OutputStreamWriter。
OutputStreamWriter(OutputStream?out, String?charsetName)
??????????創建使用指定字符集的 OutputStreamWriter。
?這個是中文JDK的文檔說明,剛開始我使用默認的構造函數,所以使用了系統默認的編碼,GBK,所以在生成靜態文件的時候把UTF-8內容用GBK編碼寫入了,所以在UTF-8下瀏覽就有問題。
還有關于修改模版文件同樣也要注意這個問題。
????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 莫多 閱讀(2863) |
評論 (0) |
編輯 收藏
在以前的項目中對于一些資源的配置基本上都是通過spring的IOC注入一個目錄的地址字符串。而這樣的問題是,對于開發中的團隊來說還是很有問題的,因為每個可能都配置一個不同的本地目錄,而發布到服務器之后又有不同的目錄。這樣造成每個人提交了配置文件之后其他人都可能需要修改配置文件才能正確啟動服務。這確實很令人煩勞。
???? 最近看《Professional Java Development with the Spring Framework》時看到了spring對底層資源的抽象,才找到了完美解決方案。
???? 原來的代碼:
????private?String?templatePath;
????public?void?setTemplatePath(String?templatePath)?{
????????this.templatePath?=?templatePath;
????}
????public?void?initListener()?{
????????TemplateEventListener?templateListener?=?new?TemplateEventListener(){
????????????public?void?handleTemplateEvent(TemplateEventSupport?evt)?{
????????????????//?添加事件到隊列中
????????????????queue.offer(evt);
????????????????if(log.isDebugEnabled()){
????????????????????log.debug("Add?Template?about:"?+?evt.getTemplateName());
????????????????}
????????????}
????????????
????????};
????????
????????//注冊模版監聽事件
????????templateManager.addEventListener(Constants.TEMPLATE_SAVE_EVENT,?templateListener,false);
????????
????????
????????//設置freemarker的參數
????????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對底層資源的抽象只要把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)?{
????????????????//?添加事件到隊列中
????????????????queue.offer(evt);
????????????????if(log.isDebugEnabled()){
????????????????????log.debug("Add?Template?about:"?+?evt.getTemplateName());
????????????????}
????????????}
????????????
????????};????
????????//注冊模版監聽事件
????????templateManager.addEventListener(Constants.TEMPLATE_SAVE_EVENT,?templateListener,false);
????????
????????
????????//設置freemarker的參數
????????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目錄下面建立一個template目錄就可以了。在部署到服務器的時候需要部署到一個特定的目錄只要修改這個配置文件為
templatePath.path=file:/D:/template
這樣就可以了。
?? | 除經特別注明外,本文章版權歸莫多泡泡所有. 署名,非商業用途,保持一致.???somebody(莫多)??? |
posted @
2006-06-11 23:01 莫多 閱讀(1865) |
評論 (2) |
編輯 收藏
上篇文章:《
今天發現一個hibernate的bug,或者說一個應該注意的地方比較合適 》里面我提到了Hibernate查詢需要注意的一個問題。今天發現了一個最好的解決辦法。如果大家現在用Hibernate,相信大家都回用到DetachedCriteria.關于DetachedCriteria查詢請查看
http://dev.yesky.com/241/2033241.shtml。
????? DetachedCriteria給我們的Hibernate查詢帶來了很多方便,但是如果你帶上排序信息就會出現我的上一篇文章里面說的那種錯誤,今天發現一個很好的解決方法,其實也很簡單。就是先把傳入的帶Order信息的DetachedCriteria去掉order信息查詢數據總條數,然后再把Order加回來查詢滿足條件的對象。通過查看Hibernate的源代碼發現Criteria的實現CriteriaImpl發現其實addOrder是給private List orderEntries = new ArrayList();這個List加值。這個List里面放的是OrderEntry對象。這個OrderEntry里面放了一個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 莫多 閱讀(5038) |
評論 (12) |
編輯 收藏
現在的系統中雖然使用了。Hibernate但是沒有使用Hibernate的關聯關系來進行數據庫操作。所有的管理操作都是單獨實現的。所以也不能用Criteria.add()這種方式去查詢關聯的一方。所以只能用Native SQL去查詢結果返回對象了。按照Hibernate3的reference里面說的
對原生SQL查詢執行的控制是通過SQLQuery接口進行的,通過執行Session.createSQLQuery()獲取這個接口。最簡單的情況下,我們可以采用以下形式:
List cats = sess.createSQLQuery("select * from cats")
.addEntity(Cat.class)
.list();
這個查詢指定了:
這里,結果集字段名被假設為與映射文件中指明的字段名相同。對于連接了多個表的查詢,這就可能造成問題,因為可能在多個表中出現同樣名字的字段。下面的方法就可以避免字段名重復的問題:
List cats = sess.createSQLQuery("select {cat.*} from cats cat")
.addEntity("cat", Cat.class)
.list();
這個查詢指定了:
addEntity()方法將SQL表的別名和實體類聯系起來,并且確定查詢結果集的形態。
addJoin()方法可以被用于載入其他的實體和集合的關聯.
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查詢可能返回一個簡單的標量值或者一個標量和實體的結合體。
Double max = (Double) sess.createSQLQuery("select max(cat.weight) as maxWeight from cats cat")
.addScalar("maxWeight", Hibernate.DOUBLE);
.uniqueResult();
除此之外,你還可以在你的hbm文件中描述結果集映射信息,在查詢中使用。
List cats = sess.createSQLQuery(
"select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
)
.setResultSetMapping("catAndKitten")
.list();
后來我使用了命名SQL查詢方式。
可以在映射文檔中定義查詢的名字,然后就可以象調用一個命名的HQL查詢一樣直接調用命名SQL查詢.在這種情況下,我們不 需要調用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();
我覺得這種發式比較好。這樣寫出來的sql可以很整齊。我們的數據庫使用的是oracle,不過按照這上面的寫法發現sql語句有錯誤。
后來拿到控制臺執行也抱錯。因為原來都用sqlserver,而sqlserver都是可以的。后來發現是表不能有別名改成這樣就好了。
????????????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
?
這里要特別的提醒一下大家千萬不要把主鍵忘了。剛開始我就忘了主鍵,后來調試了半天才找出原因來。
這樣在sping里面用回調查詢一下就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 莫多 閱讀(3786) |
評論 (0) |
編輯 收藏
今天把myblog用sql server部署了一下,可是發現分頁查詢的時候出現錯誤,看控制臺報錯說語句有錯,由來發現分頁的時候先查詢總記錄數目的那條語句出錯了
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
????? 原來開發的時候我是用的mysql,沒有任何問題。原因就在最后面的order by 語句,sql server 在select count(*)里面不能用 order by。然后跟蹤代碼發現:
????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);
????}
原來問題就在Criteria.addOrder(Order.desc("postTime"));這句話的位置上面,int totalCount = ((Integer) criteria.setProjection(Projections.rowCount())
??????.uniqueResult()).intValue();
這句話的時候就會生成上面那句話,如果在這之前addOrder就會出現問題,如果你用mysql不會出現問題,如果你用sql server就會報錯。解決方法就是把addOrder語句放到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語句就是這樣的。
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 莫多 閱讀(6440) |
評論 (4) |
編輯 收藏
我們的項目比較特殊,基本上每天都要發布一次。為了不影響系統的正常使用,我們的做法是在下班之前把打包好的war放到服務器的一個目錄下面(eg:d:\bak)。然后用windows的計劃任務在晚上12點自動部署系統,也就是net stop tomcat,刪除xx.war,刪除xx,然后把d:\bak\xx.war拷貝到webapps下面。然后再net start tomcat。這樣在第二天來的上班的時候就可以使用升級過的系統了。也不會影響其他人的使用,不需要中斷操作。
??? 關于項目的一個配置我的前幾篇文章我也提到過,那個upload的問題就不會發生了。還有就是關于項目開發中的一些問題。比如數據庫的連接地址,upload directory的配置等,這些在團隊中的每個人都是不一樣的,那么在發布的時候都要改成服務器上的正確配置,如果一個月部署一次這到沒有什么。但是像我們這樣每天部署就不是那么輕松了。而且如果一時不注意很容易造成配置的不正確。所以對于很多配置文件我們都有兩份。一份是用戶自己開發用的,一份是部署到服務器的配置,這樣在開發的時候團隊中的每個人都不一樣,關于服務器的配置都是一樣的,在發布的時候是用的服務器的配置而不是用開發用的配置。eg:web.xml(個人的配置)web-dest.xml 而關鍵的配置也就是下面這段。
web.xml
????<context-param>
????????<param-name>contextConfigLocation</param-name>
????????<param-value>
????????????classpath:spring/*_context.xml,
????????????classpath:spring/global.xml?
????????</param-value>
????</context-param>
web-dest.xml
????<context-param>
????????<param-name>contextConfigLocation</param-name>
????????<param-value>
????????????classpath:spring/*_context.xml,
????????????classpath:spring/global-dest.xml,
????????????classpath:spring/scheduler.xml
????????</param-value>
????</context-param>
注意到其中不一樣的。dest里少了scheduler.xml這個主要是定時執行的一些任務,一般在開發的時候都不需要,去掉也可以提升速度,也不會出現那么多的log。還有就是發布的web.xml用了global-dest.xml這個是關于spring的總的配置。
global.xml
????<bean?id="dataSource"?class="org.apache.commons.dbcp.BasicDataSource"?destroy-method="close">
????????<property?name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value></property>
????????<property?name="url">
????????????<value>jdbc:jtds:sqlserver://192.168.0.240:1433/fivefortunes;SelectMethod=cursor</value>
????????????</property>
????????<property?name="username"><value>sa</value></property>
????????<property?name="password"><value></value></property>
????</bean>
????
????<bean?id="dataSource2"?class="org.apache.commons.dbcp.BasicDataSource"?destroy-method="close">
????????<property?name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value></property>
????????<property?name="url">
????????????<value>jdbc:jtds:sqlserver://192.168.0.240:1433/outmail;SelectMethod=cursor</value>
????????????</property>
????????<property?name="username"><value>sa</value></property>
????????<property?name="password"><value></value></property>
????</bean>
????
????<bean?id="customDataSource"?class="org.apache.commons.dbcp.BasicDataSource"?destroy-method="close">
????????<property?name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value></property>
????????<property?name="url">
????????????<value>jdbc:jtds:sqlserver://192.168.0.240:1433/custom;SelectMethod=cursor</value>
????????????</property>
????????<property?name="username"><value>sa</value></property>
????????<property?name="password"><value></value></property>
????</bean>
global-dest.xml
????<bean?id="dataSource"?class="org.apache.commons.dbcp.BasicDataSource"?destroy-method="close">
????????<property?name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value></property>
????????<property?name="url">
????????????<value>jdbc:jtds:sqlserver://192.168.0.5:1433/fivefortunes;SelectMethod=cursor</value>
????????????</property>
????????<property?name="username"><value>sa</value></property>
????????<property?name="password"><value></value></property>
????</bean>
????
????<bean?id="dataSource2"?class="org.apache.commons.dbcp.BasicDataSource"?destroy-method="close">
????????<property?name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value></property>
????????<property?name="url">
????????????<value>jdbc:jtds:sqlserver://192.168.0.5:1433/outmail;SelectMethod=cursor</value>
????????????</property>
????????<property?name="username"><value>sa</value></property>
????????<property?name="password"><value></value></property>
????</bean>
????
????<bean?id="customDataSource"?class="org.apache.commons.dbcp.BasicDataSource"?destroy-method="close">
????????<property?name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value></property>
????????<property?name="url">
????????????<value>jdbc:jtds:sqlserver://192.168.0.5:1433/custom;SelectMethod=cursor</value>
????????????</property>
????????<property?name="username"><value>sa</value></property>
????????<property?name="password"><value></value></property>
????</bean>
還有關于一些properties文件我們采用了用ant部署的時候改名字來達到目的。
build.xml
????????<move?file="${dist.dir}/mail.properties"?tofile="${dist.dir}/mail-dev.properties"?/>
????????<copy?file="${dist.dir}/mail-dest.properties"?tofile="${dist.dir}/mail.properties"?/>
????????<move?file="${dist.dir}/upload.properties"?tofile="${dist.dir}/upload-dev.properties"?/>
????????<copy?file="${dist.dir}/upload-dest.properties"?tofile="${dist.dir}/upload.properties"?/>
這個是在war之前做的,大家眼看也就明白吧,就是把xx-dest.properties,改名成xx.propeties。在打完包之后
????????<move?file="${dist.dir}/mail-dev.properties"?tofile="${dist.dir}/mail.properties"?/>
????????<move?file="${dist.dir}/upload-dev.properties"?tofile="${dist.dir}/upload.properties"?/>
這樣就達到了我們無憂的目的了。只要每天部署的時候保證程序能正常運行,ant war一下就安心部署吧。
以上就是全部內容,如果有什么不正確歡迎砸板磚。
posted @
2006-04-28 22:27 莫多 閱讀(2687) |
評論 (3) |
編輯 收藏
前面一篇文章提到通過webwork的interceptor給webwork的action設置初始值,
jdev說到"為什么要放在這里,而不是放到系統配置文件中,然后在系統設置界面中提供設置",后來我就用spring來注入了。現在就把值放入properties文件中了。
????<bean?id="propertyPlaceholderConfigurer"?class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
??????<property?name="locations">
????????<list>
??????????<value>classpath:mail.properties</value>
??????????<value>classpath:upload.properties</value>
????????</list>
??????</property>
????</bean>
????<!--?收發外部郵箱?author:somebody-->
????<bean?id="outMailManager"?class="cn.com.fivefortunes.mail.manager.impl.OutMailManagerImpl">
????????<property?name="javaMailSender"><ref?bean="javaMailSender"/></property>
????????<property?name="attachementDirectory"><value>${mail.attachementDirectory}</value></property>
????????<property?name="uploadFileDirectory"><value>${upload.directory}</value></property>
????????<property?name="outMailHibernateManager"><ref?bean="outMailHibernateManager"/></property>
????????<property?name="outMailAccountManager"><ref?bean="outMailAccountManager"/></property>
????</bean>
這樣把uploadFileDirectory放入mananger中去了。在properties里面配置一下就ok了。
upload.directory=D:\\tomcat5\\webapps\\files
mail.attachementDirectory=D:\\tomcat5\\webapps\\files
上次還有網友這樣說到"return ServletActionContext.getServletContext().getRealPath("/");
你這樣換了部署環境每次都要改
而且也該是
D://tomcat5//webapps//files"
也許很多人都以為這是最好的方式,可是實際情況不是這樣,我們的uploadfile目錄已經有3G的文件,而基本上每天我們都要發布新的webapp,如果把uploadfile目錄放到webapp的一個子目錄,每次部署的時候都要先把uploadfile copy出來然后再部署。所以我們這么做就是把upload目錄放到其他目錄不影響uploadfile目錄里面的文件。關于我們項目的部署見我的下一篇文章。謝謝大家。如果您有什么更好的方法請您指教。
posted @
2006-04-22 11:21 莫多 閱讀(1187) |
評論 (0) |
編輯 收藏
剛才在tss上看到Joe發布的消息,DWR允許異步調用Javascript了。DWR 2.0 builds on this to allow you to asynchronously call Javascript code from Java. Reverse Ajax makes writing interactive applications much easier.
值得去看看。
posted @
2006-04-12 09:23 莫多 閱讀(314) |
評論 (0) |
編輯 收藏
Rss,Atom,基本上是Web2.0的基本特征,今天終于有時間決定實現一下。對于動態的Rss,Atom其實就是選取最新的內容,迭迨一下生成一個固定格式的xml文件就可以了。其實也很簡單。
?????? 我用webwork2,用freemarker做模版,在網上找了一個標準的Rss2.0格式就生成我的模版文件rss.ftl
<?xml?version="1.0"?encoding="UTF-8"?>
<rss?version="2.0">
<channel>
<title><![CDATA[我的小站]]></title>
<link>http://leaf.jdk.cn/</link>
<description><![CDATA[泡出好心情,泡出好技術]]></description>
<language>zh-cn</language>
<copyright><![CDATA[Copyright?2006?PaoPao?v4.0]]></copyright>
<webMaster><![CDATA[rory.cn@gmail.com?(Rory?Ye)]]></webMaster>
<generator>PaoPao?v4.0</generator>?
????<image>
????????<title>我的小站</title>?
????????<url>http://leaf.jdk.cn/logo.gif</url>?
????????<link>http://leaf.jdk.cn</link>?
????????<description>莫多泡泡2006</description>?
????</image>
????<#list?blogs?as?blog>
????<item>
????????<link>http://leaf.jdk.cn/entry.action?entryId=${blog.id}</link>
????????<title><![CDATA[${blog.title}]]></title>
????????<author>${blog.authorMail}(${blog.author})</author>
????????<category><![CDATA[?${blog.categories}?]]></category>
????????<pubDate>${blog.pubDate}</pubDate>
????????<guid>http://leaf.jdk.cn/entry.action?id=${blog.id}</guid>????
????????<description><![CDATA[${blog.content}]]></description>
????</item>
????</#list>
</channel>
</rss> 我在rss.action里面去取blogs就可以了。
????public?String?execute()?throws?Exception?{
????????PaginationSupport?ps?=?blogManager.getBlogsByPage(0);
????????blogs?=?new?ArrayList();
????????
????????for(Iterator?ite?=?ps.getItems().iterator();?ite.hasNext();){
????????????Blog?blog?=?(Blog)ite.next();
????????????WrapRssBlog?wrapBlog?=?new?WrapRssBlog();
????????????wrapBlog.setId(blog.getId());
????????????wrapBlog.setAuthor(blog.getAuthor().getNickname());
????????????wrapBlog.setAuthorMail(blog.getAuthor().getMail());
????????????wrapBlog.setTitle(blog.getTitle());
????????????wrapBlog.setContent(StringUtil.extractText(blog.getContent()));
????????????wrapBlog.setPubDate(DateUtil.formatRssDate(blog.getPostTime()));
????????????StringBuffer?sb?=?new?StringBuffer();
????????????for(Iterator?ite2?=?blog.getCategories().iterator();?ite2.hasNext();){
????????????????Category?cate?=?(Category)?ite2.next();
????????????????sb.append("?")
??????????????????.append(cate.getName());
????????????}
????????????wrapBlog.setCategories(sb.toString());
????????????blogs.add(wrapBlog);
????????}
????????return?super.execute();
????}
這里把blog包裝了一下,主要是處理了一下日期,內容,還有把分類拼成字符串。關于日期的處理,參考了飛云小俠寫的rss日期的研究。實現代碼如下。
????public?static?String?formatRssDate(Date?date){
????????SimpleDateFormat?sdf?=?new?SimpleDateFormat("EEE,?d?MMM?yyyy?HH:mm:ss?z",Locale.US);
????????//TODO?TimeZone
????????SimpleTimeZone?zone?=?new?SimpleTimeZone(8,"GMT");
????????sdf.setTimeZone(zone);
????????return?sdf.format(date);
????}
這樣就得到了這樣的日期
Thu, 6 Apr 2006 16:01:36 GMT
做好了這些,配置一下action
????????<action?name="rss"?class="cn.jdk.leaf.action.RssAction">????????
????????????<result?name="success"?type="freemarker">/WEB-INF/pages/rss.ftl</result>
????????</action>
不過像這樣配置的話,你訪問
http://xxx.xxx.com/rss.action看到的不是一個xml
因為返回結果的contentType是text/html.而不是xml,這樣是不行的。看了一下webwork源碼。原來可以這樣簡單的解決。改成這樣配置就可以了。
????????<action?name="rss"?class="cn.jdk.leaf.action.RssAction">
????????????<result?name="success"?type="freemarker">
????????????????<param?name="location">/WEB-INF/pages/rss.ftl</param>
????????????????<param?name="contentType">application/xml</param>
????????????</result>
????????</action>
簡單吧。其實你還可以把這個contentType改成其他類型的。比如excle的。這樣用戶執行就可以得到一個xls文件。哈哈。
posted @
2006-04-10 22:40 莫多 閱讀(1336) |
評論 (2) |
編輯 收藏