2009年4月24日星期五

javascript 缺少对象

经常遇到javascript 缺少对象的错误,无外乎调用的js方法未定义,名字写错了,之类,今儿遇到的郁闷的
我在页面中加了一个注释 <!-- -- >,注意结束标签--和>之间有个空格,结果未起作用,结果可想而知,找了半天才找到

蒲公英dandelion flower



将blogger原有标签label widget改成标签云形式

通过简单修改,将blogger原有标签widget改成标签云形式
修改html模板
找到
<b:loop values='data:labels' var='label'>
..........
</b:loop>
将<b:loop>标签之间的内容改成:


<b:if cond='data:blog.url == data:label.url'>

<span expr:dir='data:blog.languageDirection'>

    <font expr:size='data:label.count'><data:label.name/></font>

</span>

<b:else/>

<a expr:dir='data:blog.languageDirection' expr:href='data:label.url'>

    <font expr:size='data:label.count'><data:label.name/></font>

</a>

</b:if>

<span dir='ltr'>(<data:label.count/>)</span>
OK啦 看看效果吧

2009年4月22日星期三

自己用jquery 实现 google blogger 首页文章摘要

早就注意到google blogger 首页文章不能只显示摘要,而是全部显示
google了几个网页提供的方法,官方的方式是在文章中加一个span,让当在首页显示时span隐藏,这种方式只适合以后新增文章,以前的旧文章均没有加入这个span,就不好使
想到blogger这么高度自定义,那么用jquery实现吧
经过一个晚上的实验,终于出结果了

修改html模板,在<head>下面加入<b:if cond='data:blog.pageType != "item"'>
   <script src='http://www.google.com/jsapi'/>
       <script type='text/javascript'>
            google.load('jquery', '1.3.2');
       </script>
       <script language='javascript' src='http://www.reindel.com/truncate/jquery.truncate.js' type='text/javascript'/>
       <script type='text/javascript'>
       $(function() {
           $("div[class='post-body entry-content']").truncate( 90, {
               chars: /\s/,
               trail: [ " ( <a href='#' class='truncate_show'>more</a> . . . )", " ( . . . <a href='#' class='truncate_hide'>less</a> )" ]
           });
       });
       </script>
       </b:if>
保存,就大功告成啦,看效果http://liuspring.blogspot.com/
经测试,IE7中会提示:是否停止运行脚本?此页面的脚本造成Internet Explorer 运行速度减慢,如果继续运行,您的计算机将可能停止响应
在FireFox3和Google Chrome中没有什么提示,速度还挺快,但会有显示问题,因为应用的jquery.truncate框架有浏览器兼容问题

2009年4月19日星期日

搬家到Google blogger

step1 blogbus注册一用户,然后用其首页的搬家工具导出sohu博客的内容。

step2 yo2注册一用户,导入step1得到的文件,再导出。

step3 在http://wordpress2blogger.appspot.com/转换step2得到的文件。

这是转换好的文件是符合blogger规范的,可以直接导入

部署我的Google App Engine(二)

手上有四个版本的Linux,Ubuntu,Redhat,Fedora,openSUSE,都装过,后来感觉还是Fedora比较好用,我装的是

Fedora9,Fedora10正在下载中

以下Linux安装配置,仅限于在Fedora9上安装通过,资料都是通过Google搜索得来,感谢各位网友,网络的力量真是强大。

1、在VMware中装上Fedora9后,首先安装VMware-tools,方便与主机交互

首先需要下载相应的kernel-devel.rpm包进行安装
首先查看内核版本:uname -r一下,我的是2.6.25-14.fc9.i686,

所以下载kernel-devel-2.6.25-14.fc9.i686.rpm,然后运行rpm -ivh kernel-devel-2.6.25-14.fc9.i686.rpm 进行安装. 内核安

装完毕后,需要用这个命令确定内核 C header 的安装目录:ls -d /usr/src/kernels/$(uname -r)*/include

安装内核具体步骤如下:

[root@localhost ~]# uname -r
2.6.25-14.fc9.i686
[root@localhost ~]# rpm -q kernel-devel
package kernel-devel is not installed
[root@localhost ~]# cd /home
[root@localhost home]# wget ftp://rpmfind.net/linux/fedora/releases/9/Everything/i386/os/Packages/kernel-devel-

