企业应用架构模式读书笔记(一)

最近懂得要写写读书笔记了。平时看了一些书,看过就忘,真是坏习惯。但记在本子上又不怎么看,觉得BLOG还算个好地方。以后都记在这里吧。当然,这本书的笔记还要为技术沙龙做一些准备。
模式先不说,先把那个例子解释清楚。英文版的看起来还是有点难度的,要看两遍才知道(其实就是因为那个例子是什么意思不知道)。不过这种经典书应该是多看几遍的吧?
先把数据库表列出来
Prouducts

int id
varchar name
varchar type

Contract

int id
int product_id
int revenue
date signon

RevenueRecognition

int
contract_id
int amount
date recognizeon

有三种产品,数据库、字处理软件、电子表格软件。IBM三件套是DB2, Lotus Word, Lotus123,微软三件套大家都很了解了,不过是SqlServer, Word, Excel。产品表很好理解了。合同表里有个产品的ID,也就是说,一份合同只是一份软件(虽然听起来比较ridiculous),还有收入(估计每一份都不一样价钱吧)。比较难理解的是收确认。因为有这么一项业务逻辑:字处理软件在签合同的当天就确认收入;而电子表格是在签合同当日确认三分之一,60天后确认三分之一,90天后确认三分之一,有点像分期付款吧;数据库也分三份,当天、30天、60天。每一次确认收入都要记录在数据库里,这样可以计算在某一日前有多少已确认的收入。
服务有两项。第一项是计算某一个合同在某一天前所确认的收入。其实这靠一条SQL语句就可以办到的。第二项是向数据库里插入某项合同的确认收入条目。比如Word就插入一条,DB2就插入三条。
顺便说一说第一个模式,也是最简单的模式:Transaction Script吧。这个是初学者常用的办法,如果再高级一点,可以用上个Command模式,让所有的Script都继承一个接口。所有的业务都在一个Script里完成,包括了业务逻辑、数据库操作、甚至是事务处理。这种模式,毋宁说是反模式,成也简单、败也简单。当然做一个DEMO、或者是以后不需要扩展的程序还是可以考虑这种模式的,呵呵。

FCKEdtior初步集成

我使用的是Javascript版本+Java的。主要用Javascript, Java的只是用来参考一下源代码。
1. 拷贝文件,主要是js包里的,根目录下fckeditor.js, fckconfig.js, fckstyles.js, fcktemplates.js以及editor目录拷贝到web应用下。拷贝到哪里与以后要设置的BasePath有关系。
2. 显示代码: 在页面里包含 fckeditor.js。然后写这一段:
<script type=”text/javascript”>
var oFCKeditor = new FCKeditor(‘content’) ;
oFCKeditor.BasePath = “fckeditor/” ;
oFCKeditor.Height = 600;
oFCKeditor.ToolbarSet = “Default” ;
oFCKeditor.Value = ”;
oFCKeditor.Create();
</script>
最主要是BasePath的设置。比如你把fckeditor.js放在了http://localhost:8080/test/fckeditor/fckeditor.js,你的调用文件在http://localhost:8080/test下,你就把BasePath设成”fckeditro/”(后面要跟’/’)
3. 上传文件的设置:
(1)修改fckconfig.js里的最后几部分,如LinkUploadURL, ImageUploadURL, FlashUploadURL,改成你上传文件的地址。不管那些什么Language了。
(2)修改editor/filemanager/browser/default/frmupload.html,把那个form的action改成上传的地址。这个不知道为什么,我是找了好久才找到的。
(3)编写upload servlet。参考Java包里的那个ConnectorServlet里的doPost()方法。 主要是返回值要设对。

javascript高级程序设计读书笔记(一)

上“人机交互”课上时记的一些东西,留下来备忘。上次那个JVM书的读书笔记真的只有一篇了,因为只能在IBM里才能看到,呵呵~~
1. isFinit(Number) 判断数字是不是无穷大, isNan(..)判断是不是数字
2. parseInt(String, int), 可以解析各种进制的整数
3. Nan != NaN, typeof(null) == “object”
4. Stirng.charCodeAt(int)
5. String.slice()基本上等于String.substring,不同的是substring(3, -4) == substring(3),对于负数,substring是忽略的。
6. ===, !==
7. Array.push(), Array.pop(), Array.shift(), Array.unshift()
8. Array.splice(),可以插入、替换、删除数组中的元素
9. Global对象,很大部分全局函数是Global对象的属性
10. encodeURI(), encodeURIComponent()

