在以前的項目中對于一些資源的配置基本上都是通過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) |
編輯 收藏
以前一直都沒有試過,前幾天打算把wordpress換成自己寫的程序,就想到了數據的導入和導出,首先想到的是用數據庫工具來導。可是覺得有些麻煩,我自己的程序是用spring+hibernate的。后來我就試了一下spring的JdbcTemplate,就和HibernateTemplate一樣的好用。首先增加一個連接到wp數據庫的dataSource
????<bean?id="dataSource2"?class="org.springframework.jdbc.datasource.DriverManagerDataSource"?destroy-method="close">
????????<property?name="driverClassName"><value>org.hibernate.dialect.MySQLDialect</value></property>
????????<property?name="url">
????????????<value>jdbc:mysql://192.168.0.240:3306/wordpressωuseUnicode=true&characterEncoding=utf8</value>
????????????</property>
????????<property?name="username"><value>root</value></property>
????????<property?name="password"><value></value></property>
????</bean>
??? 然后在轉換程序里面get這個dataSource,new 一個JdbcTemplate(dataSource2),這樣就ok了。很簡單吧。
????public?void?testCopyData()?throws?Exception{
????????DataSource?ds?=?(DataSource)applicationContext.getBean("dataSource2");
????????
????????CategoryManager?cateManager?=?(CategoryManager)?applicationContext.getBean("categoryManager");
????????
????????JdbcTemplate?jt?=?new?JdbcTemplate(ds);
????????System.out.println("Total?posts:"+jt.queryForInt("select?count(*)?from?wp_posts"));
????????assertNotNull(ds);
????????
????????List?cates?=?jt.queryForList("select?*?from?wp_categories");
????????int?i=?0;
????????for(Iterator?ite?=?cates.iterator();?ite.hasNext();){
????????????i++;
????????????Map?result?=?(Map)?ite.next();
????????????Category?cate?=?new?Category();
????????????cate.setName((String)result.get("cat_name"));
????????????cate.setOrder(i);
????????????if(i==1)
????????????????cate.setDefaultCategory(true);
????????????cateManager.saveCategory(cate);
????????????System.out.println("cat_name:"+result.get("cat_name")+"\n");
????????}
????}
posted @
2006-04-07 00:03 莫多 閱讀(3588) |
評論 (7) |
編輯 收藏
只是自己的想法,不對不要扔雞蛋哦。
今天突發奇想的實現一個小小的cache。把分類categories放入map中,cache起來。
????private?void?cache()?{
????????if(log.isDebugEnabled()){
????????????log.debug("Starting?cache?the?categories
");
????????}
????????cacheCategoryMap?=?new?HashMap();
????????cacheCategoryMap.put("categories",categoryDao.getCategories());
????}
然后我想在interceptor里面把categories寫到ognlvaluestack里面這樣我在ftl里面就可以<#list categories>....</#list>了。因為這個是在每個頁面的header.ftl里面的。我也就不需要再每個action里面去get一下了。
剛開始我implements Interceptor
????????final?OgnlValueStack?stack?=?ActionContext.getContext().getValueStack();
????????stack.setValue("categories"?,categoryManager.getCategories());
????????return?invocation.invoke();
可是這樣也不可以。后來我想到是不是action執行完畢之后就把stack中的這個值清空了我又用了。AroundInterceptor 我想在after里面去設置不就可以了。
????protected?void?after(ActionInvocation?dispatcher,?String?result)?throws?Exception?{
????????final?OgnlValueStack?stack?=?ActionContext.getContext().getValueStack();
????????stack.setValue("categories"?,categoryManager.getCategories());
????}
可是這樣還是不可以。我暈了。我想是不是要在action里面聲明一下categories。
????private?List?categories;
????public?List?getCategories()?{
????????return?categories;
????}
????public?void?setCategories(List?categories)?{
????????this.categories?=?categories;
????}
然后在before里面去get就可以了。
????protected?void?before(ActionInvocation?invocation)?throws?Exception?{
????????final?OgnlValueStack?stack?=?ActionContext.getContext().getValueStack();
????????stack.setValue("categories"?,categoryManager.getCategories());
????}
總算實現了。不過還要在每個action里面聲明一下categories,這樣還是很不好的。剛才有人建議用filter。我在試試吧.
http://leaf.jdk.cn/index.php/archives/91
posted @
2006-03-21 11:37 莫多 閱讀(1128) |
評論 (0) |
編輯 收藏