2.6.25-14.fc9.i686.rpm
[root@localhost home]# rpm -i kernel-devel-2.6.25-14.fc9.i686.rpm
[root@localhost home]# rpm -q kernel-devel
kernel-devel-2.6.25-14.fc9.i686

再安装gcc,否则安装VMware-tools时会提示:Setup is unable to find the "gcc" program on your machine. Please make

sure it
is installed. Do you want to specify the location of this program by hand?
[yes]

What is the location of the "gcc" program on your machine?

在命令行执行:yum install gcc


然后安装VMware Tools就行了,打开菜单“VM -> Install VMware Tools”,然后有光盘自动弹出,把里面的源代码拷贝出来.我的文

件是VMwareTools-6.5.0-xxxxx.tar.gz,我把它拷贝到/opt里.

安装 VMware TOOLS

          cd /opt

          tar -zxvf VMwareTools-6.5.0-xxxxx.tar.gz

          cd vmware-tools-distrib/

          ./vmware-install.pl

再一路安回车OK


2、由于在装载xorg-x11-drv-vmmouse驱动时的一个bug,在客户虚拟机的显示中,鼠标位置可能不正确。直到被更新前,在客户机

中添加Option NoAutoAddDevices到/etc/X11/xorg.conf文件的ServerFlags节中。如果需要,创建这个节:

Section "ServerFlags"
        Option      "NoAutoAddDevices"
EndSection


3、第一,安装JDK
第一,到http://java.sun.com下载最新JDK,当前本人下载的是jdk1.6.0_02!下载文件:jdk-6u2-linux-i586-rpm.bin.注意是

rpm.bin的!

第二,给下载回来的文件增加执行权限:chmod 755 jdk-6u2-linux-i586-rpm.bin.

第三,执行文件:./jdk-6u2-linux-i586-rpm.bin.

第四,执行文件产生一个rpm文件,可直接双击执行也可以在shell下执行:rpm -ivh jdk-6u2-linux-i586-rpm.

第五:配置环境变量,环境变量配置可在全局文件/etc/profile下修改,这样所有linux系统的用户都可以用JDK,如果只是特定的

用户用可修改/root/.bashrc文件,本人的修改为:

#java set
set JAVA_HOME=/usr/java/jdk1.6.0_02
export JAVA_HOME
export JRE_HOME=/usr/java/jre1.6.0_02
set JAVA_BIN=/usr/java/jre1.6.0_02
export JAVA_BIN

第五,当环境变量修改完后,重起系统,在shell下输入java,看是否输入相关JAVA帮助信息,如果有,说明已经安装成功!如果没有,

检查一下变量环境设置是否有误!

2,安装Eclipse,Eclipse不需要安装,只要解压缩就行了

运行Google App Engine不需要Tomecat,记录在这
3,安装tomcat的方法跟安装eclipse的一样,也是下一个tar.gz的文件按安装eclipse方法和步骤就行了!进入tomcat/bin

下./startup.sh,如果在shell出现jdk的相关信息说明已经安装成功启动了,在firefox下打http://localhost:8080/出现tomcat页就

大成功了!

在以上的安装过程之中,出现了小插曲,就是tomcat找不到JDK,后来我又到JAVA网站下了一个JRE回来安装,并建JRE_HOME,重起

TOMCAT,成功了!


4、运行Google App Engine的应用,提示
** Unable to load Mozilla for hosted mode **
java.lang.UnsatisfiedLinkError:
/home/dhofmann/development/ide/gwt-linux-1.4.61/mozilla-1.7.12/libxpcom.so:
libstdc++.so.5: cannot open shared object file: No such file or directory
at java.lang.ClassLoader$NativeLibrary.load(Native Method)解决办法:
Search for stdc++5 in synaptic package manager (System->Administration->Synaptic) and then mark and install it. Or

use this console command:
yum install libstdc++.so.5

停止进程命令:
就是kill 比较不错,如果kill不了. 加上-9
如#kill -9 1778
注1778 为进程pid
pid可以通过ps aux|grep 服务名查得


启动Eclipse时,提示错误:

eclipse.buildId=M20090211-1700
java.version=1.6.0
java.vendor=Sun Microsystems Inc.
BootLoader constants: OS=linux, ARCH=x86, WS=gtk, NL=zh_CN
Command-line arguments: -os linux -ws gtk -arch x86