要学的技术太多了

(本来只想放在我的技术blog里的,想了想也转到这里吧)
在IBM实习了三个月,学到了不少东西,认识了不少同事,见识了大公司的开发流程,但同时,我的学习也被耽搁了三个月。本来计划得不错,下班和周末可以好好看看书了。但毕竟上班对着电脑8、9个小时的,下班了见了电脑屏就恶心,书也不想看,除了看看电视、报纸杂志什么的,其他也没什么兴趣了。于是这些学习计划也就作空了。不过后来的开发任务少了,上班时间也开始看看东西。回学校以后,发现自己已经落后于时代了。
感觉落后主要来源于低年级的同学吧。觉得最近我和他们都是在交流、研究同一种东西,对于JAVA的开源工具、框架的使用情况也差不多。其实对于JAVA,我的入门还是比较晚的。大一一直都在搞C++,大二上学期新学JAVA,对JAVA还比较不屑,那个时候加入了工作室,然后就折腾了一个学年的.NET,感觉也没学到什么东西。大三开始做JAVA的Web应用,对JAVA才有一点点感觉。不过DLZX网站的开发对我来说是一个噩梦,对Web应用的感觉还不是很好。然后是VOD的项目,经验不足导致开发产品的质量很差。不过终于开始学习开源框架和工具了,接触了Hibernate和Velocity(这主要还是得到了烧饭的提示),才开始对Java Web应用有一点点感觉。而CMS之后,我也决定了以后的发展方向–Java,以Web为主。再加上实习三个月,我和他们基本上处于同一水平线上吧。这也是我一直所乐于见到的,有一群技术相当的人可以一起做项目,进行讨论。
说到技术上,特别是Java Web,我主攻的技术的落后,还是比较惭愧的。现在主流的开源框架中的核心–Spring,我是压根没用过,虽然书和技术文档看过一些,但还是没有真正动过手实践。而Web层的框架,除了Struts,也没用过别的,比如WebWork,Tapestry, Maverick, JSF等等。就是Struts,也觉得用的不是很深,而那些Taglib基本就没动过,因为我主要用的是Velocity(模板还行,不过Velocity是个轻量级的东东,也没多少东西可以深入,而FreeMarker就是不懂了)。模型层技术除了Hibernate(也只是简单的用用),也没试过IBatis,更糟糕的是,JDBC基本上忘了该怎么用了。更不用说那些数据库连接池DBCP、C3P0,还有缓存的工具OSCache,EhCache,JBossCache。EJB更是一窍不通。Jakarta底下的项目,比如commons,除了io和fileupload接触过,beanutils之类比较基本的不行(所以一直想用那本Jakarta-commons实例,不过图书馆的被人借走了,有米了买一本吧)。
最近大三的在做TORM的软件设计大作业,用到的一些技术也是我没有接触过的。比如cglib和BCEL。其实本来对Reflection的运用就不够。Java Security的技术倒是最近一直在看,对ClassLoader有一点感觉了,不过没有做到具体的应用。Java底层如JVM的东西也还待挖掘。
Web方面,本来一直在看Ajax的,不过被实习打断了。最近重拾Ajax in Action,反有几份陌生。Javascript的类库只会用prototype的很基本的功能。而高级一些的如DWR, Dojo的没见过。我想,连Widget Base都还没达到吧。
对于桌面应用,RCP、OSGi等技术也很不错,在IBM的时候看了一些资料,跟tutorial做几个demo,有不小的兴趣。
Java已经如此,更不说其他方面了。最近也在学RoR,觉得开发实在是太便利了。约定高于配置,多么好的开发场景。Python, Perl早浮云了。
接下去还有Apache, Linux… .NET呢?下辈子吧,呵呵
当然,我也知道不能好高骛远。只是感叹一下,技术如此之多。以上也只要任选一种,就够捧个好饭碗的了~~~不过好高骛远好像一向是技术人员的毛病。。。
嗯,脚踏实地,从开发中学习吧!
对了,好像还有管理要积累经验的吧?我晕。。。

