在我以前的意识里,觉得用JavaScript或Ajax提交文件表单似乎是一件麻烦的事情,也没有太仔细的研究,后来看jQuery的时候,发现了jQuery Form Plugin这个插件,它方便的实现了Ajax方式的表单提交,例子里也包括了文件表单的提交,那我也来试一下吧,还是用Kohana(最近专注于这个,而且PHP开发要快多了,要是用Struts,要费好多功夫)。
要Kohana支持上传,先要配置一些upload的参数,把system\config\upload.php拷贝到application/config下,里面的参数做好设置,具体参考Kohana的文档吧,之后创建一个Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| class Myupload_Controller extends Top_Controller {
public function index() {
$view = new View ("upload");
$view->msg = "Upload File";
$view->render ( TRUE );
}
public function upload() {
$filename = upload::save('myfile');
echo $filename;
exit ();
}
} |
Top_Controller为我自己创建的类,也继承自Kohana的Controller,之后创建upload.php的view文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| <html>
<head>
<title><?php echo $msg;?></title>
<script type="text/javascript" src="<?=url::base()?>js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="<?=url::base()?>js/jquery.form.js"></script>
<script type="text/javascript">
// wait for the DOM to be loaded
$(document).ready(function() {
var options = {
target: '#fileinfo' // target element(s) to be updated with server response
};
$('#myForm').submit(function() {
$(this).ajaxSubmit(options);
return false;
});
});
</script>
</head>
<body>
<h2><?php echo $msg;?></h2>
<form id="myForm" action="<?=url::base()?>myupload/upload" method="post"
enctype="multipart/form-data">
<input name="myfile" type="file" />
<input type="submit" value="Submit Comment" />
</form>
<div id="fileinfo"></div>
</body>
</html> |
在这里我们用jQuery Form Plugin来提交表单,之后将信显示在“fileinfo”这个div里,去试试效果吧。
在http://malsup.com/jquery/form/里有详细的API和例子,同时http://malsup.com/jquery/里也有其他的一些不错的jQuery的插件。
Kohana是一个使用PHP5的面向对象的MVC框架,是从CodeIgniter衍生出来,研究了几天,感觉还不错,就是它的文档实在太简陋了,在看到它的Events机制和Hooks机制时,确实有点不明白,文档上说的实在太简单了,后来我在Google上搜索了一下,找到两篇文章《Events and hooks in Kohana》和《Practical Kohana Hooks example: PHPIDS》,上面讲了一下Kohana的Events和Hooks,并举了例子,我也开始慢慢理解了它的含义。
在Kohana的Events中,默认定义了很多的Events(例如system.ready、system.pre_controller等等),中文理解就是事件,也就是触发点,在程序在运行到某个位置时,会被触发,具体就是调用Event::run方法,我们在Kohana.php里可以看到在不同的位置执行了不同的Event::run方法,那么Hooks的意义在于当一个事件被触发之前,可以通过已加载的Hooks来修改事件的回调,有点绕口,说白了就是在事件发生之前,做点事情,举个例子,你安排了今天的日程,下午3点要开会,那么在3点开会就是一个Event(事件),那么到3点的时刻,你希望提醒你一下,你在你的手机里定了一个闹钟,在3点的时候会响,这就是一个Hook,可以看出Hook是基于Event的。
我们可以创建自己的Hook程序,并加载如默认的Events里,但是默认的Events不一定能满足我们的需要,比如我们在Web应用中经常使用的权限校验,判断这个用户是否登陆过,我们虽然可以使用默认Events里的system.pre_controller,但是这个Event是针对所有的Controller的,有些Controller是不需要校验用户的,还好Kohana允许自己定义Event,下面我们还是举例说明吧。
要使用Hooks,首先要在application/config/config.php里将$config['enable_hooks']置为TRUE。
之后我们定义自己的Event,我们在application/controllers目录下建立base.php,代码如下:
1
2
3
4
5
6
7
| class Base_Controller extends Controller {
public function __construct() {
parent::__construct();
Event::run("base.construct");
}
} |
我们继承了Kohana的Controller,在构造函数里定义了Event,名字叫“base.construct”,以后我们的Controller都继承自Base_Controller,那么在对象创建的时候都会触发base.construct事件。
Hook的文件放在application/hooks下,我们就创建一个hook文件sessioncheck.php,代码如下:
1
2
3
4
5
6
7
8
9
| class SessionCheck {
public function check() {
echo "check session ...";
}
}
Event::add('base.construct', array('SessionCheck','check')); |
我们将SessionCheck的check方法加载到了base.construct事件上,也就是在触发base.construct事件之前,会执行SessionCheck的check方法。
接下来我们写一个Controller,在application/controllers目录下建立first.php,代码如下:
1
2
3
4
5
6
7
| class First_Controller extends Base_Controller {
public function index() {
echo "First - index";
exit();
}
} |
我们执行一下看看会有什么提示,http://localhost/kohana/first,显示
check session …First – index
没问题了,在Controller构造时,执行了Hook里的方法。
在Blog或新闻发布的时候,我们希望URL是一段有意义的字串,例如我Blog里的《Linux下切分Tomcat的catalina.out日志文件》文章链接是http://i.laoer.com/2009/02/18/rotating-catalina-out-in-tomcat-using-cronolog/,这样有利于SEO(搜索引擎优化),对于我们母语为中文的小虾,有时候要翻译标题还是有点头疼的,还好有了Google翻译,让翻译的事情变得简单了一点,但对于开发者,怎么使用户也方便的翻译,特别是在写Blog的时候就能把标题翻译好,还要动点脑筋,我看到JavaEye里发布新闻的地方有个“让Google帮助生成永久链接”的功能挺好的,看了一下他们的源码,得到以下这段,顺别也解释一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| <script type="text/javascript" src="http://www.google.com/jsapi"></script> //载入Google的jsapi
<script type="text/javascript">
function slugify(str) { //这个方法应该是将字符转为小写,并把一些特殊字符转为"-"
return str.toLowerCase().replace(/[^a-z0-9-_]+/g, '-').replace(/^-|-$/g, '');
}
google.load("language", "1"); //载入Google的language Ajax库
function translate_title() { //这里就是翻译文章标题了,里面的方法需要jQuery支持,之前要引入jQuery的包,这里就省略了
if($F("news_title").blank()) {
alert("请先填写标题");
return;
}
$("news_slug_url").value = "正在翻译中...";
google.language.translate($F("news_title"), "zh", "en", function(result) {
if (!result.error) {
$("news_slug_url").value = slugify(result.translation);
}
});
}
</script> |
这里有个地方要说一下,Google的Ajax库API还是挺好的,可以load几种Ajax的库,另外Google的Web 工具包也可以看看。
在SQL/PLUS下,先检查一下当前连接数
show parameter process;
show parameter session;
修改命令,根据自己实际情况修改数值
alter system set processes=300 scope = spfile;
alter system set sessions=350 scope = spfile;
之后重启Oracle
随着Tomcat的运行,catalina.out文件会越来越大,虽然Tomcat每日会生成一个catalina.ymd.log的文件,但catalina.out主文件仍然不断增加,需要对catalina.out按日切分才好,在网上找了一下,看到一篇《rotating catalina.out in tomcat 5.5 using cronolog》,就用公司的Tomcat配置一下。
cronolog工具已经在服务器上装过,一个对日志切分的小工具,其主页在http://cronolog.org/,我们也用它来切分Apache的日志。
进入Tomcat的bin目录,打开catalina.sh文件,找到tomcat启动的相关行,或者你直接查找catalina.out,一般我们修改下面行中的内容(因为我们一般不会在-security条件下运行),
1
2
3
4
5
6
7
8
9
10
11
12
13
| else
“$_RUNJAVA” $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs=”$JAVA_ENDORSED_DIRS” -classpath “$CLASSPATH” \
-Dcatalina.base=”$CATALINA_BASE” \
-Dcatalina.home=”$CATALINA_HOME” \
-Djava.io.tmpdir=”$CATALINA_TMPDIR” \
org.apache.catalina.startup.Bootstrap “$@” start \
>> “$CATALINA_BASE”/logs/catalina.out 2>&1 &
if [ ! -z "$CATALINA_PID" ]; then
echo $! > $CATALINA_PID
fi
fi |
修改
org.apache.catalina.startup.Bootstrap “$@” start \
>> “$CATALINA_BASE”/logs/catalina.out 2>&1 &
为
org.apache.catalina.startup.Bootstrap “$@” start 2>&1 \
| /usr/local/sbin/cronolog “$CATALINA_BASE”/logs/catalina.%Y-%m-%d.out >> /dev/null &
同时,上面有一行
touch “$CATALINA_BASE”/logs/catalina.out
可以注释掉,完成之后重起Tomcat就可以了,在logs目录下可以看到catalina.2009-02-18.out的日志,是按日生成的。
自定义Mysql启动命令
/usr/local/mysql/bin/mysqld –defaults-extra-file=/usr/local/mysql/my.cnf –basedir=/usr/local/mysql –datadir=/usr/local/mysql/data –user=mysql –log-error=/usr/local/mysql/data/localhost.localdomain.err –pid-file=/usr/local/mysql/data/localhost.localdomain.pid –socket=/tmp/mysql.sock –port=3306
通过定义里面的参数,可以在一个机子上启动多个Mysql实例在不同的端口
CREATE USER ‘username’@'%’ IDENTIFIED BY ‘password’;
创建用户,%代表可以来自任何主机,如果是本机,可以写localhost
GRANT ALL PRIVILEGES ON * . * TO ‘username’@'%’ IDENTIFIED BY ‘password’ WITH GRANT OPTION MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0
给用户赋所有权限,也可以根据需要,赋特定的权限
导出一个库
mysql/bin/mysqldump -u user -p password dbname > /full/path/dbname.sql
导入一个库
mysql -u user -p password –default-character-set=utf8 dbname < /full/path/dbname.sql
–default-character-set是指定数据库编码
方法一:
1. 执行rpm -i your-package.src.rpm
2. cd /usr/src/redhat/SPECS
3. rpmbuild -bp your-package.specs 一个和你的软件包同名的specs文件
4. cd /usr/src/redhat/BUILD/your-package/ 一个和你的软件包同名的目录
5. ./configure 这一步和编译普通的源码软件一样,可以加上参数
6. make
7. make install
方法二:
1. 执行rpm -i you-package.src.rpm
2. cd /usr/src/redhat/SPECS (前两步和方法一相同)
3. rpmbuild -bb your-package.specs 一个和你的软件包同名的specs文件
这时,在/usr/src/redhat/RPM/i386/ (根据具体包的不同,也可能是i686,noarch等等) 在这个目录下,有一个新的rpm包,这个是编译好的二进制文件。执行:
rpm -i new-package.rpm即可安装完成。
最近在公司里做一些Java Web开发的培训,同时对已经做的一些工程做一些ReView,现在的工程里,工程师直接使用JSTL取得Action里的属性,这个用法我以前到真的没有用过,因为在我印象中,Struts2的这些Action属性,应该是在ValueStack中,而在某些情况下,从ValueStack取值是件挺麻烦的事情,在做天乙社区8时,我就参考Struts2的标记库,自己扩展标记库,从而取得ValueStack里的值,而JSTL应该是从Page、Request、Session和Application里顺序取值,莫非Struts2将ValueStack里的值也放入了Request?同时我们直接用EL标签也直接取出了Action的属性值,莫非真的放入了Request?但是打开Struts2的Debug,发现Request里并没有值。
带着这个疑问,我Google了一下,很快找到答案:
提问:在Struts2中,如何使用JSTL来读取Action中的变量?
这是一个历史悠久的问题。因为事实上,很多朋友(包括我在内)是不使用Struts2自身的标签库,而是使用JSTL的,可能因为JSTL标签库比较少,简单易用的原因吧。
我们知道,JSTL默认是从page,request,session,application这四个Scope逐次查找相应的EL表达式所对应 的对象的值。那么如果要使用JSTL来读取Action中的变量,就需要把Action中的变量,放到request域中才行。所以,早在 Webwork2.1.X的年代,我们会编写一个拦截器来做这个事情的。大致的原理是:在Action执行完返回之前,依次读取Action中的所有的变 量,并依次调用request.setAttribute()来进行设置。具体的整合方式,请参考以下这篇文档:http://wiki.opensymphony.com/display/WW/Using+WebWork+and+XWork+with+JSP+2.0+and+JSTL+1.1
不过随着时代的发展,上面的这种方式,已经不再被推荐使用了。(虽然如此,我们依然可以学习它的一个解决问题的思路)目前来说,自从 Webwork2.2以后,包括Struts2,都使用另外一种整合方式:对HttpServletRequest进行装饰。让我们来看一下源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| public class StrutsRequestWrapper extends HttpServletRequestWrapper {
/**
* The constructor
* @param req The request
*/
public StrutsRequestWrapper(HttpServletRequest req) {
super(req);
}
/**
* Gets the object, looking in the value stack if not found
*
* @param s The attribute key
*/
public Object getAttribute(String s) {
if (s != null && s.startsWith("javax.servlet")) {
// don't bother with the standard javax.servlet attributes, we can short-circuit this
// see WW-953 and the forums post linked in that issue for more info
return super.getAttribute(s);
}
ActionContext ctx = ActionContext.getContext();
Object attribute = super.getAttribute(s);
boolean alreadyIn = false;
Boolean b = (Boolean) ctx.get("__requestWrapper.getAttribute");
if (b != null) {
alreadyIn = b.booleanValue();
}
// note: we don't let # come through or else a request for
// #attr.foo or #request.foo could cause an endless loop
if (!alreadyIn && attribute == null && s.indexOf("#") == -1) {
try {
// If not found, then try the ValueStack
ctx.put("__requestWrapper.getAttribute", Boolean.TRUE);
ValueStack stack = ctx.getValueStack();
if (stack != null) {
attribute = stack.findValue(s);
}
} finally {
ctx.put("__requestWrapper.getAttribute", Boolean.FALSE);
}
}
return attribute;
}
} |
看到了嘛?这个类会在Struts2初始化的时候,替换HttpServletRequest,运行于整个Struts2的运行过程中,当我们试 图调用request.getAttribute()的时候,就会执行上面的这个方法。(这是一个典型的装饰器模式)在执行上面的方法时,会首先调用 HttpServletRequest中原本的request.getAttribute(),如果没有找到,它会继续到ValueStack中去查找, 而action在ValueStack中,所以action中的变量通过OGNL表达式,就能找到对应的值了。
在这里,在el表达式广泛使用的今天,JSTL1.1以后,也支持直接使用el表达式。注意与直接使用struts2的tag的区别,这里需要使用el的表示符号:${}
例如:${user.name}, <c:out value=”${department.name}” />
原来是这样,学无止境啊,很多东西需要仔细去研究。
离最初用PHP编程序已经有8、9年时间了,后来这6、7年的时间一直研究Java,对PHP有些生疏了,但PHP的生命力却依旧顽强,对于面向Web开发时Java的繁琐,我最近又将注意力集中到了PHP上,但已经习惯了Struts这样的MVC框架,我也要寻找一个适合的PHP MVC框架,选择的标准有几个:1、性能;2、易用性;3、文档;4、长期支持度
我最开始看了Zend Framework,Zend的东西,毕竟带有官方特性,他的framework应该是代表着主流,看了之后,Zend Framework可以说是纷繁复杂,但是面面俱到,Web应用方面的问题基本都可以解决,我唯一担心的就是性能,虽没有做过测试,但也确实担心。
后来有一天在JavaEye上逛,看到一篇帖子《PHP框架的繁荣是正确的发展方向吗?》,讨论了PHP的运行机制、与ROR的比较、性能等等,非常热闹,同时也列举出了一些PHP的框架,特别是一些性能比较,让我很吃惊,CakePHP、Symfony可以不用考虑了。
接下来我看了看CodeIgniter,感觉不错,简单,相比Zend Framework要简单得多,大多数问题也都能解决,性能在一些资料描述中也表现的尚可(比Zend Framework要快几倍),而且其文档比较细,学习起来不难,后来又发现了Kohana,Kohana是从CodeIgniter衍生出来,由于CodeIgniter是兼容PHP4和5的,而Kohana只支持PHP5,是完全的OO方式,其文档并还没有仔细研究,看到了一个比较的文章《Notes on Choosing a PHP Framework: A Quick Comparison of CodeIgniter and Kohana》,看上去Kohana有些特性还是很优秀的,但不知道Kohana社区对于这个开源产品的支持有多好。
后来又看到文章《Performance of Yii》,发现Yii这个框架的性能更强劲啊,比CodeIgniter还要好几倍,不可思议,看了看Yii的文档,它也是完全OO的,要PHP5以上,核心应该也比较简单,能保持比较好的性能,但我觉得它的Guide文档比较粗,学习起来似乎要费点功夫,其性能应该是我最感兴趣的地方。
再说说国内的PHP框架,在JavaEye的文章里,QeePHP的作者也在推荐自己的框架,简单测试下比Yii还要快,好NB啊,但从社区反应出来其文档不够详细,其代码我也没有细看,似乎和Yii有很多相近的地方,另一个国内的PHP框架ThinkPHP文档比较详尽,但没有测试报告,不知道性能如何,而且在PHPChina的社区里和QeePHP有激烈的争论,挺有意思的。
看了一大圈,我也没有决定采用何种PHP的框架,他们各有长处,也各有缺陷,但综合考虑,我还是应该会在CodeIgniter、Kohana和Yii中选择最终的方案。
在公司上不了http://apiwiki.twitter.com/,难道又被封了?找个代理上去看看吧,把它的Libraries记录下,备用
ActionScript/Flash
C++
- QTwitLib by Bradley Lackey & Maks Zolin. C++ library for Linux, Windows, and Mac. Currently in beta.
C#/.NET
- Yedda Twitter Library by Yedda. Every Twitter API method has an equivalent .NET method in this wrapper library.
- TwitterooCore API by Eric Willis/RareEdge Design Group. Binary .NET library that can be used in any .NET project.
- Twitterizer originally by DigitallyBorn, but now open source. Written for .NET 2.0.
- tweet# by Daniel Crenna. “100% coverage of the REST and Search APIs”.
Java
- Twitter4J by Yusuke Yamamoto. BSD licensed and Maven aware pure java interface for the Twitter API.
- java-twitter by DeWitt Clinton. Pure java interface for the Twitter API.
- jtwitter by Daniel Winterstein. Open-source pure Java Interface to Twitter.
Objective-C/Cocoa
- MGTwitterEngine by Matt Gemmell. Integrate Twitter support into your Cocoa app.
Perl
- App::Tweet by Joshua McAdams. Tweet on Twitter from the command line.
- Net::Twitter by Chris Thompson. Perl interface to Twitter.
- Twitter::Shell by Daisuke Maki. Twitter from your shell.
PHP
PL/SQL
- OraTweet by Noel Portugal. PL/SQL procedures to get friends timeline and post updates.
Python
- python-twitter by DeWitt Clinton. This library provides a pure Python interface for the Twitter API.
- python-twyt by Andrew Price. BSD licensed Twitter API interface library and command line client.
- twitty-twister by Dustin Sallings. A Twisted interface to Twitter.
Ruby
- Twitter4R by Susan Potter. Open-source Ruby library for the Twitter REST API.
- Twittery by Chris Ledet. Lightweight class for Twitter’s API.
- Twitter by John Nunemaker. Command line twits and an api wrapper using Hpricot.