!ENTRY org.eclipse.ui.workbench 4 0 2009-04-18 02:12:18.085
!MESSAGE Widget disposed too early!
!STACK 0
java.lang.RuntimeException: Widget disposed too early!
    at org.eclipse.ui.internal.WorkbenchPartReference$1.widgetDisposed(WorkbenchPartReference.java:171)

在网上搜索得知:   
eclipse.ini文件加个参数
-vmargs
-Dorg.eclipse.swt.browser.XULRunnerPath=

在Fedora9中安装拼音输入法
保证Fedora 9联网的状态下
在application->system tools->terminal 应用程序->系统工具->终端
输入
su 回车
提示输入root密码
yum install scim 回车
系统会自动从一个镜uy像站点检索scim,并询问是否下载,选择y
下载完成后输入
yum install scim-pinyin 回车
提示和操作如上
然后输入
scim 回车
(笔者的电脑运行到starting SCIM后就没有反应了,不过没关系这时候可以按ctrl+c中断)
选择Fedora 9
System->Preference->Personal->Input Method
系统->首选项->个人->输入法
选择启用新特性,然后选择里面的SCIM,然后选择配置SCIM,
在进入后的界面中选择Global Set 全局设置,在这里设置激活热键即可,然后重新启动电脑,就可以在Fedora 9下面使用中文输入

法了 虽然有点麻烦 但毕竟fedora等众多linux桌面系统还很年轻,有很多不足之处。

参考资料:
http://www.5dlinux.com/article/6/2007/linux_9042.html
http://zhidao.baidu.com/question/62290384.html
http://www.linuxidc.com/Linux/2008-09/16011.htm

部署我的Google App Engine(一)

    截止到今天下午,中午把自己的应用部署到了Google app engine,用了一周的时间啊,真是费劲周折
    好长时间了,听说Google出了个Google App Engine - Google Code,说是可以让用户上传自己的应用,但是只支持python,当时就想什么

时候支持java啦啊,上个月看新闻就听说Google app engine 要开始支持java啦,哈哈,喜,到时候把我的写的blog传上去,哈哈
    上周,终于知道了Google app engine终于开始宣布支持java了,哈哈呼呼,动手,到官网一看,没有支持java的动静啊,

对,英文页面,哈哈,看来中文的还是慢一拍啊
    首先到注册一个,竟然还要手机号发注册码,Google了一下 说在手机号前加 86就OK了,填上手机号点按钮,呦,短信马

上就来啦,搞定,注册成功。
    这下下载SDK,还有eclipse插件,帮助文档只有英文的,配合Google工具栏的翻译功能,基本能看懂,哈哈,感觉一路下

来,英语水平有所上升啊,哈哈
    打开eclipse,装上插件,很轻松的建了第一个应用,插件自动生成了一个小实例,部署上去,惊叹于Google的GWT
    开始一直我原来写的blog程序,原来到处找免费的空间,jsp的空间不好找,先是找了http://www.eatj.com/,但是没24小

时(好像是)就会自动停止,必须手动重启服务,原来还坚持去上去看看,后来终于因为有一次很忙时间太长被注销了,接下来就听

说了http://www.stax.net/,跟Google的路子差不多,好像还更自定义些,继续使用着,搞java朋友可以去看看
    因为google app engine使用Google Account,原来的用户管理模块需要剔除,原来数据库使用的是mysql hibernate,现在

Google 使用JDO,数据库被封装了,还好,当初设计是采用了工厂模式,实现了数据库访问模块与业务处理模块的松耦合,很容易

配置数据库访问模块的更改,感受到好的设计真是为以后修改省很多事啊。
    接着说部署我的Google app engine,终于改好相关代码,准备上传了,噩梦开始了
    1、Unable to upload:
java.lang.IllegalStateException: cannot find javac executable based on java.home, tried “D:\Java\jdk1.6.0_13

\jre\bin\javac.exe” and “D:\Java\bin\javac.exe”
参考http://zhuyx808.javaeye.com/blog/370124
http://onlypython.group.javaeye.com/group/blog/366471
http://618119.com/archives/2009/04/12/148.html
    2、决定转战Linux...(昨儿弄到3点,今儿早点,明儿再写)

2009年4月1日星期三

Google的愚人节

上班的路上听广播,说今天是愚人节,就想不知道今天Google会出什么新花样,哈哈
到公司一看,果然,首页上多了个
谷鸽鸟看
,打造山寨信息网
最近诸事不顺,轻松一下吧