Web文件上传的草案

转自张博的blog。想到写以前的项目,要做到Ajax,可是在文件上传这一步,始终没办法逾越。只能用
<form target=”…” enctype=”multi-part/form-data” method=”post” >

</form>
<iframe name=”..”/>
这种提交到一个内部iframe的办法搞。而且上传结束的event只能通过服务器端返回的javascript调用,可以说要多难看有多难看。这个draft定义的API虽然简单,可是也够用咯~~
<![CDATA[转自张博的blog。想到写以前的项目,要做到Ajax,可是在文件上传这一步,始终没办法逾越。只能用

这种提交到一个内部iframe的办法搞。而且上传结束的event只能通过服务器端返回的javascript调用,可以说要多难看有多难看。这个draft定义的API虽然简单,可是也够用咯~~]]>

Java Servlet文件上传解决方案(主要针对中文)

以前做动力中心那个网站的时候,由于用户要求要上传图片以及一些文件,所以要一个上传Servlet的组件。最后选中了SmartUpload,至少在Baidu上搜,到处都是。
没想到这才是噩梦的开始。主要问题是在中文文件名上。后来找了很多资料,用了一个迫不得已的最后方法:重新编译SmartUpload,加上中文的解决方法。后来也不知道怎么也就OK了。
前几个月动力中心的硬盘挂了,数据全丢了。不巧,我这里也没有备份,工作室的备份也丢了。没有办法,只好从一个旧的版本改起。其实中文开发的问题还是很多的,即使在Windows下好好的,到Linux下也会出各种各样的问题(比如Locale是en_US.UTF8)等等。
再也恢复不起来原来的办法了。后来也是在网上找到的资料,说是可以用Commons里的FileUpload. Jakarta Commons名气挺大的,我一起想学学,却一直忘,也不知道该怎么用(以前只听过BeanUtils, 用来注入一个bean的)。
马上从Apache下了一个来试试。注意,要用起来FileUpload,还要下一个Commons IO。里面对国际化的支持还是不错的,至少我用item.getName()出来的居然就有中文。
但保存文件还是遇到了问题。为了对国际化的良好支持,要达到以下几点:在页面显示的文件名要是中文的,下载的时候保存的文件名也要是中文的,同时文件要保存在一个目录下。
在做链接生成的时候,我发现浏览器会把链接中的中文自动encode成UTF-8的URL表示(就是%20%30那种)。没错,文件保存也可以用这个名字,这样在不支持中文路径的linux上也可以保存中文文件名了。然后我自己写了一个下载的Servlet,用于从本地读取文件内容,并写入response.getWriter()里。这样的话文件名自动就成中文了。至于重名问题,我的链接是这么写的: http://www.test.com/download/1892649237492/%8D%82.txt 结果文件名会自动转成中文的(IE6, FF1.5通过)。但是实际的文件名是1892649237492%8D%82.txt,就是没有了”/”,这一点,在Download Servlet里解析。同时DownloadServlet里加了一些逻辑,保护系统的安全。

javascript获取textarea光标选择位置和内容方法(IE, Firefox)

