isn't it a good idea to have your virtualbox based guest OS running on host system starting ?
let me show you how it can be done :
Suppose that you already have a guest os, such as JeOS. you can start it from command line :
>VBoxManage startvm "Ubuntu Server" -type vrdp #your server's name , or vm id which you may already know. pay attention to the "-type vrdp", it means starting the guestOS in non-GUI mode.
the script for shutdown is :
>VBoxManage controlvm "Ubuntu Server" poweroff
these two lines are the core code, we write a shell file to include it (lets name it ubuntu.server.sh and put it under /etc/iniit.d/ , omit the file content....), and schedule it :
>sudo update-rc.d ubuntu.server.sh start 40 2 3 . stop 01 0 1 6 .
now you dont have to start the guestOS manually every time restart the machine :)
2009-04-10
2008-07-23
the jsp-config trap
There will be conflict if configure the servlet and jsp-config the same pattern as below :
<servlet-mapping>
<url-pattern>/system/*</url-pattern>
</servlet-mapping>
<jsp-property-group>
<url-pattern>/system/*</url-pattern>
if a request came, "/system/watch" for example, Tomcat will pass the request to the jsp container,
since jsp container cannot found any jsp fit this request, an http 404 would be returned.
I spent 3 hours and worked it out. here i list out some related resource :
1. the request process diagram
http://tomcat.apache.org/tomcat-6.0-doc/architecture/requestProcess.html
2. org.apache.catalina.core.StandardContext : how the war context was loaded.
<servlet-mapping>
<url-pattern>/system/*</url-pattern>
</servlet-mapping>
<jsp-property-group>
<url-pattern>/system/*</url-pattern>
if a request came, "/system/watch" for example, Tomcat will pass the request to the jsp container,
since jsp container cannot found any jsp fit this request, an http 404 would be returned.
I spent 3 hours and worked it out. here i list out some related resource :
1. the request process diagram
http://tomcat.apache.org/tomcat-6.0-doc/architecture/requestProcess.html
2. org.apache.catalina.core.StandardContext : how the war context was loaded.
2008-05-23
控制Bundle的启动
在开放RCP程序时, 由于ActivationPolicy的存在(这是个优点, 保证OSGi只加载需要的Bundle), spring的osgi-extender并不能自动start, 这导致所有基于spring-osgi的bundle只能愣在那起不了作用.
启动osgi-extender的方法是: 在config.ini里的osgi.bundles项里, 加入
org.springframework.bundle.osgi.extender@start
这个OSGi能识别并且确保会执行Activator.start()方法.
目前, 俺仅找到这么一个方式被证明是正确的, 之前也尝试过写另一个Bundle来激活它, 可那个bundle本身都没被激活...
小发现: osgi.extender被start过一次后(通过console), 之后每次都会自动启动.
小小发现: org.eclipse.update.configurator不依赖于org.eclipse.update.core, 并且, 是它负责启动plugins/目录下的所有插件, 这就是为啥它的启动顺序排第三:
org.eclipse.update.configurator@3:start
启动osgi-extender的方法是: 在config.ini里的osgi.bundles项里, 加入
org.springframework.bundle.osgi.extender@start
这个OSGi能识别并且确保会执行Activator.start()方法.
目前, 俺仅找到这么一个方式被证明是正确的, 之前也尝试过写另一个Bundle来激活它, 可那个bundle本身都没被激活...
小发现: osgi.extender被start过一次后(通过console), 之后每次都会自动启动.
小小发现: org.eclipse.update.configurator不依赖于org.eclipse.update.core, 并且, 是它负责启动plugins/目录下的所有插件, 这就是为啥它的启动顺序排第三:
org.eclipse.update.configurator@3:start
2008-05-16
Eclipse Monkey -- Eclipse 的脚本
Eclipse Monkey 是Dash下的兴趣项目, 由Aptana贡献,提供给Eclipse插件开发者使用。
它是用javascript书写的, 用来支持在Eclipse运行时期执行一些操作, 就像可以通过Firebug提供的JS输入接口可以窥探页面DOM信息, Eclipse Monkey可以访问整个运行时的上下文, 比如获得当前选中的Editor并插入一段数字, 激活/停止某个bundle/plugin.
1.安装与运行
通过update site , 安装后重启. 在菜单栏会出现"script"项, 选sample, 会自动在生成出一些sample脚本. 然后再看菜单栏的"script"项, 就会看到sample脚本已经可以执行了.如果想写自己的脚本, 就复制任意一个sample, 然后选"script"项下的"paste new script"
2.语法与规则
注意文件最上几行的注释是元数据, 譬如Menu, Listener, DOM等, 不能省略.一般情况下main方法是执行入口, 如果是listener, 则依赖所触发的事件去调用相应的方法.
DOM里有已经定义好的对象, 比如editors, views等. 如获得当前激活的Editor的代码就是:
var ae = editors.activEditor;
这个不好用, 限制太多. 通过Packages就非常灵活了.Packages后面跟类的全限定名, 就能访问到这个类, 俺的喜好, 从Packages.org.eclipse.core.runtime.Platform基本上什么都能访问到.
Listener可以监听并执行脚本, 比如键盘监听, Editor/View被选中的监听.
3.延伸阅读
Aptana在EclipseCon的PPT以及Demo代码
它是用javascript书写的, 用来支持在Eclipse运行时期执行一些操作, 就像可以通过Firebug提供的JS输入接口可以窥探页面DOM信息, Eclipse Monkey可以访问整个运行时的上下文, 比如获得当前选中的Editor并插入一段数字, 激活/停止某个bundle/plugin.
1.安装与运行
通过update site , 安装后重启. 在菜单栏会出现"script"项, 选sample, 会自动在生成出一些sample脚本. 然后再看菜单栏的"script"项, 就会看到sample脚本已经可以执行了.如果想写自己的脚本, 就复制任意一个sample, 然后选"script"项下的"paste new script"
2.语法与规则
注意文件最上几行的注释是元数据, 譬如Menu, Listener, DOM等, 不能省略.一般情况下main方法是执行入口, 如果是listener, 则依赖所触发的事件去调用相应的方法.
DOM里有已经定义好的对象, 比如editors, views等. 如获得当前激活的Editor的代码就是:
var ae = editors.activEditor;
这个不好用, 限制太多. 通过Packages就非常灵活了.Packages后面跟类的全限定名, 就能访问到这个类, 俺的喜好, 从Packages.org.eclipse.core.runtime.Platform基本上什么都能访问到.
Listener可以监听并执行脚本, 比如键盘监听, Editor/View被选中的监听.
3.延伸阅读
Aptana在EclipseCon的PPT以及Demo代码
2008-04-03
通过电脑收发短信
基本结构是, 用电脑控制手机收发短信.
手机收发短信, 就象电脑上网需要一个猫一样, 也有一个"GSM-modem". 插入SIM卡后, 就相当于给猫输入了用户名, 密码, 然后就可以打电话/发短信了.
电脑与手机的数据传输, GSM在这方面有个规范, 叫做"AT", 所有与"GSM-modem"的交互都是在这个协议上进行的. 在编程层次上, 这属于串口编程
大概流程是这样的
Nokia的手机除了早期出品的外, 基本上都可以通过pc suite实现这个功能, 它封装了这些交互细节. 我用的nokia 1116, 不被pc suite支持, 接口规范用的是FBUS, 在nokia官方网站上找不到相应的驱动程序, 不过有第三方的, 叫做"mobiMB".这有破解版.
市面上, 有种东西叫做"短信猫" , 基本上就是这个意思. 不用自己去diy了 :)
手机收发短信, 就象电脑上网需要一个猫一样, 也有一个"GSM-modem". 插入SIM卡后, 就相当于给猫输入了用户名, 密码, 然后就可以打电话/发短信了.
电脑与手机的数据传输, GSM在这方面有个规范, 叫做"AT", 所有与"GSM-modem"的交互都是在这个协议上进行的. 在编程层次上, 这属于串口编程
大概流程是这样的
Nokia的手机除了早期出品的外, 基本上都可以通过pc suite实现这个功能, 它封装了这些交互细节. 我用的nokia 1116, 不被pc suite支持, 接口规范用的是FBUS, 在nokia官方网站上找不到相应的驱动程序, 不过有第三方的, 叫做"mobiMB".这有破解版.
市面上, 有种东西叫做"短信猫" , 基本上就是这个意思. 不用自己去diy了 :)
2008-01-07
TPTP agent-controller 配置
配置AgentController以profilejava程序.(用eclipse callisto版本的tptp)
先设置AGENT_HOME=D:\dev\eclipseCallisto\plugins\org.eclipse.hyades.execution.win32.x86_4.2.2.v200701141614
然后在jboss启动里加上下面的参数:
-XrunpiAgent:server=standalone,filters=tptp.profile.filters.txt,file=profilejboss.trcxml
启动程序, 然后打开eclipse, 通过远程方式连1002端口就可以了.
其中tptp.profile.filters.txt是用来过滤profile的对象的, 内容/格式如下:
com.eha.* * include
* * exclude
包名 函数名 过滤掉/包含
其中profilejboss.trcxml是在"standalone"模式下, 收集的数据, 这个可以被eclipse tptp打开.
最后说一下agent:server的4种模式:standalone, enabled, controlled, application
stantalone, 不需要通过eclipse做什么事, 完全独立运行, 最后会得出一个*.trcxml文件, 保存了profile的数据.
enabled, 默认的, 只有客户端请求时才采集数据, 否则什么也不做.
controlled, 加载agent的时候会暂停正常的java程序, 直到有客户端连上agent:server为止才恢复java程序运行.
application, 跟enabled没啥区别.
除了standalone模式外, 其它的都只根据请求产生xml片断(fragment).
先设置AGENT_HOME=D:\dev\eclipseCallisto\plugins\org.eclipse.hyades.execution.win32.x86_4.2.2.v200701141614
然后在jboss启动里加上下面的参数:
-XrunpiAgent:server=standalone,filters=tptp.profile.filters.txt,file=profilejboss.trcxml
启动程序, 然后打开eclipse, 通过远程方式连1002端口就可以了.
其中tptp.profile.filters.txt是用来过滤profile的对象的, 内容/格式如下:
com.eha.* * include
* * exclude
包名 函数名 过滤掉/包含
其中profilejboss.trcxml是在"standalone"模式下, 收集的数据, 这个可以被eclipse tptp打开.
最后说一下agent:server的4种模式:standalone, enabled, controlled, application
stantalone, 不需要通过eclipse做什么事, 完全独立运行, 最后会得出一个*.trcxml文件, 保存了profile的数据.
enabled, 默认的, 只有客户端请求时才采集数据, 否则什么也不做.
controlled, 加载agent的时候会暂停正常的java程序, 直到有客户端连上agent:server为止才恢复java程序运行.
application, 跟enabled没啥区别.
除了standalone模式外, 其它的都只根据请求产生xml片断(fragment).
2007-12-18
ejb环境下的org.hibernate.TransientObjectException
网站上用户注册的同时还要给用户加分.
以前ear部署时CallByValue设置的是false(ear-deployer.xml), 后来改成了true, 然后就不能加分了, 注册还是可以的, 就是一直报org.hibernate.TransientObjectException的异常.
代码大概是这样的:
Consumer c = new Consumer();
c.setUsername("uname001");
c.setPassword("pwordddd");
service.save(c);//1
service.addPoints(c, 300);//2
service是对EJB的引用(Stateless)
故事就是由EJB引起的.如果CallByValue=false, 在执行"1"后执行
System.out.println(c.getId());//841
返回值不是空, 如果CallByValue=true, 返回值就是空.
分析一下 : CallByValue时, Hibernate不能同步c的id.
POJO有3种状态, Transient, Persistent, Detached, Transient是用"new" 实例化的, 执行hibernate的save操作, 会存储到数据库的同时更新这个对象, 变成Persistent.而在CallByValue=true 的情况下, hibernate无法更新到这个对象, 也就是说, 在上面1步骤执行的时候, hibernate没有办法更新c这个变量.
废话多了, 好像也没大说明白....
以前ear部署时CallByValue设置的是false(ear-deployer.xml), 后来改成了true, 然后就不能加分了, 注册还是可以的, 就是一直报org.hibernate.TransientObjectException的异常.
代码大概是这样的:
Consumer c = new Consumer();
c.setUsername("uname001");
c.setPassword("pwordddd");
service.save(c);//1
service.addPoints(c, 300);//2
service是对EJB的引用(Stateless)
故事就是由EJB引起的.如果CallByValue=false, 在执行"1"后执行
System.out.println(c.getId());//841
返回值不是空, 如果CallByValue=true, 返回值就是空.
分析一下 : CallByValue时, Hibernate不能同步c的id.
POJO有3种状态, Transient, Persistent, Detached, Transient是用"new" 实例化的, 执行hibernate的save操作, 会存储到数据库的同时更新这个对象, 变成Persistent.而在CallByValue=true 的情况下, hibernate无法更新到这个对象, 也就是说, 在上面1步骤执行的时候, hibernate没有办法更新c这个变量.
废话多了, 好像也没大说明白....
2007-11-20
访问EJB
Local的是不能在EJB外访问的, 否则会报这样的异常:
javax.ejb.EJBException: Invalid invocation of local interface (null container)
如果想独立启动junit测试访问ejb, 需要把ejb声明为Remote.
javax.ejb.EJBException: Invalid invocation of local interface (null container)
如果想独立启动junit测试访问ejb, 需要把ejb声明为Remote.
2007-11-19
jms定时发送
需求说在23:00至10:00这个区间不准向用户发短信, 如果有的话, 时间顺延.
jms标准并未提供定时发送的规范, 所以根据各实现的不同, 有不同处理方法, 在jboss中, 设置如下:
//....
Message msg = session.createObjectMessage();
msg.setLongProperty("JMS_JBOSS_SCHEDULED_DELIVERY", time());
//....
sender.send(msg);
其中time()返回的是msg发送的时间点, long类型. 如果是想立即发送的话, 值应该是
System.currentTimeMillis()
tss讨论帖
jms标准并未提供定时发送的规范, 所以根据各实现的不同, 有不同处理方法, 在jboss中, 设置如下:
//....
Message msg = session.createObjectMessage();
msg.setLongProperty("JMS_JBOSS_SCHEDULED_DELIVERY", time());
//....
sender.send(msg);
其中time()返回的是msg发送的时间点, long类型. 如果是想立即发送的话, 值应该是
System.currentTimeMillis()
tss讨论帖
2007-11-16
今儿总算是明白了, 为什么那么多人追着学xml
http://www.w3schools.com/xml/xml_xsl.asp
非常清晰直观的sample.
我觉得非常突出的一个优点是, 强制web designer更标准化地去做xsl.
用html的话, 就很随便了, 可以拼凑出页面来.
xml数据是独立出来的, 也方便供其它接口调用(ws?, 采集数据?)
终于发觉它值得学了.....
非常清晰直观的sample.
我觉得非常突出的一个优点是, 强制web designer更标准化地去做xsl.
用html的话, 就很随便了, 可以拼凑出页面来.
xml数据是独立出来的, 也方便供其它接口调用(ws?, 采集数据?)
终于发觉它值得学了.....
2007-11-01
函数式编程
适合做DSL.
包括回调(callback)这样的技巧.
感觉象一种"操作注入" , 相对"依赖注入"来说.
实现有Erlang和Haskell等, 高并发, 据说Erlang的http服务器比apache快15倍
复杂的系统倾向于用这种语言, 代码比较优美, 相对较少. ref=>越少的代码越不容易出错
少废话, 来几个链接
http://www.ibm.com/developerworks/cn/web/wa-javascript.html
developerWorks上用js解释的
http://www.ibm.com/developerworks/java/library/j-fp.html
java中的函数式编程
http://code.google.com/p/pure-functional-java/
一个小项目, 大致实现了函数式编程.
http://chn.blogbeta.com/232.html
一个从几千年开始讲起的函数式编程的历史.
包括回调(callback)这样的技巧.
感觉象一种"操作注入" , 相对"依赖注入"来说.
实现有Erlang和Haskell等, 高并发, 据说Erlang的http服务器比apache快15倍
复杂的系统倾向于用这种语言, 代码比较优美, 相对较少. ref=>越少的代码越不容易出错
少废话, 来几个链接
http://www.ibm.com/developerworks/cn/web/wa-javascript.html
developerWorks上用js解释的
http://www.ibm.com/developerworks/java/library/j-fp.html
java中的函数式编程
http://code.google.com/p/pure-functional-java/
一个小项目, 大致实现了函数式编程.
http://chn.blogbeta.com/232.html
一个从几千年开始讲起的函数式编程的历史.
2007-09-24
慎用System.exit()
写个程序, 给邮件列表里每个人都发封邮件.
用main启动spring, 然后main就一直等, 一直等...spring就嘿咻嘿咻地启动线程, 发邮件, 启动线程, 发邮件.....
然后就完成任务了~~~ :).
后来, 又给了我一个邮件列表, 这次要带附件发送...
问题来了, 程序还没等邮件发完, 就终止了....
然后发现, 在读邮件列表时, 是一行一行地读的, 每读一个, 就发送给spring, 让spring去嘿咻嘿咻, 如果读到最后一行, 就执行
System.exit(0);
问题就是这段代码了, 把它修改成
return;
OK了, 阳光明媚 :D
虽然读到了最后一行, 但是, 后台的发送程序还没结束.
用main启动spring, 然后main就一直等, 一直等...spring就嘿咻嘿咻地启动线程, 发邮件, 启动线程, 发邮件.....
然后就完成任务了~~~ :).
后来, 又给了我一个邮件列表, 这次要带附件发送...
问题来了, 程序还没等邮件发完, 就终止了....
然后发现, 在读邮件列表时, 是一行一行地读的, 每读一个, 就发送给spring, 让spring去嘿咻嘿咻, 如果读到最后一行, 就执行
System.exit(0);
问题就是这段代码了, 把它修改成
return;
OK了, 阳光明媚 :D
虽然读到了最后一行, 但是, 后台的发送程序还没结束.
2007-09-06
发现spring写的代码跟我的一样, 偷乐.....
我写了个StringArrayEditor, 后来发现spring有一个StringArrayPropertyEditor, 名字差不多, 看内容, 完全一样的, 呵呵.
不过, 最后还是把我的代码删除掉了.....
不过, 最后还是把我的代码删除掉了.....
这是一个bug么?Spring.BeanWrapper
spring的BeanWrapper会存放属性值.
class A{
BeanWrapper bw = new BeanWrapper(this);
private String[] sa;
//setter/getter....
}
给sa属性加了个属性编辑器StringArrayPropertyEditor
我觉得, 这么调用, 应该不会出问题:
A a = new A();
a.setSa(new String[]{"a", "b", "c"});
//我期望它的结果应该是 "a,b,c"
a.bw.findCustomEditor(String[].class, "sa").getAsText();
结果, 却是空, 不是找不到属性编辑器, 当你通过属性编辑器去获取属性值时, spring不会真正地去a这个类里面实时查找.只有当执行这句,
上面的代码才能得到预期的结果:
a.bw.setPropertyValue("sa", new String[]{"a", "b", "c"});
令人失望....咋就不去inspect一下'a'这个类捏?
2007-09-05
2007-08-31
又一次谈classloading--java.lang.VerifyError
事情是这样的, ear里的war老部署不上去, war里的一个filter(确切的应该是acegi的filter, 托管给spring的)加载不了, 问题出在spring给它的doFilter方法注入属性被检测到verifyError.
后来, 修改jbossweb-tomcat55.sar/META-INF/jboss-service.xml, 把Java2ClassLoadingCompliance属性设置为true, 就OK了.
这个属性是jboss集成tomcat用的, 它的意思是, 是否把java2的"父类优先"加载模型替换为servlet 2.3的"web容器优先"
后来, 修改jbossweb-tomcat55.sar/META-INF/jboss-service.xml, 把Java2ClassLoadingCompliance属性设置为true, 就OK了.
这个属性是jboss集成tomcat用的, 它的意思是, 是否把java2的"父类优先"加载模型替换为servlet 2.3的"web容器优先"
2007-08-29
jobss类加载
一般来说, 象httpclient, logging等, 不会从ear包内加载, 而是用jboss现有的.如果想加载, 要在meta-inf/下加个jboss-app.xml文件, 内容大概是:
然后我就照这个办了, 后来发现还不行, 说是mdb(部署了一个message-driven bean)不合规范:
section:15.7.4
The message driven bean must declare one onMessage method
后来才发现, 不知道哪个傻X把geronimo-j2ee-spec.jar放到ear包里来了, NND, 估计是geronimo与jboss验证方法不一样吧.
去掉就OK了. 还有个关于logging的, 不加jboss-app.xml的话, 会自动把你自己ear内的logging.jar忽略掉(而用jboss服务器的), 加了jboss-app.xml, ear的classLoader也会把ear里面的logging.jar加载上 , 然后Log对象就发现它有两个版本(一个jboss的, 一个ear载的).就会报错(检查的还挺仔细)
再这么下去, 快成jboss专家了....
--
It's Hard to Define, But I Know it When I See it…
<jboss-app>原文
<loader-repository>some.dot.com:loader=webtest.ear</loader-repository>
</jboss-app>
然后我就照这个办了, 后来发现还不行, 说是mdb(部署了一个message-driven bean)不合规范:
section:15.7.4
The message driven bean must declare one onMessage method
后来才发现, 不知道哪个傻X把geronimo-j2ee-spec.jar放到ear包里来了, NND, 估计是geronimo与jboss验证方法不一样吧.
去掉就OK了. 还有个关于logging的, 不加jboss-app.xml的话, 会自动把你自己ear内的logging.jar忽略掉(而用jboss服务器的), 加了jboss-app.xml, ear的classLoader也会把ear里面的logging.jar加载上 , 然后Log对象就发现它有两个版本(一个jboss的, 一个ear载的).就会报错(检查的还挺仔细)
再这么下去, 快成jboss专家了....
--
It's Hard to Define, But I Know it When I See it…
2007-08-28
class 版本
Unsupported major.minor version 49.0
部署ejb的时候就出这问题, 也会出classNotFoundException. 原因是jdk5编译出来的class在jdk4上面不能.
这种问题...真让人无奈....
--
It's Hard to Define, But I Know it When I See it…
部署ejb的时候就出这问题, 也会出classNotFoundException. 原因是jdk5编译出来的class在jdk4上面不能.
这种问题...真让人无奈....
--
It's Hard to Define, But I Know it When I See it…
2007-07-25
因无索引导致的性能问题
测试那边说, 页面打开很慢, 自己跑去试了下, 果然, 一个搜索结果页面, 大概要30s~60s, 查看了下代码, 发现是段hql执行问题, 就抽取出来单独测试, 这个查询类似这样的结构:
select count(*) from a, b where a.bid = b.bid;
其中a表中的bid是b表的id外键. 每个表大概有7k条记录.这个查询每次都耗时30s, 后来把a表中的bid字段建立个属性, 速度就快多了, 大概是300ms~1s.
以前一直没觉得索引有这么神奇的效果.....
--
It's Hard to Define, But I Know it When I See it…
select count(*) from a, b where a.bid = b.bid;
其中a表中的bid是b表的id外键. 每个表大概有7k条记录.这个查询每次都耗时30s, 后来把a表中的bid字段建立个属性, 速度就快多了, 大概是300ms~1s.
以前一直没觉得索引有这么神奇的效果.....
--
It's Hard to Define, But I Know it When I See it…
2007-07-24
接口参数类型
之前写过一个接口, 目的是更新FriendLink对象到数据库.形式如下:
update(FriendLink link);
接口的实现是这么写的:
update(FriendLink link){
dao.update(link);
}
后来, 发现有弊病在: 这个接口依赖这样的事实: link已经存在于数据库中 .这样很容易产生潜在的不安全性, 外部的任何程序都可以随意构造一个FriendLink实例(而不是从数据库中取然后稍加修改而成的), 然后传入到这个接口, 然后产生异常. 还有个问题就是, 它限制了访问媒介为java对象(须先构造出FriendLink对象来, 才能访问到这个接口), 不利于其它形式的访问(如webServices, REST等---虽然可以, 但是须对FriendLink中accessor信息了然于胸). 所以应修改如下:
update(long friendLinkId);
传入基本类型(long), 声明说会对这个(id为friendLinkId的FriendLInk)作更新, 这样, link已经存在于数据库中 这样的谓词是由接口内部来判断处理的. 对于其它形式的访问, 基本类型都是被支持的. 至于update的信息, 可以以参数形式, 或函数名形式展现, 如下:
update(long frindLinkId, Date accessDate); ①
或
updateAccessDate(long friendLinkId);②
象②这样的只传入id的接口, 依赖于"执行更新所需信息可以从接口上下文得到", 比如当前时间等.所以应用面比较狭窄, 不知道具体应该怎么处理(map参数?) :( (还是动态语言比较好, 象js的arguments参数很灵活)
--
It's Hard to Define, But I Know it When I See it…
update(FriendLink link);
接口的实现是这么写的:
update(FriendLink link){
dao.update(link);
}
后来, 发现有弊病在: 这个接口依赖这样的事实: link已经存在于数据库中 .这样很容易产生潜在的不安全性, 外部的任何程序都可以随意构造一个FriendLink实例(而不是从数据库中取然后稍加修改而成的), 然后传入到这个接口, 然后产生异常. 还有个问题就是, 它限制了访问媒介为java对象(须先构造出FriendLink对象来, 才能访问到这个接口), 不利于其它形式的访问(如webServices, REST等---虽然可以, 但是须对FriendLink中accessor信息了然于胸). 所以应修改如下:
update(long friendLinkId);
传入基本类型(long), 声明说会对这个(id为friendLinkId的FriendLInk)作更新, 这样, link已经存在于数据库中 这样的谓词是由接口内部来判断处理的. 对于其它形式的访问, 基本类型都是被支持的. 至于update的信息, 可以以参数形式, 或函数名形式展现, 如下:
update(long frindLinkId, Date accessDate); ①
或
updateAccessDate(long friendLinkId);②
象②这样的只传入id的接口, 依赖于"执行更新所需信息可以从接口上下文得到", 比如当前时间等.所以应用面比较狭窄, 不知道具体应该怎么处理(map参数?) :( (还是动态语言比较好, 象js的arguments参数很灵活)
--
It's Hard to Define, But I Know it When I See it…
Subscribe to:
Posts (Atom)