=====================
关于“谷鸽鸟看”计划

2009年4月1日, 总部位于美国加州山寨城(Mountain Village)的谷歌公司正式推出“谷鸽鸟看”计划。 该计划旨在利用装备了 CADIE 芯片和软体, 并被赋予了超智能信息处理能力的“谷鸽”, 动态采集、整理和分享山寨信息,打造全球最大的山寨信息网。 简言之,“谷鸽鸟看”计划的使命是:

鸟看全球信息,使人人皆可山寨并从中受益!

除谷鸽自动外出寻找山寨信息外,用户也可以主动召唤谷鸽采集身边的山寨信息。召唤方法如下:

  • 走到户外或楼顶超过20平方米的空地
  • 用支持上网功能的手机打开谷歌移动版http://g.cn/
  • 对着手机屏幕上出现的麦克风图标,使用鸽子的方法,“咕——咕——咕——”大叫三声
  • 耐心等待……

不出意外的话,谷鸽会在三十分钟内出现在您的身边。 根据不完全统计,排除软件 Bug 和芯片抽风等影响因素, 谷鸽响应召唤者的平均时间间隔是 21.04 分钟,响应成功率为 99.5865%。

2009年3月30日星期一

vs2008 无法打开项目文件

vs2008 无法打开项目文件 .vsproj .vdproj
此安装不支持该项目类型C:\Documents and Settings\Administrator\Local Settings\Temp

因为莫名其妙的错误,刚刚重新ghost了系统,然后重装了vs2008,之后打开我原来的项目报上面的错误,狂晕,项目文件我也没动过啊,搜索微软帮助,建议重装vs2008,重装vs2008后可以了

==
今天想学学WPF,靠,打开我原来建的一个WPF项目还报上面的错误,突然想到我以前装过vs2008 sp1

大大提醒了我

装上sp1后 OK

转载:

安装中文VS2008 SP1 和.NETFRAMEWORK 3.5SP1后智能提示是英文的解决办法
期待已久的VS2008 SP1 和.NET FRAMEWORK 3.5 SP1都出来了

下载地址

Microsoft Visual Studio 2008 Service Pack 1 (iso)

http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=27673c47-b3b5-4c67-bd99-84e525b5ce61

Visual Studio 2008 Team Foundation Server Service Pack 1(iso)

http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=9e40a5b6-da41-43a2-a06d-3cee196bfe3d

Microsoft .NET Framework 3.5 Service Pack 1

http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=ab99342f-5d1a-413d-8319-81da479ab0d7

      第一时间安装完后,智能提示却是英文的,呵呵这对于我这个英文不好的人来说,有点郁闷,重新装了好几次.NETFROAMWORK 3.5 SP1语言包都解决不了问题,后来就用备份的资源文件替换掉ZH-CN目录。问题解决掉了呵呵,下载地址

点击下载(2.0)

完了解压后,替换掉

C:\Windows\Microsoft.NET\Framework\v2.0.50727\zh-CN 目录,

点击下载(3.0)

完了解压后,替换掉

C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\zh-CN目录

点击下载(3.5)

完了解压后,替换掉

C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\zh-CN目录

2009年3月26日星期四

myeclipse7插件安装

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class Test {
private String path;

public Test(String path) {
   this.path = path;
}

public void print() {
   List list = getFileList(path);
   if (list == null) {
    return;
   }

   int length = list.size();
   for (int i = 0; i < length; i++) {
    String result = "";
    String thePath = getFormatPath(getString(list.get(i)));
    File file = new File(thePath);
    if (file.isDirectory()) {
     String fileName = file.getName();
     if (fileName.indexOf("_") < 0) {
      continue;
     }
     String[] filenames = fileName.split("_");
     String filename1 = filenames[0];
     String filename2 = filenames[1];
     result = filename1 + "," + filename2 + ",file:/" + path + "\\"
       + fileName + "";
     System.out.println(result);
    } else if (file.isFile()) {
     String fileName = file.getName();
     if (fileName.indexOf("_") < 0) {
      continue;
     }
     int last = fileName.lastIndexOf("_");// 最后一个下划线的位置
     String filename1 = fileName.substring(0, last);
     String filename2 = fileName.substring(last + 1, fileName
       .length() - 4);
     result = filename1 + "," + filename2 + ",file:/" + path + "\\"
       + fileName + ",4,false";
     System.out.println(result);
    }
   }
}

public List getFileList(String path) {
   path = getFormatPath(path);
   path = path + "/";
   File filePath = new File(path);
   if (!filePath.isDirectory()) {
    return null;
   }
   String[] filelist = filePath.list();
   List filelistFilter = new ArrayList();

   for (int i = 0; i < filelist.length; i++) {
    String tempfilename = getFormatPath(path + filelist[i]);
    filelistFilter.add(tempfilename);
   }
   return filelistFilter;
}

public String getString(Object object) {
   if (object == null) {
    return "";
   }
   return String.valueOf(object);
}

public String getFormatPath(String path) {
   path = path.replaceAll("\\\\", "/");
   path = path.replaceAll("//", "/");
   return path;
}

public static void main(String[] args) {
   new Test(
     "D:\\Program Files\\Genuitec\\Common\\Dropins\\JSEclipse\\eclipse\\plugins")
     .print();//插件路径
}
}
执行完之后,将控制台中打印出的执行结果,直接复制到下面这个文件中: C:\Genuitec\MyEclipse 7.0\configuration\org.eclipse.equinox.simpleconfigurator\bundles.info