在网上用baidu找了很久,找到的都是IE的方法,Firefox都不能用。 而且很多要用到<textarea>.focus()方法,用起来很不方便。
后来转用Google,搜了下”textarea cursor”,第一个就有好方法。我根据最后一个家伙的comments,写了一个sample,应该还是挺好用的。
原文地址:http://weblogs.asp.net/skillet/archive/2005/03/24/395838.aspx
<html>
<head>
<title>TEST</title>
<style>
body,td{
font-family: verdana, arial, helvetica, sans-serif;
font-size: 12px;
}
</style>
<script type=”text/javascript”>
var start=0;
var end=0;
function add(){
var textBox = document.getElementById(“ta”);
var pre = textBox.value.substr(0, start);
var post = textBox.value.substr(end);
textBox.value = pre + document.getElementById(“inputtext”).value + post;
}
function savePos(textBox){
//如果是Firefox(1.5)的话,方法很简单
if(typeof(textBox.selectionStart) == “number”){
start = textBox.selectionStart;
end = textBox.selectionEnd;
}
//下面是IE(6.0)的方法,麻烦得很,还要计算上’\n’
else if(document.selection){
var range = document.selection.createRange();
if(range.parentElement().id == textBox.id){
// create a selection of the whole textarea
var range_all = document.body.createTextRange();
range_all.moveToElementText(textBox);
//两个range,一个是已经选择的text(range),一个是整个textarea(range_all)
//range_all.compareEndPoints()比较两个端点,如果range_all比range更往左(further to the left),则                //返回小于0的值,则range_all往右移一点,直到两个range的start相同。
// calculate selection start point by moving beginning of range_all to beginning of range
for (start=0; range_all.compareEndPoints(“StartToStart”, range) < 0; start++)
range_all.moveStart(‘character’, 1);
// get number of line breaks from textarea start to selection start and add them to start
// 计算一下\n
for (var i = 0; i <= start; i ++){
if (textBox.value.charAt(i) == ‘\n’)
start++;
}
// create a selection of the whole textarea
var range_all = document.body.createTextRange();
range_all.moveToElementText(textBox);
// calculate selection end point by moving beginning of range_all to end of range
for (end = 0; range_all.compareEndPoints(‘StartToEnd’, range) < 0; end ++)
range_all.moveStart(‘character’, 1);
// get number of line breaks from textarea start to selection end and add them to end
for (var i = 0; i <= end; i ++){
if (textBox.value.charAt(i) == ‘\n’)
end ++;
}
}
}
document.getElementById(“start”).value = start;
document.getElementById(“end”).value = end;
}
</script>
</head>
<body>
<form action=”a.cgi”>
<table border=”1″ cellspacing=”0″ cellpadding=”0″>
<tr>
<td>start: <input type=”text” id=”start” size=”3″/></td>
<td>end: <input type=”text” id=”end” size=”3″/></td>
</tr>
<tr>
<td colspan=”2″>
<textarea id=”ta” onKeydown=”savePos(this)”
onKeyup=”savePos(this)”
onmousedown=”savePos(this)”
onmouseup=”savePos(this)”
onfocus=”savePos(this)”
rows=”14″ cols=”50″></textarea>
</td>
</tr>
<tr>
<td><input type=”text” id=”inputtext” /></td>
<td><input type=”button” onClick=”add()” value=”Add Text”/></td>
</tr>
</table>
</form>
</body>
</html>

如何配置tomcat的ROOT为/

