终于有一本书的读书笔记写到第二篇了,呵呵~~不过这本书的第一篇读书笔记更像是速记的内容:)
1. Javascript只有public作用域,没有private,更不用说protected,另外也没有静态方法。
2. this指向的是调用该方法的对象
obj.color = “red”;
obj.show = function(){
alert(this.color); //output “red”
}
3. 定义类的几种方法(略去最后一种,根本没看懂,而且说非常不推荐这种做法)
(1) Factory
function showColor(){
alert(this.color);
}
function createCar(color, doors, mpg){
var temp = new Object;
temp.color = color;
temp.doors = doors;
temp.mpg = mpg;
temp.showColor = showColor;
}
var car = createCar(“red”, 4, 23);
缺点:没有共享函数。不同的实例间可能有不同的函数调用。可以改变一个对象的函数绑定。不用new构造,不像是类(当然,只是不像)。
(2) Constructor
function Car(color, doors, mpg){
this.color = color;
this.doors = doors;
this.mpg = mpg;
this.showColor = function(){
alert(this.color);
}
}
var car = new Car(“red”, 4, 23);
优点:用new构造
缺点:同工厂的第一点。
(3)Prototype
function Car(){}
Car.prototype.color = “red”;
Car.prototype.doors = 4;
Car.prototype.mpg = 23;
Car.prototype.showColro = function(){
alert(this.color);
}
var car = new Car();
优点:函数真正共享,不会出现不同实例之间使用不同函数的情况(指的是同一函数名的情况下,同时Javascript里不存在函数重载)。可以使用car instanceof Car
缺点:显而易见,函数共享的同时把属性也共享了,没什么比这个更糟糕的了。
(4) Mixed Constructor/Prototype
function Car(color, doors, mpg){
this.color = color;
this.doors = doors;
this.mpg = mpg;
}
Car.prototype.showColor = function(){
alert(this.color);
}
var car = new Car(“red”, 4, 23);
优点:函数真正共享,但不共享属性。不过我发现可以把属性加入prototype来实现静态的属性。也可以使用car instanceof Car
(5) Dymanic Prototype
function Car(color, doors, mpg){
…
if(typeof Car._initialized == “undefined”){
Car.prototype.showColor = function(){
alert(this.color);
}
Car._initialized = true;
}
}
这个更大的进步就在于,函数的创建只有一次了。
4. 一个StringBuffer实例,通过Array.join()来实现append()。同时还有实现Array.indexOf()方法(这个Prototype.js里也有的)。前面一个用的是构造类,后面用的是prototype
Category: 技术
企业应用架构模式读书笔记(一)
最近懂得要写写读书笔记了。平时看了一些书,看过就忘,真是坏习惯。但记在本子上又不怎么看,觉得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()
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>
“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。]]>