E:\Program Files\Genuitec\Common\plugins\vss\eclipse\plugins\org.vssplugin_1.6.1

2009年3月19日星期四

hibernate异常

备案:
java.lang.IllegalStateException: No data type for node: org.hibernate.hql.ast.tree.IdentNode


hibernate查询时报上面的异常,仔细检查hql写的有不对的地方,我就是把逗号,写成点.

2009年2月17日星期二

获取这个月的最后一天

给你一个日期2009-01-01 00:00:00 获取这个月的最后一天。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date=null;
try {
    date = sdf.parse("2009-12-01 00:00:00");
} catch (ParseException e) {
    e.printStackTrace();
}
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
calendar.set(Calendar.DATE, calendar
        .getActualMaximum(Calendar.DATE));
Date d = calendar.getTime();
System.out.println(sdf.format(d));

2009年2月5日星期四

开始学习struts2(七)

好久没写了,过了个年,过了七天猪的日子,吃了睡睡了吃中间偶尔看看电视,为假期准备了几个电影都没看,唉:-(忙,上了几天班了,怎么感觉这周过的这么慢呢,刚刚刚周四
昨儿看了一集struts2

总结几点

1、struts.xml中的package标签有个abstract="true"属性,如果为true,则这个package中不能有<action>标签,为true表示这个package为一个抽象package,就像java中的接口中不能有方法实现似的。

2、package标签还有个namespace属性,它关系到这个package中的action访问路径,默认是"",比如

<package name= "capinfo" extends= "struts-default" namespace="/hello">
<action name= "HelloWorld"
class= "com.capinfo.struts2.action.HelloWordAction" >
<result>/HelloWorld.jsp</result>
</action>
</package>

则jsp中则应为<form action="/hello/HelloWorld.action" method="post">,如果没有找到hello/HelloWorld.action则会寻找namespace为""的,也就是HelloWorld.action,如果再没有,就会抛出异常。

3、在struts1中可以有多个struts-config.xml的文件,只要在web.xml配置org.apache.struts.action.ActionServlet时加到config参数中,以逗号分隔,在struts2中也可以有多个struts.xml形式的文件,这次不需要修改web.xml了,在struts.xml中添加诸如
<include file=""/>就Ok了

4、关于struts各种参数的配置信息位于struts2-core.jar/org.apache.struts2/default.properties中,如果要修改里面的配置,有两种方式,一是在struts.xml中配置,例如<constant name="struts.devMode" value="true" />,二是在classess中建一个struts.properties,在里面配置比如struts.i18n.encoding=GBK,在struts2-core.jar/org.apache.struts2/default.properties中有一下这句注释,说明了struts.properties将覆盖default.properties中的配置

### Struts default properties
###(can be overridden by a struts.properties file in the root of the classpath)
###

就总结这么些先。

2009年2月2日星期一

2009年全年放假安排

一、元旦:1月1日至3日放假,共3天。其中,1月1日(星期四、新年)为法定节假日,1月3日(星期六)为公休日。1月4日(星期日)公休日调至1月2日(星期五)。1月4日(星期日)上班。  

二、春节:1月25日至31日放假,共7天。其中,1月25日(星期日、农历除夕)、1月26日(星期一、农历正月初一)、1月27日(星期二、农历正月初二)为法定节假日,1月31日(星期六)照常公休;1月25日(星期日)公休日调至1月28日(星期三),1月24日(星期六)、2月1日(星期日)两个公休日调至1月29日(星期四)、1月30日(星期五)。1月24日(星期六)、2月1日(星期日)上班。  

三、清明节:4月4日至6日放假,共3天。其中,4月4日(星期六、农历清明当日)为法定节假日,4月5日(星期日)照常公休。4月4日(星期六)公休日调至4月6日(星期一)。  

四、劳动节:5月1日至3日放假,共3天。其中,5月1日(星期五、“五一”国际劳动节)为法定节假日,5月2日(星期六)、5月3日(星期日)照常公休。  

五、端午节:5月28日至30日放假,共3天。其中,5月28日(星期四、农历端午当日)为法定节假日,5月30日(星期六)照常公休;5月31日(星期日)公休日调至5月29日(星期五);5月31日(星期日)上班。  

六、国庆节、中秋节:10月1日至8日放假,共8天。其中,10月1日(星期四)、10月2日(星期五)、10月3日(星期六)为国庆节法定节假日,10月4日(星期日)照常公休;10月3日(星期六)公休日及中秋节分别调至10月5日(星期一)、10月6日(星期二),9月27日(星期日)、10月10日(星期六)公休日调至10月7日(星期三)、10月8日(星期四)。9月27日(星期日)、10月10日(星期六)上班。

2009年1月17日星期六

开始学习struts2(六)

前两天实践了关于拦截器的具体实现,说实话关于底层实现还没有看明白,看jdk的源码中的
public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces)
方法,好长啊
迂回一下,今儿看struts2的具体拦截器Interceptor怎么配置
配置可比自己写实现拦截器容易多了
1、首先写一个拦截器类,拦截器类有两只写法(目前俺知道的)
一种是显示com.opensymphony.xwork2.interceptor.Interceptor接 口,com.opensymphony.xwork2.interceptor.Interceptor接口有三个方法destroy()、init() 和String intercept(ActionInvocation actionInvocation),跟过滤器差不多
这里指出的是init初始化方法将在容器启动是调用这个方法。
package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-15
* Time: 16:34:17
* To change this template use File | Settings | File Templates.
*/
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.ActionInvocation;