修改%TOMCAT_ROOT%/conf/Catalina/localhost下的Web应用配置文件。
1.删除或移走ROOT.xml,这个文件就 是tomcat的root配置;
2.修改server.xml, <Host>里加上
<Context docBase=”test” path=”” workDir=”work\Catalina\localhost\test” reloadable=”true”/>
docBase:为你的Web应用程序所在的路径,可以为相对和绝对路径, 相对路径 为相对于在<Host>里配置的属性appBase的路径;
path:为Web应用的上下文路径,保持为空则会绑定到root路径上;(其实就是如果没有被其他<Context>定义了,就到这个目录去。
workDir: 为Web应用的临时工作目录,存放编译后的类和页面。
Tomcat的doc:
If you specify a context path of an empty string (“”), you are defining the default web application for this Host, which will process all requests not assigned to other Contexts. The value of this field must not be set except when statically defining a Context in server.xml, as it will be infered from the filenames used for either the .xml context file or the docBase.
还有一个debug属性,经常看到人写,但在tomcat的文档里没有看到,不知道是为什么。
文档地址 http://tomcat.apache.org/tomcat-5.5-doc/config/context.html
<![CDATA[修改%TOMCAT_ROOT%/conf/Catalina/localhost下的Web应用配置文件。
1.删除或移走ROOT.xml,这个文件就 是tomcat的root配置;
2.修改server.xml, 里加上

docBase:为你的Web应用程序所在的路径,可以为相对和绝对路径, 相对路径 为相对于在里配置的属性appBase的路径;
path:为Web应用的上下文路径,保持为空则会绑定到root路径上;(其实就是如果没有被其他定义了,就到这个目录去。
workDir: 为Web应用的临时工作目录,存放编译后的类和页面。
Tomcat的doc:
If you specify a context path of an empty string (“”), you are defining the default web application for this Host, which will process all requests not assigned to other Contexts. The value of this field must not be set except when statically defining a Context in server.xml, as it will be infered from the filenames used for either the .xml context file or the docBase.
还有一个debug属性,经常看到人写,但在tomcat的文档里没有看到,不知道是为什么。
文档地址 http://tomcat.apache.org/tomcat-5.5-doc/config/context.html%5D%5D&gt;

“Working with Java Virtual Machine” 读书笔记(一)

在books24x7.com上在线看的这本书(不过不是免费的,IBM为员工买了这个网站的阅读权利),觉得有些东西有必要记下来。不知道有“一”还会不会有“二”,呵呵。
Chapter 2 Overview of JVM architecture, Section 2 Runtime Data Areas in JVM
JVM data area:
1. Method area
2. Heap
3. PC Register
4. Java Stack
5. Native Method Stack
Method area: Shared among all JVM thread
1. name
2. super class
3. class/interface
4. modifier
5. list of super interfaces
6. Other:
a. Constant pool
b. field info
c. method info
d. class var
e. ref to Classloader
f. ref to Class
Heap:
1. Handle pool: pointer to object(in object pool) & class(in method area)
2. Object pool (instances)
Such design is for the avoiding fragmentation
Stach: 2 types
1. Frame for func activation
2. Operand for instructions, arg & ret of JVM instruction
Java Stack Component
1. local var
2. execution env
3. operand stack
JDK — JRE — JVM — bytecode Interpreter, GC, Class manager, …
\            \
classlib — byte code
\
native

做DITAOT的碰到xalan的一些问题

1. SUN JDK自带了一个xalan,不过版本比较老,要把它给替换掉。但办法不是把xalan.jar放到CLASSPATH里。要放在jre里的endorsed目录下。
这个FAQ下有解答:(http://xml.apache.org/xalan-j/faq.html#faq-N100D6)
2. xalan里用document()函数load外面的XML文档的时候,在一个stylesheet里,不能读两次一个文件,不然会抛出下面的错误: Programmer’s Error; “putDocumentInCache found reparse of doc: “ 这是一个比较SB的BUG,如果xalan查到这个文件在cache里了,他就不干了,说你应该用一个variable把文件里的内容存起来,不要给我读两次。这是我见过最SB的理由。让你读文件你就给我读,JJWW干什么,在cache里有是吧?给我从cache里读出来就可以了啊!
不过这个问题好像是出现在输入文件的路径有空格的情况下,要再查一查。
3. 好像没有了。。想不起来了。。不然就是没有碰到过,因为我平常是用的SAXON。嗯,在这里推荐一下SAXON,很不错的一个xslt processor。
<![CDATA[1. SUN JDK自带了一个xalan,不过版本比较老,要把它给替换掉。但办法不是把xalan.jar放到CLASSPATH里。要放在jre里的endorsed目录下。
这个FAQ下有解答:(http://xml.apache.org/xalan-j/faq.html#faq-N100D6)
2. xalan里用document()函数load外面的XML文档的时候,在一个stylesheet里,不能读两次一个文件,不然会抛出下面的错误: Programmer's Error; “putDocumentInCache found reparse of doc: “ 这是一个比较SB的BUG,如果xalan查到这个文件在cache里了,他就不干了,说你应该用一个variable把文件里的内容存起来,不要给我读两次。这是我见过最SB的理由。让你读文件你就给我读,JJWW干什么,在cache里有是吧?给我从cache里读出来就可以了啊!
不过这个问题好像是出现在输入文件的路径有空格的情况下,要再查一查。
3. 好像没有了。。想不起来了。。不然就是没有碰到过,因为我平常是用的SAXON。嗯,在这里推荐一下SAXON,很不错的一个xslt processor。]]>