第一次用 Zoundry 客户端工具来发布博客,WordPress 还是不错的博客了,提供了 XML-RPC 方式的远程提交接口,我们可以比较容易的把我们的博客发布到 WordPress 上。
老外对这方面的支持工作还是做的不错的,国内的同类系统往往只考虑到功能,好一点的考虑到性能,而在这些新技术带来的扩展性的增强上似乎没有太多的理解,虽然 WordPress 在功能上和国内的很多博客有一定的差距,但是人家支持插件,这样就可以让地球人都上来扩展一把。Eclipse 的插件风风火火的做了几年,现在人似乎没有不用插件开发的了。
老外在 Web 2.0 中又很多好的思想,技术,拿到国内来就有点变味了,虽说国人在 Web 2.0 技术上跟进的速度还是相当的快,不过思想还是又相当的差距的。
要好好学学人家做东西的思想,而不仅仅是技术。
posted @
2008-01-04 16:42 steady 阅读(997) |
评论 (0) |
编辑 收藏
该文章被发布在我的新博客中:http://4think.cn/blog/index.php/archives/25
市面上这么多的IM工具,每次打开的时候就要开上一堆,还不时的有个新的IM工具出来,加上一两个及其有吸引力的功能,然后又不得不装上,搞的每次开机以后总是要开上一大堆的IM,比如QQ啦,MSN啦,还有Yahoo,Google Talk,飞信,Skype,真的挺麻烦的。
一年前的时候,突然听说 Yahoo 可以和 MSN 互通了,于是从此就没用过 MSN 了,也是对 Microsoft 歧视国内用户的一种不满吧,这么多IM工具,最不稳定的也最为常用的要属 MSN 了,虽然飞信这样“国”字号的软件似乎更加的不争气,就原谅他吧,谁叫他是咱最有钱的移动运营商呢。可以说,MSN 的掉线率是相当的高,登录速度也是惊人的,在公司内部传文字的效率呢更加不用说了,反正没有人走的快。不过据我们去过美国的一些同事说,MSN 在美国速度是非常快的,包括其下属的 hotmail,MSN Space,怪不得这么被推崇了,不过没办法,毕竟是在国内,属于不被重视的使用群体,大不了就不用了,于是机子里再也没有出现过 MSN,所有重要的好友都加到 Yahoo 里了。
其实说来 Yahoo 也是个比较不争气的东西,功能嘛,没啥强的,不过吃内存的能力还挺强,印象中也就 Skype 可以和他有的一拼,不过好歹人家 Yahoo 还是比较重视中文用户的,起码光缆断的时候还是能用的,而且相关的本地化服务也还是有一定的可用性的,Yahoo的邮件提示是最为迅速的,基本上是新邮件来到5秒之内就得让你知道,这个功能还是挺体贴用户的,其实我的一些 IM 的一个重要作用就是 check email,比如说 Google Talk。Yahoo 的客户端程序其实是比较不稳定的,群聊功能是个杀手,一次领导通知事情,让大家开个会,结果一位老兄图方便,Yahoo 把大家全部加进来了,大家的机器全部死翘翘,只好 reset 重启,自此以后,这个功能再也不敢使用了,Yahoo 工具箱里有个看股市行情的插件,不过这个曲线也太不本地化了,中午休息的时间也画在上面,一条长长的直线,怎看都别扭。没办法啊,公司里唯一允许的 IM 工具,不得不装,也就不得不去忍受这些了。
Google Talk 其实是我用的最多的,极为简洁,拥有我需要的主要功能,email 通知,语音,文本聊天,传文件(大家都喜欢装中文版的,没这个功能,所以也基本找不到人传文件),其实还有一点重要的就是所有聊天记录都会保存在 Gmail 里,在哪都不会丢失,也很连贯,这对于我们经常讨论需求的人就不会有上句没下句的了。也不用担心聊天记录留在本地泄密。另外还有一点,传代码的时候绝对不会变成一堆笑脸什么的。Google Talk 其实功能上是相当有限的,但是我却非常喜欢,简洁就是美了。
下面隆重出场的是唯利是图、忘恩负义外加极端不安全的 QQ 了,如果不是这么多好友在里面,我是不会开 QQ 的,当然 QQ 作为国内用的最多的 IM 工具(其实叫他聊天工具更确切),QQ 还是有相当多的优势的,首先网络稳定性好,传文件速度快,有远程协助功能,语音质量也不错,可以看 IP(还不都是珊瑚虫的功劳,被忘恩负义的腾讯扼杀了),有群聊功能,也是最适合某些夜晚不甘寂寞的人寻找刺激的工具了,其他的功能我是不大能想到的了,更不用说去用了,所以嘛,QQ 对我来说,太大了,太花哨了,对公司来说也是的,基本上正规的公司,没有哪个不封 QQ 的,所以嘛,QQ 只能被远远的拒之于企业应用的门外,腾讯的 RTX 也就不是那么容易进入企业市场的,谁让你这么花哨,看了就不想好好工作了。
Skype 这个东西嘛,对我用处不大,自从充值卡被封事件以后就不再常开了,开会的时候才会去用,毕竟多人语音聊天功能还是挺不错的。
国外的大部分 IM 工具都开放互通了,包括 MSN 和 Yahoo,Google Talk 也在和 MS 谈互通的问题,国内的 IM 互通嘛,似乎完全不可能,国外那几家都不是靠 IM 吃饭的,腾讯就不一样了,如果不保持其 QQ 的占有率,疯狂的扼杀非“官方”的客户端,LumaQQ 这么优秀的跨平台解决方案也就被腾讯自己和谐掉了,最近对珊瑚虫下狠手也表示其在此方面的决心,呵呵,我的 QQ 从此不升级了。
posted @
2008-01-02 11:27 steady 阅读(2030) |
评论 (4) |
编辑 收藏
每个人在开发的时候,都会根据自己的喜好选择一些好用的工具,当然,通过一些年头的积累,我自己也有了这么一些顺手的工具,就把这些还不错的东西拿出来和大家分享吧。
CyberArticle (网文快捕)
我们在查看资料,或者遇到问题上网搜索的时候,经常会想把自己看到的一些好东西保存下来,以后需要用的时候可以找到,有人把东西复制下来保存成文本,有人用 Word 文档,也有人直接保存页面,这些方法固然是可以,不过以后找起来可就比较麻烦了。我们需要一个带分类的文档管理工具。
在对一堆工具的筛选之后,我选中了 CyberArticle,也就是网文快捕,安装以后,在浏览页面时,IE 和 FF 的右键会出现保存全文,保存选中部分这样的选项,我最喜欢的是保存选中部分这个功能,毕竟我们并不需要一个网页中一些不相关的文字和图片。CyberArticle 可以完整的把文章内容或选中部分的内容保存下来,无论是图片或者其他什么的,都能较好的支持。在保存下自己喜欢的内容后,我们可以手工把这些内容分类,以后会比较容易的找到自己需要的东西。
另外 CyberArticle 中比较有用的功能是生成电子书。我们在网上搜集到一堆某一类别的文章,为了与他人分享或者便于携带,我们可以把这一个独立的类别的内容导出成 CHM 或 EXE 版本的电子书。
CyberArticle 可以到 http://www.wizissoft.com/cn/index.aspx 下载,强烈建议使用最新的 5.0 版(只要25块钱),旧的版本会有相当一部分的文章保存不下来。
posted @
2007-11-29 10:59 steady 阅读(2088) |
评论 (11) |
编辑 收藏
昨天看到新闻,IBM 在其网站上放出了 Lotus Symphony 的 beta 版,看上去有点 Office2007 的一套办公产品,最重要的是它是基于 Eclipse-RCP 平台的,如果说 IBM 让 Lotus 去做一个标准的 Windows 应用像 Office2007 到没有什么奇怪的,关键在于它是 Eclipse 平台的,IBM 在一个强大的 Eclipse 平台上,构建出了一个向 Microsoft 最核心产品叫板的应用,这大大的壮大了 Java 爱好者的威风。
过去我们 Swing / SWT 做的东西似乎很难有直接面向普通用户的优秀的应用,这次 IBM 是代 Java 出了重重的一拳,Eclipse 平台不但是与 Microsoft 的 Visual Studio 叫板,甚至可以和 Office 叫板了。
从另一方面来说,从 Lotus Symphony 的推出,IBM 进一步亮相了 Eclipse RCP 的高级 UI 组件,传统的 Eclipse 开发出的东西,千篇一律,没有太大的界面差别,但是 Lotus Symphony 上却不太容易让人联想到 Eclipse,除了看到启动画面上 build on eclipse 的只有,还有一些熟悉的菜单项,和 PlugIn 相关的内容才会发现,哇,这个酷酷的应用原来是 Eclipse 平台上的产品。
当然 Lotus Symphony 并没有说是开源的,这些新的,酷酷的 UI 组件也并没有向开源社区开放,按照 IBM 最近几年的惯例,迟早是要捐出来的,但前提是先做几套东西,卖点钱再说,Eclipse WTP 的很多东西来源于 WSAD,很多 Eclipse 的插件也是来源于 Rational 的产品,只是 IBM 觉得没有什么商业价值了,才捐出来。
其实我是非常希望 IBM 能尽快和大家分享 Lotus Symphony 的成功经验,也希望更多的 Eclipse 爱好者能够开发出更多强大的应用,特别是桌面级应用,让更多的人看到,Java 在成长,在进取。
---------------------------------------------------
顺便做个小广告 链客中国 www.linkedcast.cn 上线运行,欢迎广大 Blogger 使用
posted @
2007-09-23 08:40 steady 阅读(1139) |
评论 (8) |
编辑 收藏
Java Web 应用似乎总有这样的情况,有事没事总是要在 URL 后面加上个 jsessionid,而且似乎不能使用配置的方式直接禁用 URL 传递 sessionid,这样,就比较容易造成安全性的问题,或者在浏览器地址栏里留下一堆很不好看的地址,在 Struts2 中,使用了 url 标签的所有链接,甚至 CSS, JS 这样的东西,都会加上 jsessionid,如何去禁用呢,搜索国内的相关文章,无功而返,询问我们过去的架构师,也没有做过,只好想办法去找国外的网站,找到了这样的一篇文章。
http://randomcoder.com/articles/jsessionid-considered-harmful
通过加入 Filter 的方式过滤掉 URL 中包含的 jsessionid,再重新包装 Response 返回给浏览器。
因为没有太多东西,就不多解释了,大家拿了用就可以了。
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* Servlet filter which disables URL-encoded session identifiers.
* <p/>
* <pre>
* Copyright (c) 2006, Craig Condit. All rights reserved.
* <p/>
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* <p/>
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* <p/>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* </pre>
*/
@SuppressWarnings("deprecation")
public class DisableUrlSessionFilter implements Filter {
/**
* Filters requests to disable URL-based session identifiers.
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// skip non-http requests
if (!(request instanceof HttpServletRequest)) {
chain.doFilter(request, response);
return;
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// clear session if session id in URL
if (httpRequest.isRequestedSessionIdFromURL()) {
HttpSession session = httpRequest.getSession();
if (session != null) session.invalidate();
}
// wrap response to remove URL encoding
HttpServletResponseWrapper wrappedResponse = new HttpServletResponseWrapper(httpResponse) {
@Override
public String encodeRedirectUrl(String url) {
return url;
}
@Override
public String encodeRedirectURL(String url) {
return url;
}
@Override
public String encodeUrl(String url) {
return url;
}
@Override
public String encodeURL(String url) {
return url;
}
};
// process next request in chain
chain.doFilter(request, wrappedResponse);
}
/**
* Unused.
*/
public void init(FilterConfig config) throws ServletException {
}
/**
* Unused.
*/
public void destroy() {
}
-------------------------------------------------------------------------------------------------
顺便做个小广告 链客中国 www.linkedcast.cn 上线运行,欢迎广大 Blogger 使用
posted @
2007-09-08 20:13 steady 阅读(5683) |
评论 (4) |
编辑 收藏
在过去使用 Spring 整合 Hibernate 的时候,都是用这样的配置方式。
<bean id="sessionFactory" lazy-init="true"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingResources">
<list>
<value>resources/icustomer/Contact.hbm.xml</value>
<value>resources/icustomer/Customer.hbm.xml</value>
</list>
</property>
.
</bean>
每当需要加入一个新的 VO 时,我需要过来修改配置文件,来引入对新的 VO 的支持。现在我使用的时候,是这么配的:
<bean id="sessionFactory" lazy-init="true"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingLocations">
<list>
<value>classpath:resources/**/*.hbm.xml</value>
</list>
</property>
.
</bean>
做项目开发的时候,就再也没有改过配置。
posted @
2007-08-17 13:58 steady 阅读(1933) |
评论 (5) |
编辑 收藏
因为有一个 Struts2 网站发布,需要整合一个论坛来使用,公司的一个项目过去曾经整合过一个英文论坛,但似乎不能满足我们的需求,需要找一个成熟稳定的中文论坛,与我们的系统结合。
最终选择了 Discuz 作为我们的论坛系统,主要是因为它提供了一套可用的 Passport API,来直接与我们现有系统进行整合。
下面摘录 Discuz 文档中的内容来说明整合原理,随后的几篇中,将详细描述具体的整合过程。
假设已设置如下变量或参数
- 挂接 Discuz! Passport 的应用程序假设为一套 PHP 语言编写的 CMS 系统
- Discuz! 的 URL 为 http://www.myforums.com
- 应用程序的 URL 为 http://www.mywebsite.com
- 应用程序的注册页面为 http://www.mywebsite.com/register.php
- 应用程序的登录页面为 http://www.mywebsite.com/login.php?action=login
- 应用程序的退出页面为 http://www.mywebsite.com/login.php?action=logout
开启通行证后的用户登录流程
- 如果用户在论坛点击“登录”,则转向到事先设置好的应用程序登录页面(http://www.mywebsite.com/login.php?action=login),并在登录页面的 URL 中加入参数 forward(加入 forward 后的链接例如 http://www.mywebsite.com/login.php?action=login&forward=http://www.myforums.com/index.php),用于在登录后将用户导向到指定的 URL。
- 应用程序收到此请求后,按照惯例生成表单,并增加一个表单变量,将 GET 方式传递过来的 forward 参数通过表单进行传递。
- 用户在应用程序的表单中填写登录信息,并提交到应用程序的登录验证程序。应用程序验证用户提交的用户名和密码的合法性:
- 如果不通过:提示用户名密码错误,要求其返回上一页重新填写。
- 如果通过,需要进行如下操作:
- 设置自身 Cookie 或 Session,使得应用程序自身处于登录状态。
- 检查表单中是否提交了 forward 变量,如有,则意味着登录请求可能是由论坛而来,将此变量传递到后面的请求中。如没有,自行生成 forward 变量,使得论坛登录后能够跳转回到应用程序中。
- 通过 header('Location: http://www.myforums.com/api/passport.php?action=login&auth=xxx&forward=http://yyy&verify=zzz') 的方式,将登录请求传递到论坛进行处理。其中 auth 用来将用户信息与资料以特定的格式,加密传递给论坛,forward 用于告知论坛 Passport API 完成自身操作后转向到的 URL 地址,verify 用于验证前面两个变量的有效性。auth、forward、verify 格式与结构将在后面进行说明。
- Discuz! Passport API 在接收到由应用程序通过 header() 提交过来的请求后,进行如下操作:
- 根据 verify 判断 auth 和 forward 变量是否合法,如合法则继续,否则终止。
- 将 auth 根据既定算法解密,并还原成数组,数组的内容与格式将在后面进行说明。根据数组中的内容,检查此用户是否存在。如存在,则根据上述数组中的内容 UPDATE 论坛中相应的用户资料。如不存在,则使用数组中的信息 INSERT 到论坛用户资料表中。
- 论坛设置 Cookie 或 Session,使得论坛自身处于登录状态。
- 根据应用程序反馈的 forward 值,通过 header('Location: http://xxx') 的形式将页面跳转到 forward 变量指定的 URL。
- 至此,登录流程结束
开启通行证后的用户退出流程
- 如果用户在论坛点击“退出”,则转向到事先设置好的应用程序退出页面(http://www.mywebsite.com/login.php?action=logout),并在登录页面的 URL 中加入参数 forward(例如 http://www.mywebsite.com/login.php?action=login&forward=http://www.myforums.com/index.php),用于在退出后将用户导向到指定的 URL。
- 应用程序收到此请求后,清除自身 Cookie 或 Session,使得应用程序自身处于非登录状态。
- 检查是否提交了 forward 变量,如有,则意味着登录请求可能是由论坛而来,将此变量传递到后面的请求中。如没有,自行生成 forward 变量,使得论坛登录后能够跳转回到应用程序中。
- 通过 header('Location: http://www.myforums.com/api/passport.php?action=logout&forward=http://yyy&verify=zzz') 的方式,将退出请求传递到论坛进行处理。其中 forward 用于告知论坛 Passport API 完成自身操作后转向到的 URL 地址,verify 用于验证 forward 变量的有效性。forward、verify 格式与结构将在后面进行说明。
- Discuz! Passport API 在接收到由应用程序通过 header() 提交过来的请求后,进行如下操作:
- 根据 verify 判断 forward 变量是否合法,如合法则继续,否则终止。
- 清楚论坛的 Cookie 或 Session,使得论坛自身处于非登录状态。
- 根据应用程序反馈的 forward 值,通过 header('Location: http://xxx') 的形式将页面跳转到 forward 变量指定的 URL。
- 至此,退出流程结束。
开启通行证后的用户注册流程
posted @
2007-08-11 17:30 steady 阅读(3288) |
评论 (3) |
编辑 收藏
Reschedule
rescheduleJob(String triggerName, String groupName, Trigger newTrigger)
在进行 reschedule 操作的时候,我们通常只需要修改 Trigger 的时间,这时候我们只需要重新 new 一个含有新的 Schedule 时间的 Trigger 对象,reschedule 一下就可以了。
Unschedule
unscheduleJob(String triggerName, String groupName)
进行 unschedule 的时候,我们只需要知道名字和 group 就可以了。
进行 Schedule 操作前后,Database 中的相关数据都会被更改,在执行 unschedule 或者该 schedule 已经执行过,数据库中的 trigger 信息都会被删除。
posted @
2007-08-03 09:00 steady 阅读(1673) |
评论 (4) |
编辑 收藏
Quartz 是一个强大的企业级 Schedule 工具,也是目前最好的开源 Schedule 工具,最近因为项目的需要,简单的用到了 Quartz 的一些功能,对项目中使用 Quartz 的一些问题做简单的记录。
在 Quartz 的应用中,我们用到了以下的一些东西,ScheduleFactory, Scheduler, Job, JobDetail, Trigger,简单说明一下他们的用途。
SchedulerFactory 是 Scheduler 的工厂,我们可以从中获得受工厂管理的 Scheduler 对象。
SchedulerFactory scheduleFactory = new StdSchedulerFactory();
Scheduler scheduler = scheduleFactory.getScheduler();
Scheduler 是一个计划集,其中可以包含多个 JobDetail 和 Trigger 组成的计划任务。
我们可以从 SchedulerFactory 中取得 Scheduler。
接口Job是每个业务上需要执行的任务需要实现的接口,该接口只有一个方法:
public interface Job {
public void execute(JobExecutionContext context)
throws JobExecutionException;
}
我们可以在里面定义我们的 Job 执行逻辑,比如清除过期数据,更新缓存等。
JobDetail描述了一个任务具体的信息,比如名称,组名等等。
JobDetail jobDetail = new JobDetail("SayHelloWorldJob", Scheduler.DEFAULT_GROUP, SayHelloWorldJob.class);
在上面的构造方法中,第一个是任务的名称,第二个是组名,第三个就是实际当任务需要执行的回调类。
Trigger顾名思义就是触发器,Quartz有个很好的想法就是分离了任务和任务执行的条件。Trigger就是控制任务执行条件的类,当Trigger认为执行条件满足的时刻,Trigger会通知相关的Job去执行。分离的好处是:
1.你可以为某个Job关联多个Trigger,其中任何一个条件满足都可以触发job执行,这样可以完成一些组合的高级触发条件
2.当Trigger失效后(比如:一个永远都不能满足的条件),你不必去声明一个新的job,代替的是你可以为job关联一个新的Trigger让job可以继续执行。
目前的Quartz实现中,存在两种Trigger,SimpleTrigger和CronTrigger,SimpleTrigger用来完成一些比如固定时间执行的任务,比如:从现在开始1分钟后等等;而CronTrigger(没错,和unix的cron进程的含意一样)用来执行calendar-like的任务,比如:每周五下午3:00,每月最后一天等等。
在我们项目中,都是一些固定时间的 Job,所以只用到了 SimpleTrigger。
Trigger trigger = new SimpleTrigger("SayHelloWorldJobTrigger",Scheduler.DEFAULT_GROUP,new Date(),null,0,0L);
这个构造方法中,第一个是Trigger的名称,第二个是Trigger的组名,第三个是任务开始时间,第四个是结束时间,第五个是重复次数(使用SimpleTrigger.REPEAT_INDEFINITELY常量表示无限次),最后一个是重复周期(单位是毫秒),那么这样就创建了一个立刻并只执行一次的任务。
但我们定义好了 JobDetail,Job,和 Trigger 后,就可以开始 Schedule 一个 Job 了。
scheduler.scheduleJob(jobDetail, trigger);
这条语句就是把job和Trigger关联,这样当Trigger认为应该触发的时候就会调用(实际上是Scheduler调用)job.execute方法了。
scheduler.start();
千万别忘了加上上面的语句,这条语句通知Quartz使安排的计划生效。
关于execute方法的参数JobExecutionContext
JobExecutionContext就和很多Context结尾的类功能一样,提供的运行时刻的上下文环境,JobExecutionContext中有Scheduler,JobDetail,Trigger等很多对象的引用,从而当你在execute方法内部须需要这些对象的时刻提供的便利。
在项目中,我们把需要执行的 Job 相对应的一些信息放在 JobExecutionContext 中,在 Job 执行的时候可以调用。
jobDetail.getJobDataMap().put(userid, id);
在 Job 中,我们可以拿到相关的 Context 信息:
jobExecutionContext.getJobDetail().getJobDataMap().getInt(userid);
JobDetail和Trigger的name和group
Scheduler实例对应了很多job和trigger的实例,为了方便的区分,Quartz使用name和group这两个特性,正如你想向的一样,同一个group下不能有两个相同name的JobDetail,Trigger同理,同一个Scheduler下不能有两个相同group的JobDetail,Trigger同理,JobDetail和Trigger的完全限定名为:group + name
为了让服务器重启以后,我们的 Scheduler 信息仍然不丢失,我们通常采用数据库持久化 Scheduler 的信息。
DBScript 在 Quartz 的下载包中的:quartz-1.6.0\docs\dbTables 下,选择自己使用的 DB 相应的 Script 导入数据库就可以了。
在应用中,我们需要配置一个 quartz.properties 才能正常使用 DB。我们可以在 quartz-1.6.0\examples\example10 中找到该文件的样例,稍作一些修改,就可以放到自己项目源码的根目录下使用了。
设置 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 即可启用基于 JDBC 的 Quartz 信息持久化。
根据项目情况设置以下配置信息:
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = false
org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/myapplication
org.quartz.dataSource.myDS.user = root
org.quartz.dataSource.myDS.password =
org.quartz.dataSource.myDS.maxConnections = 5
但是光设置了 Database 不够,我们还需要在 Application 启动的时候自动启动 Scheduler 才行,我们只需要简单的写一个 Servlet 的 Listener 并在 web.xml 中声明该 Listener ,在 Servlet 容易启动的时候,Scheduler 就开始自动执行。
public class ScheduleStartListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent servletContextEvent) {
try {
scheduleFactory.getScheduler().start();
} catch (SchedulerException e) {
// write log
}
}
public void contextDestroyed(ServletContextEvent servletContextEvent) {
try {
scheduleFactory.getScheduler().shutdown();
} catch (SchedulerException e) {
// write log
}
}
}
在 web.xml 里面加入以下配置:
<listener>
<listener-class>org.agilejava.scheduler.ScheduleStartListener</listener-class>
</listener>
以上简单的记录了在项目中关于 Quartz 的一些应用,如果有什么新的使用心得,会在后面继续加入的。
posted @
2007-08-02 16:28 steady 阅读(3559) |
评论 (4) |
编辑 收藏
上一篇中我们说到了,如何使用 HttpClient 抓取所需要的数据,接下来介绍一下如何对这些数据进行处理。基本的处理原理是使用正则表达式进行内容的匹配。
为了便于处理,我们首先把使用 HttpClient 抓取到的数据做一些简单的处理。
第一步要做的就是删除回车符,当然我不会写含有回车符的正则表达式才会这么写的,当然如果您有更好的方法也可以不用这么做。
代码很简单:
1
protected String removeEnter(String response)
{
2
response = StringUtils.replace(response, "\r\n", "");
3
response = StringUtils.replace(response, "\n", "");
4
return response;
5
}
接下来就可以使用正则表达式来对所抓取的内容进行匹配了:
正则表达式是一种可以用于模式匹配和替换的强有力的工具,一个正则表达式就是由普通的字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式,它描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。正则表达式在字符数据处理中起着非常重要的作用,我们可以用正则表达式完成大部分的数据分析处理工作,如:判断一个串是否是数字、是否是有效的Email地址,从海量的文字资料中提取有价值的数据等等,如果不使用正则表达式,那么实现的程序可能会很长,并且容易出错。对这点本人深有体会,面对大量工具书电子档资料的整理工作,如果不懂得应用正则表达式来处理,那么将是很痛苦的一件事情,反之则将可以轻松地完成,获得事半功倍的效果。
在这里,我使用了 Jakarta-ORO 作为正则表达式工具来进行匹配。
Jakarta-ORO是最全面以及优化得最好的正则表达式API之一,Jakarta-ORO库以前叫做OROMatcher,是由Daniel F. Savarese编写,后来他将其赠与Jakarta Project,读者可在jakarta.apache.org的网站下载该API包。
因为在这里我们不需要用到太多正则表达式的知识,仅仅是简单的用用而已,所以几行简单的代码就可以解决问题:

protected String match(String response, String template, int index)
{
Perl5Util engine = new Perl5Util();
String name = null;

if (response != null)
{

if (engine.match(template, response))
{
name = engine.group(index);
}
}
return name;
}
第一个参数 response 表示抓取到的页面源码,第二个参数 template 表示我们预先设定的模板,第三个表示第几个匹配。返回的结果是匹配成功的 group 中的内容。
于是我们可以这样的调用它:
String template = "/(沪综指)</font></b></a> <span id=\"STK1\">(\\d{4,5}\\.\\d{1,4})</span>";
String name = match(response, template, 1);
String index = match(response, template, 2);
注意一下,我们正则表达式前后都有 "/"。
另外,我们用() 括起来的部分表示我们要匹配的内容,所以这里 name 可以匹配到 沪综指,index 可以匹配到大盘的点数。
该匹配对应于: http://web7.jrj.com/homev1/StockIndex.htm
为了防止页面以后打不开了大家找不到,我把其中相关的匹配部分的页面源码也发出来:
<a href=javascript:ShowImg('000001',2) target=_self><b><font color=#000000>沪综指</font></b></a> <span id="STK1">3914.20</span> <span id="STK2" class="c1"><img src=/HomeV1/images/down.gif width=8 height=8>164.40</span> <a href=javascript:ShowImg('399001',1) target=_self><b><font color=#000000>深成指</font></b></a> <span id="STK3">12882.17</span> <span id="STK4" class="c1"><img src=/HomeV1/images/down.gif width=8 height=8>701.53</span> <a href=javascript:ShowImg('399300',1) target=_self><b><font color=#000000>沪深300</font></b></a> <span id="STK5">3858.52</span> <span id="STK6" class="c1"><img src=/HomeV1/images/down.gif width=8 height=8>181.96</span> <b>香港恒生</b> <span id="STK7">21938.22</span> <span id="STK8" class="c3"><img src=/HomeV1/images/up.gif width=8 height=8>232.66</span> <b>道琼斯</b> <span id="STK9">13414.48</span> <span id="STK10" class="c1"><img src=/HomeV1/images/down.gif width=8 height=8>13.25</span> <b>纳斯达克</b> <span id="STK11">2612.02</span> <span id="STK12" class="c3"><img src=/HomeV1/images/up.gif width=8 height=8>6.67</span>
<div id="indexdata"><object id="STKData" width="0" height="0" classid="CLSID:333C7BC4-460F-11D0-BC04-0080C7055A83" viewastext><param name="FieldDelim" value="F"><param name="DataURL" value="/HomeV1/text/StockIndex.htm"><param name="UseHeader" value="true"></object><input type="hidden" id="STKValue" datasrc="#STKData" datafld="a" name="STKValue"></div>
因为我不是为了介绍正则表达式而写这篇文章的,所以对正则表达式不会做太多的介绍,如果大家对正则表达式有兴趣或想进一步了解的话可以参考:
JAVA中正则表达式的应用
http://www.ibm.com/developerworks/cn/java/l-regp/part1/index.html
http://www.ibm.com/developerworks/cn/java/l-regp/part2/index.html 另外因为为了抓取其他东西,代码已经被我改的面目全非了,暂时就不方便贴出来了,请大家谅解,如果大家有什么疑问的话可以和我联系,我会尽量说明清楚的。
posted @
2007-06-28 22:58 steady 阅读(1784) |
评论 (2) |
编辑 收藏
最近股市大牛,相信这里的不少朋友都在炒股,当然上班时间老是开着网页看股市或是盯着红红绿绿的专业股票软件是总是担心被周围同事看到的,但又不时的想着大盘是涨了还是跌了,自己的股票又是如何呢。
于是用 Java 写了一套简单的股市信息跟踪的小程序,Console 的,用于抓取相应的股市信息并显示到 console 中,谁也不会想到这个东西会是用来看股市的吧。
这套小小的程序用到了几个非常简单的技术,HttpClient 和 正则表达式。程序功能非常简单,找到含有股市数据的页面,使用 HttpClient 抓取下来,通过正则表达式匹配自己需要的内容,在 Console 上打印出来。
准备花两篇文章简单的介绍这个小系统中的实现细节,当然这只是简单的介绍,其实我们再稍微用点其他的技术,可以做出更多更实用的小工具。比如我就写了个小爬虫,把某个基金网站上的基金净值数据爬来了,足足有10W条,供我做基金形势分析之用,拿到这些原始数据,再动用一下自己的头脑,再配合一些方便的工具,比如 Excel,我们便可以用实际数据去辅助投资理财。
首先我们来简单的介绍我们用到的第一个工具,HttpClient。
HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
以下列出的是 HttpClient 提供的主要的功能,要知道更多详细的功能可以参见 HttpClient 的主页。
实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
支持自动转向
支持 HTTPS 协议
支持代理服务器等
HttpClient 可以在http://jakarta.apache.org/commons/httpclient/downloads.html下载
HttpClient 基本功能的使用
GET 方法
使用 HttpClient 需要以下 6 个步骤:
1. 创建 HttpClient 的实例
2. 创建某种连接方法的实例,在这里是 GetMethod。在 GetMethod 的构造函数中传入待连接的地址
3. 调用第一步中创建好的实例的 execute 方法来执行第二步中创建好的 method 实例
4. 读 response
5. 释放连接。无论执行方法是否成功,都必须释放连接
6. 对得到后的内容进行处理
根据以上步骤,我们来编写用GET方法来取得某网页内容的代码。
根据这样的过程,我们便可以写出一个简单的抓取页面的方法,该方法返回抓到的页面数据。传入的参数是页面的 URL。
protected String getURLResponse(String url) {
try {
HttpClient client = new HttpClient();
GetMethod method = new GetMethod(url);
int returnCode = client.executeMethod(method);
String response = null;
if (returnCode == 200) {
response = EncodingUtil.getString(method.getResponseBody(), "gb2312");
}
method.releaseConnection();
return decode(response);
} catch (Exception e) {
return null;
}
}
HttpClient 是一个很实用的工具,用它,我们可以做很多和 Http 有关的事情。
大家可以参考: http://www.ibm.com/developerworks/cn/opensource/os-httpclient/ 来初步了解 HttpClient 的功能。
或是去找找 Jakarta.Commons.Cookbook 或者 Jakarta.Commons.Online.Bookshelf,上面介绍了包括 HttpClient 在内的很多 Apache Jakarta Commons 项目,相信合理使用,会让你事半功倍的。
下一篇我们将介绍一下如何用正则表达式处理我们抓取到的数据。
posted @
2007-06-21 22:11 steady 阅读(1919) |
评论 (5) |
编辑 收藏
摘要: Java Platform Debugger Architecture(JPDA:Java平台调试架构) 由Java虚拟机后端和调试平台前端组成
1.Java虚拟机提供了Java调试的功能
2.调试平台通过调试交互协议向Java虚拟机请求服务以对在虚拟机中运行的程序进行调试
阅读全文
posted @
2007-06-18 16:20 steady 阅读(819) |
评论 (0) |
编辑 收藏
最近在把在 tomcat 5.5 上开发的项目 deploy 到 JBoss 4.2 上时,在操作一段时间就会出现 java.lang.OutOfMemoryError: PermGen space,开始以为是代码中存在死循环的地方造成这样的问题,但是后来发现,出问题的地方都是随机的,并不是某一处造成这样的问题出现,怀疑是内存泄露,通过增大 heap 内存的方法来尝试,依然不行,但是同样的问题却并没有在 tomcat 中出现过,难道是 JBoss 的问题?
在网上做了一番搜索得到一些相关的内容。
PermGen space的全称是Permanent Generation space,是指内存的永久保存区域OutOfMemoryError: PermGen space从表面上看就是内存益出,解决方法也一定是加大内存。说说为什么会内存益出:这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。
改正方法,在 run.bat 中加入:-Xms256m -Xmx512m -XX:MaxNewSize=256m -XX:MaxPermSize=256m
因为项目中引用了很多的 jar 包,而这些 jar 包中的 class 信息会被 JBoss 的 class loader 加载到 PermGen space 区域,在 JVM 默认的情况下,该部分空间的大小只有 4M,在 jar 包非常多的情况下,显然是不够用的,所以通过 -XX:MaxPermSize=256m 指定最大值后即可解决问题。
另外,如果 heap 内存不足出现 java.lang.OutOfMemoryError: Java heap space 时,可以通过 -Xmx512m 指定最大 heap 内存来解决这样的问题。
posted @
2007-06-17 20:13 steady 阅读(16778) |
评论 (7) |
编辑 收藏
JBoss 4.2 GA 已经发布有一段时间了,主要还是一些 bug fix 已经一些新的包的加入。感觉比较爽的是解决了过去不太好用的一些地方。
过去在用 JBoss 4.0.5 的时候一直被 Log 的问题困扰,如果在自己的项目里加入 log4j 和 common logging 的话,必然会出错,所以我们不得以,必须通过一些调整手段来处理这样的问题,也就是每次在 tomcat 下调试的应用,需要改点东西才能 deploy 到 JBoss 上去,但使用了 4.2 以后就没有这样的问题了,在 tomcat 下用的包直接放过去,没有做任何的修改就可以正常使用了。
因为我项目用的是 commons-lang 2.3 而 JBoss 4.0.5 用的是 2.1 每次使用 commons-lang 2.1 里面没有的方法时,就会出现 NoSuchMethodException,最后只好把 JBoss 下所有的 commons-lang 的包用 2.3 的替换掉,而 4.2 已经没有这个问题了,2.3 已经可以正常使用了。
默认的 JBoss 4.2 我只能用 localhost 访问,不能用 IP 地址访问,后来发现,需要修改 jboss-4.2.0.GA\server\default\deploy\jboss-web.deployer\server.xml 把 Connector 下面的 address 改成对应的 IP 或者 0.0.0.0 就可以用 IP 访问了。
后面附上了 Release Note 中的一些内容。
This is the final release of JBoss Application Server v4.2.0. JBoss AS 4.2 is a stepping stone from JBoss 4.0 to JBoss 5.0. It combines a lot (but not all) of the exciting new features of JBoss 5, but based on the stable 4.x MicroKernel architecture.
Highlights
* JDK5 is *required* to run JBossAS 4.2.x. The decision was based on the fact that JDK1.4 is phased out and the reality that a lot of people like Java Annotations support and want to combine EJB3 and JBoss Seam components with JBossAS. JDK6 is not formally supported yet, although you may be able to start the server with it. JDK6 support will come with JBossAS 5.x.
* JBoss EJB3 is now deployed *by default* in JBossAS 4.2.x The fact that we base on JDK5 makes our life easier in this regard, meaning we don't have to maintain jdk5 code retro-weaved for jdk1.4 runtimes, and we can include by default components that require jdk5 to run.
* JBoss Web v2.x is the web container in JBossAS 4.2, an implementation based on Apache Tomcat that includes the Apache Portable Runtime (APR) and Tomcat native technologies to achieve scalability and performance characteristics that match and exceed the Apache Http server. In the absence of the native libraries in the JBoss classpath, JBoss Web falls back to the standard non-native connector mode. The native libraries need to be downloaded and installed separately.
* JBoss Transactions v4.2 is the default transaction manager for JBossAS 4.2. JBoss Transactions is founded on industry proven technology and 18 year history as a leader in distributed transactions, and is one of the most interoperable implementations available. The JTA version of JBoss Transactions included with the server provides for fully recoverable transactions. For distributed transaction support the JTS version of JBoss Transactions will need to be used. Furthermore, it is always possible to fall back to the legacy JBossTM fast in-memory transaction manager implementation, if necessary.
* JBossWS is the web services stack for JBoss 4.2 providing Java EE compatible web services. It has been upgraded to v1.2.1.GA
* JGroups/JBossCache were upgraded to the latest releases. The server is already configured to support channel multiplexing, when it becomes available.
* JBoss Remoting was upgraded to the latest stable 2.2.x version. This was done in order to align dependencies with the thirdparty libraries required by the new JBoss Messaging, which means that, if you want, you can replace the default JBossMQ messaging provider with JBoss Messaging, without having to revert to a scoped deployment.
posted @
2007-06-07 10:09 steady 阅读(2741) |
评论 (1) |
编辑 收藏
新的一年开始,按理说要对去年的什么东西做一番总结了,当然总结很多了,这次先总结一下 JSF 了,毕竟这对我来说是今年最主要的技术方向,对它也算是比较熟悉了,虽然没有非常深入的去研究它,但从一年多的使用和理解来说,还是有不少自己的心得的,在新的一年到来之际,把这些东西记录下来,重新记起这个让我欢喜让我忧的 JSF。静观这一年 JSF 的发展,没有太多的兴奋,也没有太多的欢喜,更多的是平静,与同一时间大红大紫的 Ajax 和 RoR 相比,JSF 带给我们的更多是平静,静的让人心里发慌,上半年可以说还是稍有一些波涛了,而随着月份的数字越来越大,波涛是越来越小了。
可以说各大厂商在互相妥协让步的基础之上,把 JSF 实用化的实现版本的重任交到了 Apache Myfaces 项目上,而 Oracle 也将其 ADF Faces 的实现捐给了 Apache,而现在我们可以见到的 JSF 实现也主要就是 Myfaces 了,当然 Sun 自己也有一套实现,当然这只是一种不够健壮,并且功能有限的实现版本,一般不会拿来做正式的项目的。刚过完年 Myfaces 1.1.2 和 Tomahawk 1.1.2 正式发布,这是过去 Myfaces 1.1.1 的一个 bug 修复版本,离上一个版本已经有半年左右的时间了,而项目组的同事们也在与 Myfaces 1.1.1 的 bug 斗争了半年才用到这个新的版本。随后的 Myfaces Core 1.1.3 / 1.1.4 则在几乎一个月内发布,而 1.1.5 和 Tomahawk 1.1.4 则至今没有动静,虽然由 Myfaces 每次发布带给我们的 new feature 已经不是那么的多了,但是还是期盼新的版本能够给我们带来新的惊喜。
五月份的时候 JavaEE 5 最终标准发布了,JSF 1.2 终于被正式提上了日程,这是一个对过去标准的一个修复版本,修正了上一个标准中的诸多问题,比如 JSTL 兼容性问题,还有一些细节性的改动,都是过去在 JSF 1.1 标准中非常折磨人的问题,但新的 1.2 标准依赖于 JDK 1.5,依赖于一系列新的 JavaEE 5 的 API,比如 Servlet 2.5, JSTL 1.2 而这些新的 API 也是在紧锣密鼓的开发中,所以 Myfaces 1.2 的开发进程也一直很慢,因为其中出现的问题不光是 Myfaces 自己的问题,或许还有 Tomcat 6 的问题,或是其他的问题。而另一方面 Sun 也发布了一个 JSF 1.2 的实现版本,是由 JSF 1.2 的标准的主笔领导开发的,按照我对于 Sun JSF 上个版本的表现,我对于这个新的实现也不抱有太多的希望,或许它更多的只是一种象征了,象征着 JSF 1.2 的正式推出。
开源领域的 JSF 相关的项目发展缓慢。Myfaces 在一年内没有给我们带来太多的惊喜。曾经做为黑马出现的 JSF 扩展框架 Shale 至今还没有给大家带来一个满意的答复,一直以 develop 版本发布出来给大家尝鲜用,虽然慢慢的在前进,但是却很难带给大家什么惊喜,或许会被人逐渐的淡忘。而去年年底由 Oracle 捐给 Apache 的 ADF Faces 也是至今没有太大的动静,同样作为兄弟项目的 Struts 2 从提出到现在也有一年了,还没有能提供一个正式的版本给我们用,作为 Apache 的项目,这样的发布速度,确实很让人不能满意,而作为另一个大型的开源组织 Eclipse,则在一个个 Milestone 下有条不紊的向前推进,不断蚕食着别人所占据的地盘。
作为 JSF 整体应用平台一个重要的部分,第三方组件库的发展有不小的突破,但是真正的应用度似乎不是很高,这一年内出现了很多优秀的商业,开源的组件库,除去上面我们提到的 Myfaces Tomahawk, Oracle ADF 之外,还出现了 ICEFaces, BackBase,WebGalileo Faces,另外在 .Net 领域的组件提供商 Infragistics 也通过收购发布了 NetAdvantage for JSF 2006 这样的组件库。另外一直在 JSF IDE 上有所作为的 Exadel 公司也在 JSF 组件上插上一手,一方面发布了其开源的 JSF 框架 Ajax4JSF 另一方面在其基础上提供了一个商业的 JSF 组件库 VCP,这样的方式确实有一套,可以同时抓住两方面的市场。另一方面国内也出现了像金碟这样基于自己 Apusic Application Server 的开源 JSF 组件库,是一件值得我们国人骄傲的事情,不过由于其只能够运行于 Apusic 上,使其应用面受到了不小的限制。
让我们再来看看这一年 JSF 相关 IDE 在今年的作为了,在 06 年春节期间,一些支持 JSF 的 IDE 像赶集一样不断的推出来,先后有 MyEclipse 4.1 GA,Sun Java Studio Creator 2, Oracle JDeveloper, BEA Workshop Studio 3.0,在这一段时间推出。MyEclipse 和 BEA Workshop 是 Eclipse 的插件,而 JDeveloper 和 Creator 是基于 Swing 的,不过随着时间的推移,大家真正在用的 JSF 开发工具也主要就是 MyEclipse 和 Workshop,不过 MyEclipse 在 JSF 上想和 Workshop 拼,还需要一些时日了,另外在九月份正式发布的 IntelliJ IDEA 6.0 也开始支持 JSF 了,当然是用其独特的方式去支持,虽然不提供图形化的所见即所得的开发方式,但由于其 IDE 内部各个部分间完美的组合,使得其在写代码的感觉上要远远超过的其他竞争者,这也正是独立 IDE 和插件 IDE 一个重要的功能区别。
纵观 06 年的 JSF 的发展历程,我还是对 07 年的 JSF 的发展很期待,希望 Myfaces 基于 JSF 1.2 的实现能够尽快的推出,也能够有更多更好的开源组件库的出现。
posted @
2007-01-05 09:22 steady 阅读(2221) |
评论 (6) |
编辑 收藏