public class MyInterceptor implements Interceptor{

    public void destroy() {

    }

    public void init() {

    }

    public String intercept(ActionInvocation actionInvocation) throws Exception {

        System.out.println("test intercept begin");
        String result = actionInvocation.invoke();
        System.out.println("test intercept finish");
        return result;
    }
}
另一种就是继承com.opensymphony.xwork2.interceptor.AbstractInterceptor,这是个抽象类,并实 现了com.opensymphony.xwork2.interceptor.Interceptor接口,分别实现了init和destroy方法, 但什么都没做,继承AbstractInterceptor后,实现intercept方法就行了,
这里指出的是在intercept方法中执行actionInvocation.invoke();执行所拦截的action中的方法;
2、拦截器写完了剩下就是配置了,这里要用到struts.xml的组织结构<struts>中有<package>包的的概 念,包与包之间可以继承extends,就像子类继承父类一样,子类将拥有父类的属性和配置,我们一般都继承extends="struts- default",而struts-default定义在struts2-core.jar 中的struts-default.xml中,struts-default包中定义了很多struts2提供的拦截器和拦截器栈(拦截器栈可以包含多个 拦截器或拦截器栈),struts2的好多功能都是实现在这些拦截器中,其中有个<default-interceptor-ref name="defaultStack"/>标签定义了默认的拦截器,如果<action>配置中没有拦截器配置,那就调用默认拦截 器,如果有拦截器配置,要么同时加上默认拦截器,要么在自己的package中加入设置默认拦截器的标签。
<package name="capinfo" extends="struts-default">
        <interceptors>
            <interceptor name="myInterceptor" class="com.test.interceptor.MyInterceptor">
            </interceptor>
        </interceptors>
        <action name="HelloWorld"
            class="com.capinfo.struts2.action.HelloWordAction">
            <result>/HelloWorld.jsp</result>
            <interceptor-ref name="myInterceptor"></interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>
        </action>

        <!-- Add your actions here -->
    </package>

2009年1月14日星期三

开始学习struts2(五)

说是struts2的核心就是拦截器
先看看拦截器的实现
实现拦截器有这么几个东西构成
1、目标对象-将被拦截的对象,这个对象中的方法被调用是将被拦截
要求目标对象面向接口编程,首先要定义接口package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:37:23
* 面向接口编程
* 目标对象的接口
*/
public interface TargetInterface {
    public void doSomething();
}目标对象实现
package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:36:26
* 目标对象
*/
public class Target implements TargetInterface{
    public void doSomething(){
        System.out.println("do something");
    }
}
2、拦截器对象-里面包含在调用目标对象前或后要调用的方法package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:39:32
* 拦截器
*/
public class Interceptor {
    public void before(){
        System.out.println("before");
    }

    public void after(){
        System.out.println("after");
    }
}
3、处理器-处理器决定拦截器如何拦截目标对象
package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:41:08
*/
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
* 处理器
* 在这里将目标对象Target和拦截器Interceptor联系在了一起
*/
public class MyHandler implements InvocationHandler{

    /**
     * 目标对象
     * 将来目标对象的方法将被注入interceptor
     */
    private Object object;

    /**
     * 拦截器
     * MyHandler负责将Interceptor这个拦截器注入到传入的目标对象object
     */
    private Interceptor interceptor = new Interceptor();

    public void setObject(Object object){
        this.object = object;
    }

    /**
     * 实现InvocationHandler接口的方法
     * @param o 在其上调用方法的代理实例
     * @param method 对应于在代理实例上调用的接口方法的 Method 实例
     * @param objects 包含传入代理实例上方法调用的参数值的对象数组
     * @return 从代理实例的方法调用返回的值
     * @throws Throwable
     */
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        Object result = null;
        interceptor.before();
        result = method.invoke(object,objects);
        interceptor.after();
        return result;
    }
}
4、代理对象-用于得到目标对象的代理对象
package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:50:52
* 代理类
*/
import java.lang.reflect.Proxy;
public class MyProxy {
    /**
     * 返回obj的,处理器为MyHandler的代理对象
     * @param obj 目标对象
     * @return 目标对象的代理对象
     */
    public Object getProxy(Object obj){
        MyHandler myHandler = new MyHandler();
        myHandler.setObject(obj);
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(),myHandler);
    }
}
5、最后客户调用代码package com.test.interceptor;

/**
* Created by IntelliJ IDEA.
* User: Administrator
* Date: 2009-1-9
* Time: 17:55:45
* 客户调用
*/
public class Client {
    public static void main(String[] args){
        //目标对象
        TargetInterface target = new Target();
        //代理对象
        MyProxy myProxy = new MyProxy();
        //通过代理对象得到目标对象的代理
        TargetInterface proxy = (TargetInterface)myProxy.getProxy(target);
        //通过目标对象的代理调用目标对象的方法
        proxy.doSomething();
    }
}

//输出:
//before
//do something
//after
将自己的理解写了注释,现在只理解到这个程度,像
Proxy.newProxyInstance
里面是怎么实现的,还没深入考究
继续努力

2009年1月8日星期四

开始学习struts2(四)

关于类型转换还有一种写法:public class ConverterPoint extends StrutsTypeConverter {

//    @Override
//    public Object convertValue(Map context, Object value, Class toType) {
//        if(Point.class == toType){
//            String[] params = (String[])value;
//            params = params[0].split(",");
//            Point point = new Point();
//            point.setX(Integer.parseInt(params[0]));
//            point.setY(Integer.parseInt(params[1]));
//            return point;
//           
//        }else if(String.class == toType){
//            Point point = (Point)value;
//            return "x=" + point.getX() + ",y=" + point.getY();
//        }
//        return super.convertValue(context, value, toType);
//    }

    @Override
    public Object convertFromString(Map arg0, String[] arg1, Class arg2) {
        String[] params = arg1;//(String[])value;
        params = params[0].split(",");
        Point point = new Point();
        point.setX(Integer.parseInt(params[0]));
        point.setY(Integer.parseInt(params[1]));
        return point;
    }

    @Override
    public String convertToString(Map arg0, Object arg1) {
        Point point = (Point)arg1;
        return "x=" + point.getX() + ",y=" + point.getY();
    }

   
}
原来是继承ognl.DefaultTypeConverter类,现在改成继承 org.apache.struts2.util.StrutsTypeConverter类了,看 org.apache.struts2.util.StrutsTypeConverter的源码可知道 org.apache.struts2.util.StrutsTypeConverter是个抽象类,并实现了 ognl.TypeConverter,org.apache.struts2.util.StrutsTypeConverter中有两个要实现的方法 一个convertFromString,一个convertToString,看方法名字就知道一个从字符串转换成Object,一个是将Object 转换成String,这样好像更加清晰

另外还有一种全局转换的配置,就是建立一个统一的属性文件,文件名为xwork-conversion.properties,与struts.xml位于统一目录下,里面的配置改成了
com.test.struts2.data.Point=com.test.struts2.action.ConverterPoint
意思是所有com.test.struts2.data.Point类型的对象都要通过com.test.struts2.action.ConverterPoint来转换

2009年1月5日星期一

开始学习struts2(三)

struts2局部类型转换

需求为:在页面的文本框输入一个x、y坐标,之间用","隔开,Action中有一个Point类型的属性,Point类里面有两个字段,分别是 x,y,int型,要求当页面提交时将文本框中的字符串转换成Point对象,当Action返回到页面时将Point转换成字符串显示

1、首先做一个jsp用于输入和提交:point.jsp

<s:form action="Converter">
<s:textfield name="point" label="Point"></s:textfield>
<s:textfield name="point.x" label="Point.X"></s:textfield>
<s:textfield name="point.y" label="Point.Y"></s:textfield>
<s:submit label="submit"></s:submit>
</s:form>

2、再建一个用于显示的jsp-converter.jsp

<body>
<s:property value="point"/><br>
<s:property value="point.x"/><br>
<s:property value="point.y"/><br>
</body>

3、Action类 ConverterAction

public class ConverterAction extends ActionSupport{

private Point point;

public Point getPoint() {
return point;
}

public void setPoint(Point point) {
this.point = point;
}

public String execute()throws Exception {
return "success";
}
}

4、struts.xml

<action name="Converter"
class="com.test.struts2.action.ConverterAction">
<result name="success">/converter.jsp</result>
<result name="input">/point.jsp</result>
</action>

5、转换类 ConverterPoint

public class ConverterPoint extends DefaultTypeConverter {

@Override
public Object convertValue(Map context, Object value, Class toType) {
if(Point.class == toType){
String[] params = (String[])value;
params = params[0].split(",");
Point point = new Point();
point.setX(Integer.parseInt(params[0]));
point.setY(Integer.parseInt(params[1]));
return point;

}else if(String.class == toType){
Point point = (Point)value;
return "x=" + point.getX() + ",y=" + point.getY();
}
return super.convertValue(context, value, toType);
}


}

6、配置转换
在ConverterAction 类的同一目录下定义属性文件ConverterAction-conversion.properties,注意文件 名,-conversion.properties为固定不变,ConverterAction为Action的名字,文件内容:

point=com.test.struts2.action.ConverterPoint

Ok了,这样就完工了

开始学习struts2(二)

前两天初步认识了一下struts2
今儿看来教程的第二三讲,搞清了一些前面的一些猜测或是疑问
1、struts2是不用<html:...>标签了,统一成了<s:...>
如下这样:
<s:form action="Converter">
<s:textfield name="point" label="Point"></s:textfield>
<s:submit label="submit"></s:submit>
</s:form>
显示效果:

注意到<s:textfield name="point" label="Point"></s:textfield>
中的label属性,它指定了文本框前面显示的内容,还自动加了冒号,哈哈,挺聪明的嘛,但是担心这样在复杂的页面设计中是不是好使。

哦对了,要想这么写,要在页面上方加上这个:<%@ taglib prefix="s" uri="/struts-tags" %>

2、Action
前面说的Action不再需要继承任何struts类,现在看来要失望了,为了方便起见还是建议集成ActionSupport类,目前觉得有用的是 ActionSupport中定义了几个static的result name,比如SUCCESS、ERROR,原来的return "success";现在可以写成return super.SUCCESS;,将标识用的字符串常量定义成static的是一直提倡的,还有就是validate()方法,验证有错误可以调用 addFieldError()方法,好像就是struts1 ActionForm里的东西,有所改进的是super.addFieldError("username", "username is null");将在页面中显示的效果为:错误信息"username is null"将在名字为"username"文本框的上面显示,这些如果能用ajax实现就好了。
对于Action解耦,可能在于它不再需要HttpServletRequest 、HttpServletResponse这样的容器运行时参数吧