<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>idv2 &#187; 编程开发</title>
	<atom:link href="http://tech.idv2.com/category/develop/feed/" rel="self" type="application/rss+xml" />
	<link>http://tech.idv2.com</link>
	<description>关注Web开发技术，关注Internet。</description>
	<lastBuildDate>Tue, 27 Jul 2010 12:54:54 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PostScript入门(2)-基础概念</title>
		<link>http://tech.idv2.com/2010/07/27/postscript-tutorial-2/</link>
		<comments>http://tech.idv2.com/2010/07/27/postscript-tutorial-2/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 12:53:49 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[postscript]]></category>

		<guid isPermaLink="false">http://tech.idv2.com/?p=811</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p>上一章，我们简单介绍了PostScript语言，以及如何在Windows、Linux上
运行PostScript。PostScript是个页面描述语言，也是个编程语言。
本章将介绍PostScript的语言基础概念和图形基础概念，
为以后的几章做个铺垫。</p>
<!-- end Pukiwiki generated code--><span id="more-811"></span><!-- begin Pukiwiki generated code--><h2 id="content_2_0">语言基础概念</h2>
<p>从编程语言的角度来看，PostScript是十分简单的。PostScript是一种RPN，
即“逆波兰式”（Reverse Polish Notation），或称“后置记法”。
学过数据结构的人想必不陌生吧。简单来说就是<strong>操作数在前，操作符在后</strong>。
一般我们使用“中置记法”，比如 1 + 2，加号写在两个操作数1和2的中间；
但在PostScript中，要把加号放在最后，写成“1 2 add”。这是PostScript
的基础。</p>

<h3 id="content_2_1">栈</h3>
<p>后置记法最大的好处就是处理方便。学过编译原理的同学应该不会忘记
中置记法中的表达式歧义问题带来的痛苦吧（比如处理1+2*3，就必须用某种
方式告诉计算机是先计算1+2还是先计算2*3），但在后置记法中就不会有这个问题。
只需用一个栈，依次处理表达式中的符号，''遇到操作数就压栈，遇到操作符
就从栈顶弹出相应数量的操作数进行计算，并把计算结果压栈。''
例如，要计算(1+2)*(7-4)，用PostScript表示如下：</p>
<pre>1 2 add 7 4 sub mul ==</pre>
<p>末尾的“==”表示显示栈顶元素。这行代码可以直接在GhostScript的提示符下运行，
结果如下所示：</p>
<pre>GS&gt;1 2 add 7 4 sub mul ==
9</pre>
<p>下面来解释一下运行过程：</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">处理的符号</td><td class="style_td">操作</td><td class="style_td">栈的内容(右边为栈顶)</td></tr><tr><td class="style_td">1</td><td class="style_td">压栈</td><td class="style_td">1</td></tr><tr><td class="style_td">2</td><td class="style_td">压栈</td><td class="style_td">1 2</td></tr><tr><td class="style_td">add</td><td class="style_td">栈顶两元素出栈，计算加法，计算结果压栈</td><td class="style_td">3</td></tr><tr><td class="style_td">7</td><td class="style_td">压栈</td><td class="style_td">3 7</td></tr><tr><td class="style_td">4</td><td class="style_td">压栈</td><td class="style_td">3 7 4</td></tr><tr><td class="style_td">sub</td><td class="style_td">栈顶两元素出战，计算减法，计算结果压栈</td><td class="style_td">3 3</td></tr><tr><td class="style_td">mul</td><td class="style_td">栈顶两元素出栈，计算乘法，计算结果压栈</td><td class="style_td">9</td></tr><tr><td class="style_td">==</td><td class="style_td">栈顶一元素出栈并显示</td><td class="style_td">&lt;空&gt;</td></tr></tbody></table></div>
<p>可见，这种方式完全不需要对表达式进行语法分析，所以PostScript解析器
可以做得相当简单。实际上，PostScript语言中的确有这样一个栈，
用于存放操作符和操作数并进行计算，称为“操作数栈”。</p>
<p>在GhostScript中，栈的大小会显示在操作数之后。例如，可以逐个地
输入上述表达式（PostScript语言中，空白和换行是没有意义的，
所以一条命令可以分成几行写，也可以写在同一行上，效果相同）：</p>
<pre>GS&gt;1
GS&lt;1&gt;2
GS&lt;2&gt;add
GS&lt;1&gt;7
GS&lt;2&gt;4
GS&lt;3&gt;sub
GS&lt;2&gt;</pre>
<p>“GS”后面的数字就是栈中的操作数个数。“pstack”命令可以查看栈的内容，
例如在上面 GS&lt;2&gt; 的状态下执行结果为：</p>
<pre>GS&lt;2&gt;pstack
3
3</pre>
<p>另外，这里的“操作数”和“操作符”的概念也可以理解为“参数”和“函数”，
计算后的结果可以认为是函数的“返回值”。</p>

<h3 id="content_2_2">数据类型</h3>
<p>PostScript中的数据类型有数字、字符串、数组和过程。</p>

<h4 id="content_2_3">数字</h4>
<p>PostScript支持整数和实数。整数部分为0的小数可以省略整数部分，如：</p>
<pre>.123          % 表示 0.123</pre>
<p>此外还有进制计数法和科学计数法。进制计数法写成“基数#值”，例如</p>
<pre>16#ff         % 表示16进制的0xff，即255
8#777         % 表示8进制的0777，即511
7#33          % 连7进制都可以使用
2#3           % 出错，因为2进制中没有3这个符号</pre>
<p>科学计数法写成“尾数E指数”，例如</p>
<pre>1E10          % 表示1e+10
1.234E-2      % 表示0.01234</pre>

<h4 id="content_2_4">字符串</h4>
<p>字符串用圆括号表示，例如</p>
<pre>(abcdefg)     % 表示字符串&quot;abcdefg&quot;
(a(b)c)       % 表示字符串&quot;a(b)c&quot;，圆括号内成对的圆括号失去特殊意义
(a\(bc)       % &quot;a(bc&quot;，单个圆括号需要转义
(a\nb)        % &quot;a&lt;换行&gt;b&quot;</pre>
<p>转义符的形式有：</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">\t</td><td class="style_td">TAB符号</td></tr><tr><td class="style_td">\n</td><td class="style_td">换行(line feed)</td></tr><tr><td class="style_td">\r</td><td class="style_td">回车(carriage return)</td></tr><tr><td class="style_td">\f</td><td class="style_td">换页(form feed)</td></tr><tr><td class="style_td">\b</td><td class="style_td">退格</td></tr><tr><td class="style_td">\(</td><td class="style_td">左圆括号</td></tr><tr><td class="style_td">\)</td><td class="style_td">右圆括号</td></tr><tr><td class="style_td">\\</td><td class="style_td">反斜杠</td></tr><tr><td class="style_td">\ddd</td><td class="style_td">用八进制表示的字符</td></tr></tbody></table></div>
<p>注意转义符中没有十六进制表示（\xnn）。</p>
<p>此外，也可以直接在字符串中加入换行：</p>
<pre>GS&gt;(abcd
efg)
GS&lt;1&gt;pstack
(abcd\nefg)</pre>
<p>如果想在代码中让字符串换行，但并不想在字符串中加入换行，
可以在行尾使用 \ 符号：</p>
<pre>(This is a \
string \
that has no \
newlines)</pre>
<p>的值为</p>
<pre>(This is a string that has no newlines)</pre>
<p>字符串还可以用十六进制表示，只需将十六进制数写在尖括号中。例如：</p>
<pre>&lt;616263&gt;    % 表示&quot;abc&quot;
&lt;6d 6e 6f&gt;  % 表示&quot;mno&quot;，中间加入空格或换行不起作用</pre>

<h4 id="content_2_5">布尔值</h4>
<p>PostScript支持 true 和 false 两个布尔值。例如：</p>
<pre>GS&gt;true false
GS&lt;2&gt;pstack
false
true</pre>

<h4 id="content_2_6">数组</h4>
<p>数组是一系列操作数的排列，用方括号括起来。数组中的数据可以是任何类型，
甚至可以是另一个数组。</p>
<pre>[ 367 28.4 (abc) true ]    % 四个不同类型元素的数组
[ 1 2 add 7 4 sub ]        % 值为[3 3]。数组中甚至可以做运算，数组值为运算结果
[ 21 [ 53 74 ] [ 60 [ 53 48 ] 99 ] 18 ]    % 可以任意嵌套
[ ]                        % 空数组</pre>

<h4 id="content_2_7">过程</h4>
<p>过程是一系列操作符和操作数的排列，放在大括号中，用于自定义操作符。
例如：</p>
<pre>{ dup mul }                % 计算平方。dup表示复制栈顶元素，mul表示栈顶两元素相乘</pre>
<p>实际应用中需要使用def操作符将过程定义到名字(见下文)上，如：</p>
<pre>GS&gt;/square { dup mul } def   % 定义 square 为 { dup mul }
GS&gt;3 square ==               % 调用 square
9</pre>

<h4 id="content_2_8">字典</h4>
<p>字典是一系列成对的名字和值，相当于Perl语言中的哈希表，或者Java中的HashMap。</p>

<h3 id="content_2_9">名字</h3>
<p><strong>名字</strong>是任何不是数字的符号，相当于一般编程语言中的标识符。
名字可以由除了空格和特定保留字符（(、)、[、]、&lt;、&gt;、{、}、/和%）以外的
任意字符组成，例如abc、$def、ghi-jkl都是有效的名字。
名字甚至可以以数字开头，例如 1Z 是有效的名字，但这种习惯有时会遇到问题
（如 1E10 是个实数）。</p>
<p>通常，名字出现时会被当作操作符，PostScript会去“调用”该名字对应的过程。
那么怎样给名字定义“过程”呢？这就需要使用“字面意义的名字”（literal name）
和 def 操作符。在名字前面加上 / 符号，可以告诉PostScript，我们要定义这个名字了，
别把它当作操作符，当作操作数压进栈里就行了。def 操作符则从栈顶弹出两个元素，
并把第二个元素（字面意义的名字）定义为第一个元素（过程）。例如：</p>
<pre>/square { dup mul } def     % 定义 square 为 { dup mul }
3 square                    % 调用 square，相当于 3 dup mul</pre>
<p>这里还要说明一下，所谓“调用”并不是像C语言那样跳转到函数定义的位置去执行。
PostScript中的过程实质上是一系列的操作符和操作数，在“调用”
一个名字时，PostScript简单地用该名字对应的那个过程来替换该名字，
然后依次执行。例如上面的 3 square，PostScript在遇到 square时，
从以前的定义中找到 square 相当于 { dup mul }，于是将 square “展开”
成 dup mul，再依次执行，其效果跟直接写 3 dup mul 是相同的。</p>

<h3 id="content_2_10">注释</h3>
<p>PostScript中使用 % 符号表示注释，% 之后的内容会被忽略。</p>

<h2 id="content_2_11">图形基础概念</h2>
<p>作为页面描述语言，PostScript的主要功能就是绘图和显示文字，那么有几个
图形方面的基础概念是必须要了解的。</p>

<h3 id="content_2_12">用户空间</h3>
<p>用户空间是PostScript用于表达点和线的位置的坐标系。它的原点(0, 0)位于左下角，
x轴向右，y轴向上，相当于数学中的第一象限。</p>
<p>用户空间的默认单位是<strong>点</strong>（point）。一个point相当于1/72英寸，
这个值比真正打印机上的point（等于1/72.27英寸）稍稍短一些。</p>
<p>实际应用中，可以作以下定义，以便在PostScript程序中使用英寸、毫米等比较直观的单位。</p>
<pre>/mm { 2.834646 mul } def       % 毫米
/inch { 72 mul } def           % 英寸
1 inch 20 mm moveto            % 应用例</pre>

<h3 id="content_2_13">路径</h3>
<p>路径是页面上一系列直线和曲线的组合。它并不是可见的线条，只是假想的一条路径而已。
通过 stroke 和 fill 操作符可以描边或填充路径（用过Photoshop就能理解），使之可见。</p>

<h3 id="content_2_14">图形状态</h3>
<p>图形有许多状态（如当前颜色、当前路径、线的粗细、坐标系等）。
程序有时需要临时改变图形状态，此时应该将当前的图形状态保存到<strong>图形状态栈</strong>（graphics state stack）中，
画完之后再恢复状态。保存和恢复可以通过gsave和grestore操作符来实现。</p>
<!-- end Pukiwiki generated code-->
]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p>上一章，我们简单介绍了PostScript语言，以及如何在Windows、Linux上
运行PostScript。PostScript是个页面描述语言，也是个编程语言。
本章将介绍PostScript的语言基础概念和图形基础概念，
为以后的几章做个铺垫。</p>
<!-- end Pukiwiki generated code--><span id="more-811"></span><!-- begin Pukiwiki generated code--><h2 id="content_4_0">语言基础概念</h2>
<p>从编程语言的角度来看，PostScript是十分简单的。PostScript是一种RPN，
即“逆波兰式”（Reverse Polish Notation），或称“后置记法”。
学过数据结构的人想必不陌生吧。简单来说就是<strong>操作数在前，操作符在后</strong>。
一般我们使用“中置记法”，比如 1 + 2，加号写在两个操作数1和2的中间；
但在PostScript中，要把加号放在最后，写成“1 2 add”。这是PostScript
的基础。</p>

<h3 id="content_4_1">栈</h3>
<p>后置记法最大的好处就是处理方便。学过编译原理的同学应该不会忘记
中置记法中的表达式歧义问题带来的痛苦吧（比如处理1+2*3，就必须用某种
方式告诉计算机是先计算1+2还是先计算2*3），但在后置记法中就不会有这个问题。
只需用一个栈，依次处理表达式中的符号，''遇到操作数就压栈，遇到操作符
就从栈顶弹出相应数量的操作数进行计算，并把计算结果压栈。''
例如，要计算(1+2)*(7-4)，用PostScript表示如下：</p>
<pre>1 2 add 7 4 sub mul ==</pre>
<p>末尾的“==”表示显示栈顶元素。这行代码可以直接在GhostScript的提示符下运行，
结果如下所示：</p>
<pre>GS&gt;1 2 add 7 4 sub mul ==
9</pre>
<p>下面来解释一下运行过程：</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">处理的符号</td><td class="style_td">操作</td><td class="style_td">栈的内容(右边为栈顶)</td></tr><tr><td class="style_td">1</td><td class="style_td">压栈</td><td class="style_td">1</td></tr><tr><td class="style_td">2</td><td class="style_td">压栈</td><td class="style_td">1 2</td></tr><tr><td class="style_td">add</td><td class="style_td">栈顶两元素出栈，计算加法，计算结果压栈</td><td class="style_td">3</td></tr><tr><td class="style_td">7</td><td class="style_td">压栈</td><td class="style_td">3 7</td></tr><tr><td class="style_td">4</td><td class="style_td">压栈</td><td class="style_td">3 7 4</td></tr><tr><td class="style_td">sub</td><td class="style_td">栈顶两元素出战，计算减法，计算结果压栈</td><td class="style_td">3 3</td></tr><tr><td class="style_td">mul</td><td class="style_td">栈顶两元素出栈，计算乘法，计算结果压栈</td><td class="style_td">9</td></tr><tr><td class="style_td">==</td><td class="style_td">栈顶一元素出栈并显示</td><td class="style_td">&lt;空&gt;</td></tr></tbody></table></div>
<p>可见，这种方式完全不需要对表达式进行语法分析，所以PostScript解析器
可以做得相当简单。实际上，PostScript语言中的确有这样一个栈，
用于存放操作符和操作数并进行计算，称为“操作数栈”。</p>
<p>在GhostScript中，栈的大小会显示在操作数之后。例如，可以逐个地
输入上述表达式（PostScript语言中，空白和换行是没有意义的，
所以一条命令可以分成几行写，也可以写在同一行上，效果相同）：</p>
<pre>GS&gt;1
GS&lt;1&gt;2
GS&lt;2&gt;add
GS&lt;1&gt;7
GS&lt;2&gt;4
GS&lt;3&gt;sub
GS&lt;2&gt;</pre>
<p>“GS”后面的数字就是栈中的操作数个数。“pstack”命令可以查看栈的内容，
例如在上面 GS&lt;2&gt; 的状态下执行结果为：</p>
<pre>GS&lt;2&gt;pstack
3
3</pre>
<p>另外，这里的“操作数”和“操作符”的概念也可以理解为“参数”和“函数”，
计算后的结果可以认为是函数的“返回值”。</p>

<h3 id="content_4_2">数据类型</h3>
<p>PostScript中的数据类型有数字、字符串、数组和过程。</p>

<h4 id="content_4_3">数字</h4>
<p>PostScript支持整数和实数。整数部分为0的小数可以省略整数部分，如：</p>
<pre>.123          % 表示 0.123</pre>
<p>此外还有进制计数法和科学计数法。进制计数法写成“基数#值”，例如</p>
<pre>16#ff         % 表示16进制的0xff，即255
8#777         % 表示8进制的0777，即511
7#33          % 连7进制都可以使用
2#3           % 出错，因为2进制中没有3这个符号</pre>
<p>科学计数法写成“尾数E指数”，例如</p>
<pre>1E10          % 表示1e+10
1.234E-2      % 表示0.01234</pre>

<h4 id="content_4_4">字符串</h4>
<p>字符串用圆括号表示，例如</p>
<pre>(abcdefg)     % 表示字符串&quot;abcdefg&quot;
(a(b)c)       % 表示字符串&quot;a(b)c&quot;，圆括号内成对的圆括号失去特殊意义
(a\(bc)       % &quot;a(bc&quot;，单个圆括号需要转义
(a\nb)        % &quot;a&lt;换行&gt;b&quot;</pre>
<p>转义符的形式有：</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">\t</td><td class="style_td">TAB符号</td></tr><tr><td class="style_td">\n</td><td class="style_td">换行(line feed)</td></tr><tr><td class="style_td">\r</td><td class="style_td">回车(carriage return)</td></tr><tr><td class="style_td">\f</td><td class="style_td">换页(form feed)</td></tr><tr><td class="style_td">\b</td><td class="style_td">退格</td></tr><tr><td class="style_td">\(</td><td class="style_td">左圆括号</td></tr><tr><td class="style_td">\)</td><td class="style_td">右圆括号</td></tr><tr><td class="style_td">\\</td><td class="style_td">反斜杠</td></tr><tr><td class="style_td">\ddd</td><td class="style_td">用八进制表示的字符</td></tr></tbody></table></div>
<p>注意转义符中没有十六进制表示（\xnn）。</p>
<p>此外，也可以直接在字符串中加入换行：</p>
<pre>GS&gt;(abcd
efg)
GS&lt;1&gt;pstack
(abcd\nefg)</pre>
<p>如果想在代码中让字符串换行，但并不想在字符串中加入换行，
可以在行尾使用 \ 符号：</p>
<pre>(This is a \
string \
that has no \
newlines)</pre>
<p>的值为</p>
<pre>(This is a string that has no newlines)</pre>
<p>字符串还可以用十六进制表示，只需将十六进制数写在尖括号中。例如：</p>
<pre>&lt;616263&gt;    % 表示&quot;abc&quot;
&lt;6d 6e 6f&gt;  % 表示&quot;mno&quot;，中间加入空格或换行不起作用</pre>

<h4 id="content_4_5">布尔值</h4>
<p>PostScript支持 true 和 false 两个布尔值。例如：</p>
<pre>GS&gt;true false
GS&lt;2&gt;pstack
false
true</pre>

<h4 id="content_4_6">数组</h4>
<p>数组是一系列操作数的排列，用方括号括起来。数组中的数据可以是任何类型，
甚至可以是另一个数组。</p>
<pre>[ 367 28.4 (abc) true ]    % 四个不同类型元素的数组
[ 1 2 add 7 4 sub ]        % 值为[3 3]。数组中甚至可以做运算，数组值为运算结果
[ 21 [ 53 74 ] [ 60 [ 53 48 ] 99 ] 18 ]    % 可以任意嵌套
[ ]                        % 空数组</pre>

<h4 id="content_4_7">过程</h4>
<p>过程是一系列操作符和操作数的排列，放在大括号中，用于自定义操作符。
例如：</p>
<pre>{ dup mul }                % 计算平方。dup表示复制栈顶元素，mul表示栈顶两元素相乘</pre>
<p>实际应用中需要使用def操作符将过程定义到名字(见下文)上，如：</p>
<pre>GS&gt;/square { dup mul } def   % 定义 square 为 { dup mul }
GS&gt;3 square ==               % 调用 square
9</pre>

<h4 id="content_4_8">字典</h4>
<p>字典是一系列成对的名字和值，相当于Perl语言中的哈希表，或者Java中的HashMap。</p>

<h3 id="content_4_9">名字</h3>
<p><strong>名字</strong>是任何不是数字的符号，相当于一般编程语言中的标识符。
名字可以由除了空格和特定保留字符（(、)、[、]、&lt;、&gt;、{、}、/和%）以外的
任意字符组成，例如abc、$def、ghi-jkl都是有效的名字。
名字甚至可以以数字开头，例如 1Z 是有效的名字，但这种习惯有时会遇到问题
（如 1E10 是个实数）。</p>
<p>通常，名字出现时会被当作操作符，PostScript会去“调用”该名字对应的过程。
那么怎样给名字定义“过程”呢？这就需要使用“字面意义的名字”（literal name）
和 def 操作符。在名字前面加上 / 符号，可以告诉PostScript，我们要定义这个名字了，
别把它当作操作符，当作操作数压进栈里就行了。def 操作符则从栈顶弹出两个元素，
并把第二个元素（字面意义的名字）定义为第一个元素（过程）。例如：</p>
<pre>/square { dup mul } def     % 定义 square 为 { dup mul }
3 square                    % 调用 square，相当于 3 dup mul</pre>
<p>这里还要说明一下，所谓“调用”并不是像C语言那样跳转到函数定义的位置去执行。
PostScript中的过程实质上是一系列的操作符和操作数，在“调用”
一个名字时，PostScript简单地用该名字对应的那个过程来替换该名字，
然后依次执行。例如上面的 3 square，PostScript在遇到 square时，
从以前的定义中找到 square 相当于 { dup mul }，于是将 square “展开”
成 dup mul，再依次执行，其效果跟直接写 3 dup mul 是相同的。</p>

<h3 id="content_4_10">注释</h3>
<p>PostScript中使用 % 符号表示注释，% 之后的内容会被忽略。</p>

<h2 id="content_4_11">图形基础概念</h2>
<p>作为页面描述语言，PostScript的主要功能就是绘图和显示文字，那么有几个
图形方面的基础概念是必须要了解的。</p>

<h3 id="content_4_12">用户空间</h3>
<p>用户空间是PostScript用于表达点和线的位置的坐标系。它的原点(0, 0)位于左下角，
x轴向右，y轴向上，相当于数学中的第一象限。</p>
<p>用户空间的默认单位是<strong>点</strong>（point）。一个point相当于1/72英寸，
这个值比真正打印机上的point（等于1/72.27英寸）稍稍短一些。</p>
<p>实际应用中，可以作以下定义，以便在PostScript程序中使用英寸、毫米等比较直观的单位。</p>
<pre>/mm { 2.834646 mul } def       % 毫米
/inch { 72 mul } def           % 英寸
1 inch 20 mm moveto            % 应用例</pre>

<h3 id="content_4_13">路径</h3>
<p>路径是页面上一系列直线和曲线的组合。它并不是可见的线条，只是假想的一条路径而已。
通过 stroke 和 fill 操作符可以描边或填充路径（用过Photoshop就能理解），使之可见。</p>

<h3 id="content_4_14">图形状态</h3>
<p>图形有许多状态（如当前颜色、当前路径、线的粗细、坐标系等）。
程序有时需要临时改变图形状态，此时应该将当前的图形状态保存到<strong>图形状态栈</strong>（graphics state stack）中，
画完之后再恢复状态。保存和恢复可以通过gsave和grestore操作符来实现。</p>
<!-- end Pukiwiki generated code-->
]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2010/07/27/postscript-tutorial-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PostScript入门(1)-基本知识</title>
		<link>http://tech.idv2.com/2010/07/25/postscript-tuturial-1/</link>
		<comments>http://tech.idv2.com/2010/07/25/postscript-tuturial-1/#comments</comments>
		<pubDate>Sun, 25 Jul 2010 01:22:36 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[postscript]]></category>

		<guid isPermaLink="false">http://tech.idv2.com/?p=807</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p>最近由于项目需要，一直在研究PostScript语言。由于这个语言通常用在打印机上，
一般用户接触不到，因此网上的资料也十分罕见。所以，我想把这段时间的心得
整理成一篇入门文章，与大家分享，希望能对想研究打印机的朋友们有所帮助。</p>
<p>这篇文章计划分成七个部分，分别是：</p>
<ol class="list1" style="padding-left:16px;margin-left:16px"><li>基本知识(本篇)</li>
<li><a href="http://tech.idv2.com/2010/07/27/postscript-tutorial-2/">基础概念</a></li>
<li>绘图(未完成)</li>
<li>使用颜色(未完成)</li>
<li>绘制位图(未完成)</li>
<li>文本与字体(未完成)</li></ol>
<!-- end Pukiwiki generated code--><span id="more-807"></span><!-- begin Pukiwiki generated code--><h2 id="content_6_0">什么是PostScript？</h2>
<p>简单地说，PostScript是一种页面描述语言(Page Description Language)。
它由Adobe公司于1985年开发，最初应用在Apple LaserWriter打印机上。
PostScript是设备无关的，也就是说，PostScript文件中不包含任何与设备
相关的信息（如打印机的分辨率），因此PostScript文件可以在任何支持
PostScript的打印机上使用，而无需做任何修改。</p>
<p>看到“页面描述语言”这个词，可能会联想到HTML等网页标记语言。没错，
PostScript的主要作用就是记载需要打印出的各种文字和图形，但它还是
一种简单的编程语言，支持分支、循环等控制结构，以及数组、字典等简单
的数据结构。</p>
<p>例如，下面是个最简单的PostScript文件(square.ps)，它在页面上画一个正方形：</p>
<pre>%!PS-Adobe-3.0
newpath
100 600 moveto
200 600 lineto
200 700 lineto
100 700 lineto
closepath
stroke
showpage</pre>

<h2 id="content_6_1">如何运行PostScript？</h2>
<p>查看PostScript文件需要使用PostScript解释器。最常见的解释器就是
<a href="http://www.ghostscript.com/">GhostScript</a>。Windows版只需下载
gs871w32.exe安装即可。Linux下一般都包含在发行版中，使用相应的
管理程序自动安装即可，例如Ubuntu下可以这样安装：</p>
<pre>$ sudo apt-get install ghostscript</pre>
<p>安装完成后即可从开始菜单中启动GhostScript（Linux下直接使用 gs 命令启动）。
启动后出现提示符：</p>
<pre>GS&gt;</pre>
<p>随后，可以直接在提示符下输入命令，也可以先把命令写成*.ps文件，
再用GhostScript运行。例如上一节给出的square.ps文件，在Windows下
可以直接将它拖到打开的GhostScript窗口中，即可看到生成的图形。</p>
<p>此外，GhostScripth还提供了PostScript格式与其他格式之间的转换命令，
例如ps2pdf、pdf2ps等。Linux下这些命令一般位于/usr/bin，Windows下则位于
安装目录的 lib 下（建议把安装目录下的bin和lib两个目录加到PATH环境变量中）。</p>
<!-- end Pukiwiki generated code-->
]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p>最近由于项目需要，一直在研究PostScript语言。由于这个语言通常用在打印机上，
一般用户接触不到，因此网上的资料也十分罕见。所以，我想把这段时间的心得
整理成一篇入门文章，与大家分享，希望能对想研究打印机的朋友们有所帮助。</p>
<p>这篇文章计划分成七个部分，分别是：</p>
<ol class="list1" style="padding-left:16px;margin-left:16px"><li>基本知识(本篇)</li>
<li><a href="http://tech.idv2.com/2010/07/27/postscript-tutorial-2/">基础概念</a></li>
<li>绘图(未完成)</li>
<li>使用颜色(未完成)</li>
<li>绘制位图(未完成)</li>
<li>文本与字体(未完成)</li></ol>
<!-- end Pukiwiki generated code--><span id="more-807"></span><!-- begin Pukiwiki generated code--><h2 id="content_8_0">什么是PostScript？</h2>
<p>简单地说，PostScript是一种页面描述语言(Page Description Language)。
它由Adobe公司于1985年开发，最初应用在Apple LaserWriter打印机上。
PostScript是设备无关的，也就是说，PostScript文件中不包含任何与设备
相关的信息（如打印机的分辨率），因此PostScript文件可以在任何支持
PostScript的打印机上使用，而无需做任何修改。</p>
<p>看到“页面描述语言”这个词，可能会联想到HTML等网页标记语言。没错，
PostScript的主要作用就是记载需要打印出的各种文字和图形，但它还是
一种简单的编程语言，支持分支、循环等控制结构，以及数组、字典等简单
的数据结构。</p>
<p>例如，下面是个最简单的PostScript文件(square.ps)，它在页面上画一个正方形：</p>
<pre>%!PS-Adobe-3.0
newpath
100 600 moveto
200 600 lineto
200 700 lineto
100 700 lineto
closepath
stroke
showpage</pre>

<h2 id="content_8_1">如何运行PostScript？</h2>
<p>查看PostScript文件需要使用PostScript解释器。最常见的解释器就是
<a href="http://www.ghostscript.com/">GhostScript</a>。Windows版只需下载
gs871w32.exe安装即可。Linux下一般都包含在发行版中，使用相应的
管理程序自动安装即可，例如Ubuntu下可以这样安装：</p>
<pre>$ sudo apt-get install ghostscript</pre>
<p>安装完成后即可从开始菜单中启动GhostScript（Linux下直接使用 gs 命令启动）。
启动后出现提示符：</p>
<pre>GS&gt;</pre>
<p>随后，可以直接在提示符下输入命令，也可以先把命令写成*.ps文件，
再用GhostScript运行。例如上一节给出的square.ps文件，在Windows下
可以直接将它拖到打开的GhostScript窗口中，即可看到生成的图形。</p>
<p>此外，GhostScripth还提供了PostScript格式与其他格式之间的转换命令，
例如ps2pdf、pdf2ps等。Linux下这些命令一般位于/usr/bin，Windows下则位于
安装目录的 lib 下（建议把安装目录下的bin和lib两个目录加到PATH环境变量中）。</p>
<!-- end Pukiwiki generated code-->
]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2010/07/25/postscript-tuturial-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UML中的联系、聚合与组合的区别</title>
		<link>http://tech.idv2.com/2009/04/12/uml-aac-diff/</link>
		<comments>http://tech.idv2.com/2009/04/12/uml-aac-diff/#comments</comments>
		<pubDate>Sun, 12 Apr 2009 14:13:04 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[uml]]></category>

		<guid isPermaLink="false">http://tech.idv2.com/2009/04/12/uml-aac-diff/</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p>UML中的联系(association)、聚合(aggregation)和组合(composition)三个概念很相似，也很难理解。
今天看到<a href="http://ootips.org/uml-hasa.html">这篇文章</a>解释得很清楚，所以在这里转一下，
希望能对需要的人有所帮助。</p>
<p><strong>联系</strong></p>
<p>联系(association)表明某个对象可以向另一个对象通过某种方式发送消息。发送消息的方法可以通过指针成员变量，
也可以是方法参数、局部变量等等。例如：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2009/04/uml-aac-diff-01.png" alt="uml-aac-diff-01.png" title="uml-aac-diff-01.png" width="220" height="70" /></div>

<pre>class A
{
  private:
    B* itsB;
};</pre>
<p><strong>聚合</strong></p>
<p>聚合(aggregation)是一种特殊的联系，它表明了“部分”到“整体”的关系，显著的特点就是不能包含循环的联系
（就是说，部分中不能包含整体）。如：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2009/04/uml-aac-diff-02.png" alt="uml-aac-diff-02.png" title="uml-aac-diff-02.png" width="231" height="62" /></div>

<pre>class Node
{
  private:
    vector&lt;Node*&gt; itsNodes;
};</pre>
<p>上述代码只有当子节点不会成为父节点的父节点时（即，必须是树结构，不能是图结构），才能称之为聚合。</p>
<p><strong>组合</strong></p>
<p>组合(composition)跟聚合几乎相同，唯一的区别就是“部分”不能脱离“整体”单独存在，就是说，
“部分”的生命期不能比“整体”还要长。例如：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2009/04/uml-aac-diff-03.png" alt="uml-aac-diff-03.png" title="uml-aac-diff-03.png" width="250" height="67" /></div>

<pre>class Car
{
  public:
    virtual ~Car() {delete itsCarb;}
  private:
    Carburetor* itsCarb
};</pre>
<!-- end Pukiwiki generated code-->]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p>UML中的联系(association)、聚合(aggregation)和组合(composition)三个概念很相似，也很难理解。
今天看到<a href="http://ootips.org/uml-hasa.html">这篇文章</a>解释得很清楚，所以在这里转一下，
希望能对需要的人有所帮助。</p>
<p><strong>联系</strong></p>
<p>联系(association)表明某个对象可以向另一个对象通过某种方式发送消息。发送消息的方法可以通过指针成员变量，
也可以是方法参数、局部变量等等。例如：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2009/04/uml-aac-diff-01.png" alt="uml-aac-diff-01.png" title="uml-aac-diff-01.png" width="220" height="70" /></div>

<pre>class A
{
  private:
    B* itsB;
};</pre>
<p><strong>聚合</strong></p>
<p>聚合(aggregation)是一种特殊的联系，它表明了“部分”到“整体”的关系，显著的特点就是不能包含循环的联系
（就是说，部分中不能包含整体）。如：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2009/04/uml-aac-diff-02.png" alt="uml-aac-diff-02.png" title="uml-aac-diff-02.png" width="231" height="62" /></div>

<pre>class Node
{
  private:
    vector&lt;Node*&gt; itsNodes;
};</pre>
<p>上述代码只有当子节点不会成为父节点的父节点时（即，必须是树结构，不能是图结构），才能称之为聚合。</p>
<p><strong>组合</strong></p>
<p>组合(composition)跟聚合几乎相同，唯一的区别就是“部分”不能脱离“整体”单独存在，就是说，
“部分”的生命期不能比“整体”还要长。例如：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2009/04/uml-aac-diff-03.png" alt="uml-aac-diff-03.png" title="uml-aac-diff-03.png" width="250" height="67" /></div>

<pre>class Car
{
  public:
    virtual ~Car() {delete itsCarb;}
  private:
    Carburetor* itsCarb
};</pre>
<!-- end Pukiwiki generated code-->]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2009/04/12/uml-aac-diff/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[Python]Python学习笔记</title>
		<link>http://tech.idv2.com/2008/11/03/python-memo/</link>
		<comments>http://tech.idv2.com/2008/11/03/python-memo/#comments</comments>
		<pubDate>Mon, 03 Nov 2008 07:54:16 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://tech.idv2.com/2008/11/03/python-memo/</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p>Ver 2: 2008/11/7 <br />
Ver 1: 2008/11/3 <br /></p>
<h2 id="content_11_0">基本概念</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>Python居然支持复数。如(-5+4j)。但要注意虚数单位单独使用时要写成 1j，不能写成 j。</li>
<li>与Perl和PHP的区别：单引号和双引号没有任何区别。没有插值功能。</li>
<li>三引号：''' 和 &quot;&quot;&quot; 相当于Perl的heredoc。</li>
<li>行尾不需要用分号，分号仅用于一行写多条语句的情况。跟BASIC的冒号有些相似。</li>
<li>缩进是有语义的！建议使用TAB缩进</li>
<li>逻辑运算符只有 and or not，没有 &amp;&amp; || !</li>
<li>没有自增自减运算符，--a 相当于 -(-a)，a--语法错</li>
<li>赋值语句不是表达式，如 y = (x = 1) 语法错</li>
<li>字符串切片是很好用的: 'Hello'[0] == 'H'，以前只有Basic才有这个功能，其他语言都没有。当然Python比Basic要强大得多</li>
<li>cmp函数相当于Perl的 &lt;=&gt; 和 cmp，由于python有类型，所以无需像perl那样用两个运算符</li>
<li>[]、()、{} 的布尔值是False，跟JavaScript不同（JavaScript中空数组和空对象都是true）。与Perl类似，但Perl可以用环境来解释。</li></ul>

<h2 id="content_11_1">运算符与表达式</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>运算符 ** 乘幂，Perl也有。</li>
<li>字符串的 * 表示重复，相当于Perl的 x 运算符。</li>
<li>居然还有专用于整除的 // 。别跟Perl 6的 // 混淆了。</li></ul>

<h2 id="content_11_2">控制流</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>if-elif-else，Perl为if-elsif-else，bash为if-elif-fi</li>
<li>if、elif等控制流语句后面要加冒号，很像PHP的语法</li>
<li>while和for循环可以带else，循环正常结束时就会执行else。不用像C语言那样，循环结束时要检查循环变量是否等于终值，以判断是否正常结束。赞</li>
<li>range函数生成的结果不包括终点。比较：Perl的 .. 运算符包括终点。所以，Python的range(a,b)理解成C语言的 for(i=a;i&lt;b,i++) 好些。</li>
<li>什么都不做的pass语句，算是个python特色</li>
<li>enumerate能同时迭代key和value，很不错。for key, value in enumerate(LIST):</li></ul>

<h2 id="content_11_3">函数</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>函数中使用全局变量需要用global关键字，类似于PHP</li>
<li>DocString，又一个python特色，函数的第一个逻辑航的字符串作为文档字符串。类似于POD和javadoc，不过是写在函数体内的。还能通过&quot;函数名.__doc__&quot;访问</li>
<li>lambda：类似于perl的闭包</li>
<li>int()函数在字符串转整数时，不能用来转浮点数字符串，也不能转包含字母的字符串。如int(&quot;1.2&quot;)、int(&quot;123abc&quot;)都是语法错误，而并不返回 1、123。</li></ul>

<h2 id="content_11_4">数据结构</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>列表：定义方式为 a=[1,2]。等价于perl的数组/列表</li>
<li>元组(tuple)：定义方式为 a=(1,2)。</li>
<li>要注意列表中的列表不会被打散，如 a=[1,2], b=[a,3,4]，结果就是 b=[[1,2],3,4]。这一点与Perl不同。</li>
<li>字典：定义方式为 c={'a':1, 'b':2}。等价于perl的散列。注意两点：
<ul class="list2" style="padding-left:16px;margin-left:16px"><li>定义和访问时，key必须用引号引起来。</li>
<li>使用{}定义，使用[]访问，即c['a']。与Perl不同。</li></ul></li>
<li>列表赋值是引用赋值。要想拷贝，必须用切片：b = a[:]。Perl程序员要注意。</li>
<li>列表的sort会改变原列表。</li></ul>

<h2 id="content_11_5">例外</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>try-except-finally，相当于java的try-catch-finally</li>
<li>还有else，当没有发生异常、正常结束try块时执行。跟for/while的else块一样</li>
<li>故意抛出异常叫raise，java里面叫throw</li></ul>

<h2 id="content_11_6">面向对象</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>数字和字符串（对象）是不可变的。那么如何理解a=a+1？实际上是a+1创建了一个新对象赋给a，而a原来的对象被回收了。学习Python必须改变原来的“变量是个盒子”的看法</li>
<li>(-1, 100)之间的<strong>整数</strong>会被缓存，就是说即使写成 a=10; b=10; ，a和b还是同一个对象(a is b == True)</li>
<li>python的长整型是无限大的</li>
<li>类的__init__函数类似于C++的构造函数；__del__函数类似于C++的析构函数。</li>
<li>类方法定义的第一个参数必须为self，调用时这个参数会被传递为对象本身。类似于perl，perl中第一个参数也会被传递为对象本身，不过需要程序员自己写 my $self = shift; 来接收。</li>
<li>用C++的话来说，所有成员函数都是虚函数。</li>
<li>调用基类方法时要手工传递self，如 Parnet.__init__(self, name)。</li></ul>

<h2 id="content_11_7">模块</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>import foo; 相当于perl的 use foo;</li>
<li>from foo import bar 相当于perl的 use foo qw/bar/;</li></ul>
<!-- end Pukiwiki generated code-->
]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p>Ver 2: 2008/11/7 <br />
Ver 1: 2008/11/3 <br /></p>
<h2 id="content_12_0">基本概念</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>Python居然支持复数。如(-5+4j)。但要注意虚数单位单独使用时要写成 1j，不能写成 j。</li>
<li>与Perl和PHP的区别：单引号和双引号没有任何区别。没有插值功能。</li>
<li>三引号：''' 和 &quot;&quot;&quot; 相当于Perl的heredoc。</li>
<li>行尾不需要用分号，分号仅用于一行写多条语句的情况。跟BASIC的冒号有些相似。</li>
<li>缩进是有语义的！建议使用TAB缩进</li>
<li>逻辑运算符只有 and or not，没有 &amp;&amp; || !</li>
<li>没有自增自减运算符，--a 相当于 -(-a)，a--语法错</li>
<li>赋值语句不是表达式，如 y = (x = 1) 语法错</li>
<li>字符串切片是很好用的: 'Hello'[0] == 'H'，以前只有Basic才有这个功能，其他语言都没有。当然Python比Basic要强大得多</li>
<li>cmp函数相当于Perl的 &lt;=&gt; 和 cmp，由于python有类型，所以无需像perl那样用两个运算符</li>
<li>[]、()、{} 的布尔值是False，跟JavaScript不同（JavaScript中空数组和空对象都是true）。与Perl类似，但Perl可以用环境来解释。</li></ul>

<h2 id="content_12_1">运算符与表达式</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>运算符 ** 乘幂，Perl也有。</li>
<li>字符串的 * 表示重复，相当于Perl的 x 运算符。</li>
<li>居然还有专用于整除的 // 。别跟Perl 6的 // 混淆了。</li></ul>

<h2 id="content_12_2">控制流</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>if-elif-else，Perl为if-elsif-else，bash为if-elif-fi</li>
<li>if、elif等控制流语句后面要加冒号，很像PHP的语法</li>
<li>while和for循环可以带else，循环正常结束时就会执行else。不用像C语言那样，循环结束时要检查循环变量是否等于终值，以判断是否正常结束。赞</li>
<li>range函数生成的结果不包括终点。比较：Perl的 .. 运算符包括终点。所以，Python的range(a,b)理解成C语言的 for(i=a;i&lt;b,i++) 好些。</li>
<li>什么都不做的pass语句，算是个python特色</li>
<li>enumerate能同时迭代key和value，很不错。for key, value in enumerate(LIST):</li></ul>

<h2 id="content_12_3">函数</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>函数中使用全局变量需要用global关键字，类似于PHP</li>
<li>DocString，又一个python特色，函数的第一个逻辑航的字符串作为文档字符串。类似于POD和javadoc，不过是写在函数体内的。还能通过&quot;函数名.__doc__&quot;访问</li>
<li>lambda：类似于perl的闭包</li>
<li>int()函数在字符串转整数时，不能用来转浮点数字符串，也不能转包含字母的字符串。如int(&quot;1.2&quot;)、int(&quot;123abc&quot;)都是语法错误，而并不返回 1、123。</li></ul>

<h2 id="content_12_4">数据结构</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>列表：定义方式为 a=[1,2]。等价于perl的数组/列表</li>
<li>元组(tuple)：定义方式为 a=(1,2)。</li>
<li>要注意列表中的列表不会被打散，如 a=[1,2], b=[a,3,4]，结果就是 b=[[1,2],3,4]。这一点与Perl不同。</li>
<li>字典：定义方式为 c={'a':1, 'b':2}。等价于perl的散列。注意两点：
<ul class="list2" style="padding-left:16px;margin-left:16px"><li>定义和访问时，key必须用引号引起来。</li>
<li>使用{}定义，使用[]访问，即c['a']。与Perl不同。</li></ul></li>
<li>列表赋值是引用赋值。要想拷贝，必须用切片：b = a[:]。Perl程序员要注意。</li>
<li>列表的sort会改变原列表。</li></ul>

<h2 id="content_12_5">例外</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>try-except-finally，相当于java的try-catch-finally</li>
<li>还有else，当没有发生异常、正常结束try块时执行。跟for/while的else块一样</li>
<li>故意抛出异常叫raise，java里面叫throw</li></ul>

<h2 id="content_12_6">面向对象</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>数字和字符串（对象）是不可变的。那么如何理解a=a+1？实际上是a+1创建了一个新对象赋给a，而a原来的对象被回收了。学习Python必须改变原来的“变量是个盒子”的看法</li>
<li>(-1, 100)之间的<strong>整数</strong>会被缓存，就是说即使写成 a=10; b=10; ，a和b还是同一个对象(a is b == True)</li>
<li>python的长整型是无限大的</li>
<li>类的__init__函数类似于C++的构造函数；__del__函数类似于C++的析构函数。</li>
<li>类方法定义的第一个参数必须为self，调用时这个参数会被传递为对象本身。类似于perl，perl中第一个参数也会被传递为对象本身，不过需要程序员自己写 my $self = shift; 来接收。</li>
<li>用C++的话来说，所有成员函数都是虚函数。</li>
<li>调用基类方法时要手工传递self，如 Parnet.__init__(self, name)。</li></ul>

<h2 id="content_12_7">模块</h2>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>import foo; 相当于perl的 use foo;</li>
<li>from foo import bar 相当于perl的 use foo qw/bar/;</li></ul>
<!-- end Pukiwiki generated code-->
]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2008/11/03/python-memo/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Servlet/JSP学习笔记(8)-Filter的应用</title>
		<link>http://tech.idv2.com/2007/09/29/servlet-filter/</link>
		<comments>http://tech.idv2.com/2007/09/29/servlet-filter/#comments</comments>
		<pubDate>Sat, 29 Sep 2007 09:11:48 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jsp]]></category>
		<category><![CDATA[lomboz]]></category>
		<category><![CDATA[servlet]]></category>

		<guid isPermaLink="false">http://tech.idv2.com/2007/09/29/servlet-filter/</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p>Servlet有一个很有意思也很有用的功能，就是Filter。
所谓Filter，就是在用户请求到达 Servlet 之前、或者 Servlet 执行之后，
执行的一段小程序，这段程序可以对用户请求做预处理，
或者对Servlet返回的结果进行一些公用处理。</p>
<p>Filter可以在请求到达 Servlet 之前执行，
甚至即使请求一个静态页面或图片等，Filter也会被优先执行。
这样我们可以通过Filter对应用程序内的所有对象（包括Java程序和静态内容）进行预处理。
（这个功能恐怕PHP程序就无法做到了。）</p>
<!-- end Pukiwiki generated code--><span id="more-511"></span><!-- begin Pukiwiki generated code--><p>Filter通常可用于以下几种情况：</p>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>认证</li>
<li>记录访问日志</li>
<li>加密解密</li>
<li>字符编码转换</li>
<li>数据压缩</li></ul>
<p>如上面最常用的“认证”，可以在Filter中书写认证代码，
这样不仅省却了在Servlet中认证的麻烦，而且还能控制网站中静态内容的访问。</p>
<p>Filter是个接口，位于 javax.servlet.Filter。它与其他接口的关系如下：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/filter-diagram.png" alt="filter-diagram.png" title="filter-diagram.png" width="434" height="176" /></div>

<p>我们在书写自己的Filter时，只需写一个类实现 Filter 接口即可。</p>
<p>实现Filter接口需要实现以下几个方法：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void init(FilterConfig filterConfig) throws ServletException</dt>


<dd>Filter的初始化方法。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void destroy()</dt>


<dd>Filter结束之前执行的方法。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException</dt>


<dd>Filter的执行内容。参数request和response分别为输入和输出参数，而chain则为Filter链对象。</dd></dl>
<p>所谓FilterChain，一个应用程序内的Filter可以有多个，它们像链子一样串在一起，
其中的某个Filter执行之后，可以调用chain.doFilter(request, response)将执行权转给下一个Filter，
直到所有的Filter都执行完毕。</p>
<p>这次的示例程序我们修改了<a href="http://tech.idv2.com/2007/09/25/session-and-scope/">上一节</a>的登录程序，
为它增加了一个下载链接(详见SessionTest.java)。
这个下载链接指向 img/sample.jpg。
我们希望能通过一个Filter，在用户试图下载 img/sample.jpg 时验证用户身份，
如果验证失败，则禁止用户下载，并跳转到登录页面。</p>
<p>创建Filter时可惜不能像Servlet那样，直接从右键菜单中选择新建，
而只能先写好源代码然后手工添加到web.xml中。
如下图，在新建类时注意要实现javax.servlet.Filter接口。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/filter-01.png" alt="filter-01.png" title="filter-01.png" width="490" height="490" /></div>

<p>写完代码之后，打开web.xml文件，手工添加Filter。与Servlet类似，你需要添加 &lt;filter&gt; 和</p>
<blockquote><p class="quotation">filter-mapping&gt;两个标记。这里我们要对 /img/ 下的所有文件进行登录验证，
因此&lt;filter-mapping&gt;的 url-pattern 处我们填写了 /img/* 。</p></blockquote>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/filter-02.png" alt="filter-02.png" title="filter-02.png" width="466" height="123" /></div>

<p>最后执行，访问 /LearnJSP/img/sample.jpg ，就会跳转到登录页面。
登录之后再次访问上面的链接，才能看到正确的图片。</p>
<div class="img_margin" style="text-align:left"><a href="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-filter.zip" title="servlet-filter.zip(2007/09/27 12:01:20 9.0KB)"><img src="http://tech.idv2.com/wp-content/plugins/wp-pukiwiki/img/attach.gif" width="16" height="16" alt="attach" style="border-width:0px" />servlet-filter.zip</a></div>

<!-- end Pukiwiki generated code-->
]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p>Servlet有一个很有意思也很有用的功能，就是Filter。
所谓Filter，就是在用户请求到达 Servlet 之前、或者 Servlet 执行之后，
执行的一段小程序，这段程序可以对用户请求做预处理，
或者对Servlet返回的结果进行一些公用处理。</p>
<p>Filter可以在请求到达 Servlet 之前执行，
甚至即使请求一个静态页面或图片等，Filter也会被优先执行。
这样我们可以通过Filter对应用程序内的所有对象（包括Java程序和静态内容）进行预处理。
（这个功能恐怕PHP程序就无法做到了。）</p>
<!-- end Pukiwiki generated code--><span id="more-511"></span><!-- begin Pukiwiki generated code--><p>Filter通常可用于以下几种情况：</p>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li>认证</li>
<li>记录访问日志</li>
<li>加密解密</li>
<li>字符编码转换</li>
<li>数据压缩</li></ul>
<p>如上面最常用的“认证”，可以在Filter中书写认证代码，
这样不仅省却了在Servlet中认证的麻烦，而且还能控制网站中静态内容的访问。</p>
<p>Filter是个接口，位于 javax.servlet.Filter。它与其他接口的关系如下：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/filter-diagram.png" alt="filter-diagram.png" title="filter-diagram.png" width="434" height="176" /></div>

<p>我们在书写自己的Filter时，只需写一个类实现 Filter 接口即可。</p>
<p>实现Filter接口需要实现以下几个方法：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void init(FilterConfig filterConfig) throws ServletException</dt>


<dd>Filter的初始化方法。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void destroy()</dt>


<dd>Filter结束之前执行的方法。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException</dt>


<dd>Filter的执行内容。参数request和response分别为输入和输出参数，而chain则为Filter链对象。</dd></dl>
<p>所谓FilterChain，一个应用程序内的Filter可以有多个，它们像链子一样串在一起，
其中的某个Filter执行之后，可以调用chain.doFilter(request, response)将执行权转给下一个Filter，
直到所有的Filter都执行完毕。</p>
<p>这次的示例程序我们修改了<a href="http://tech.idv2.com/2007/09/25/session-and-scope/">上一节</a>的登录程序，
为它增加了一个下载链接(详见SessionTest.java)。
这个下载链接指向 img/sample.jpg。
我们希望能通过一个Filter，在用户试图下载 img/sample.jpg 时验证用户身份，
如果验证失败，则禁止用户下载，并跳转到登录页面。</p>
<p>创建Filter时可惜不能像Servlet那样，直接从右键菜单中选择新建，
而只能先写好源代码然后手工添加到web.xml中。
如下图，在新建类时注意要实现javax.servlet.Filter接口。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/filter-01.png" alt="filter-01.png" title="filter-01.png" width="490" height="490" /></div>

<p>写完代码之后，打开web.xml文件，手工添加Filter。与Servlet类似，你需要添加 &lt;filter&gt; 和</p>
<blockquote><p class="quotation">filter-mapping&gt;两个标记。这里我们要对 /img/ 下的所有文件进行登录验证，
因此&lt;filter-mapping&gt;的 url-pattern 处我们填写了 /img/* 。</p></blockquote>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/filter-02.png" alt="filter-02.png" title="filter-02.png" width="466" height="123" /></div>

<p>最后执行，访问 /LearnJSP/img/sample.jpg ，就会跳转到登录页面。
登录之后再次访问上面的链接，才能看到正确的图片。</p>
<div class="img_margin" style="text-align:left"><a href="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-filter.zip" title="servlet-filter.zip(2007/09/27 12:01:20 9.0KB)"><img src="http://tech.idv2.com/wp-content/plugins/wp-pukiwiki/img/attach.gif" width="16" height="16" alt="attach" style="border-width:0px" />servlet-filter.zip</a></div>

<!-- end Pukiwiki generated code-->
]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2007/09/29/servlet-filter/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Servlet/JSP学习笔记(7)-Session和作用域</title>
		<link>http://tech.idv2.com/2007/09/25/session-and-scope/</link>
		<comments>http://tech.idv2.com/2007/09/25/session-and-scope/#comments</comments>
		<pubDate>Tue, 25 Sep 2007 02:04:12 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jsp]]></category>
		<category><![CDATA[servlet]]></category>

		<guid isPermaLink="false">http://tech.idv2.com/2007/09/25/session-and-scope/</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p>几乎所有的Web开发语言都支持Session功能，Servlet也不例外。
Servlet/JSP中的Session功能是通过<strong>作用域</strong>(<strong>scope</strong>)这个概念来实现的。</p>
<p>作用域分为四种，分别为：</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">page</td><td class="style_td">在当前页面有效(仅用于JSP中)</td></tr><tr><td class="style_td">request</td><td class="style_td">在当前请求中有效</td></tr><tr><td class="style_td">session</td><td class="style_td">在当前会话中有效</td></tr><tr><td class="style_td">application</td><td class="style_td">在所有应用程序中有效</td></tr></tbody></table></div>
<!-- end Pukiwiki generated code--><span id="more-509"></span><!-- begin Pukiwiki generated code--><p>是不是看不太明白？page因为仅用于JSP中，这里只讲述其他三种作用域。
首先要声明的一点，所谓“作用域”就是“<strong>信息共享的范围</strong>”，
也就是说一个信息能够在多大的范围内有效。</p>
<p>话说武松一日来到景阳岗，见一旗帜迎风飘扬，旗子上书五个大字“三碗不过岗”。
武松叫道：“店家，拿三碗酒来，再切两斤熟牛肉！”店小二应声道：“三碗好酒，
二斤熟牛肉啰～～”里面厨师赶忙当当当当切好牛肉，店小二倒上三碗酒，店小二端上前来。</p>
<p>武松咕咚咕咚连干三碗，叫一声“好酒！店家，再来三碗！”小二忙又倒上三碗好酒，
武松一饮而尽。就这样前前后后武松一共喝了十八大腕。付了帐刚要走，店小二道：
“客官，这前面山上有大虫，客官刚刚喝完十八碗酒恐怕过不得岗，不如在小店暂住一夜，
待明天和猎户一同过岗岂不是好？”</p>
<p>之后武松说什么就留待各位看官自己去回忆啦。在这段武松打虎中，
大家有没有看到些熟悉的东西？</p>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li><strong>武松</strong>: 浏览器。</li>
<li><strong>酒馆</strong>: 服务器。</li>
<li><strong>店小二、厨师</strong>: Servlet或者JSP。</li>
<li><strong>来三碗好酒！</strong>: 浏览器向服务器发出HTTP请求。</li>
<li><strong>店小二上酒</strong>: 服务器的响应。</li>
<li><strong>武松从进店到离开</strong>: 一个HTTP对话。</li></ul>
<p>我们可以看到，Web交互的最基本单位为<strong>HTTP请求</strong>(<em>武松点菜</em>)。
每个用户从进入网站到离开网站这段过程称为一个<strong>HTTP会话</strong>
(<em>武松进店到出店</em>)，一个服务器的运行过程中会有多个用户访问，
就是多个HTTP会话(<em>酒馆当然不可能只接待武松一个客人</em>)。
那么作用域就可以理解为：</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">request</td><td class="style_td">HTTP请求开始到结束这段时间</td></tr><tr><td class="style_td">session</td><td class="style_td">HTTP会话开始到结束这段时间</td></tr><tr><td class="style_td">application</td><td class="style_td">服务器启动到停止这段时间</td></tr></tbody></table></div>
<p><strong>request</strong></p>
<p>一个HTTP请求的处理可能需要多个Servlet合作(<em>武松点菜时店小二就要吩咐厨房做菜</em>)，
几个Servlet之间可以通过某种方式传递信息(<em>店小二就用吆喝的方式通知厨房</em>)，
但这个信息在请求结束后就无效了(<em>厨房在做完菜之后就不用再管这道菜的事儿了</em>)。</p>
<p>Servlet之间的信息共享是通过HttpServletRequest接口的两个方法来实现的：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void setAttribute(String name, Object value)</dt>


<dd>将对象 value 以 name 为名称保存到request作用域中。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>Object getAttribute(String name)</dt>


<dd>从request作用域中取得指定名字的信息。</dd></dl>
<p>doGet()、doPost()函数的第一个参数就是 HttpServletRequest 对象，
使用这个对象的 setAttribute 即可传递信息。</p>
<p>那么设置好信息之后，如何将信息传给其他Servlet？
这就要用到 RequestDispatcher 接口的 forward 方法，将请求转发给其他Servlet。</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>RequestDispatcher ServletContext.getRequestDispatcher(String path)</dt>


<dd>取得Dispatcher以便转发。path为转发的目的Servlet。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void RequestDispatcher.forward(ServletRequest request, ServletResponse response)</dt>


<dd>将request和response转发。</dd></dl>
<p>因此，只要在当前Servlet中先 setAttribute，然后forward，最后在forward到的Servlet中
getAttribute即可实现信息传递。</p>
<p>PHP的程序员可能不太好理解这一段，因为PHP中没有转发的概念，
一个请求只能由一个PHP文件来处理，所以PHP中根本没有request作用域的概念。
而Servlet则不同，请求可以在应用程序中任意转发，所以用request作用域在不同Servlet之间传递信息。
需要注意两点：</p>
<ol class="list1" style="padding-left:16px;margin-left:16px"><li><strong>转发不是重定向</strong>，转发是在Web应用内部进行的。PHP支持重定向但没有转发。</li>
<li><strong>转发对浏览器是透明的</strong>，也就是说，无论在服务器上如何转发，浏览器地址栏中显示的仍然是最初那个Servlet的地址。</li></ol>
<p><strong>session</strong></p>
<p>session作用域比较容易理解，同一浏览器访问多次，在这多次访问之间传递信息，就是session作用域。
('''武松每次点菜帐房先生都要记一笔账，等武松走之前结帐用。
这笔帐在武松吃饭过程中始终有效，即位于session作用域中''')</p>
<p>session是通过HttpSession接口实现的。</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>Object HttpSession.getAttribute(String name)</dt>


<dd>从session中获取信息</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void HttpSession.setAttribute(String name, Object value)</dt>


<dd>向session中保存信息</dd></dl>
<p>而通过HttpServletRequest.getSession()方法可以获得HttpSession对象。</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>HttpSession HttpServletRequest.getSessio()</dt>


<dd>获取当前请求所在的session的对象。</dd></dl>
<p>session的开始容易判断(浏览器发出第一个HTTP请求即可认为会话开始)，
但结束就不好判断了(因为浏览器关闭时不会通知服务器“我关了，会话可以结束了”)，
所以只能通过这种方法判断：如果一定的时间内客户端没有反应，则认为会话结束。
Tomcat的默认值为120分钟，但这个值也可以通过 HttpSession 的 setMaxInactiveInterval 方法来设置。</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void setMaxInactiveInterval(int interval)</dt>


<dd>设置绘画的超时值。</dd></dl>
<p>如果想主动让会话结束，如用户单击“注销”的时候，可以使用 HttpSession 的 invalidate 方法：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>vooid invalidate()</dt>


<dd>强制结束当前session。</dd></dl>
<p><strong>application</strong></p>
<p>application作用域就是服务器启动到关闭的整段时间，
在这个作用域内设置的信息可以被所有应用程序使用。
(<em>餐馆打烊后结帐，用到的即是开张到打烊之间的所有信息。</em>)</p>
<p>还记得<a href="http://tech.idv2.com/2007/09/20/get-init-params/">上一节</a>提到的ServetContext吗？
application作用域上的信息传递就是通过ServetContext实现的。</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>Object getAttribute(String name)</dt>


<dd>从application中获取信息。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void setAttribute(String name, Object value)</dt>


<dd>向application作用域中设置信息。</dd></dl>
<p><strong>总结</strong></p>
<p>可以看到，每个作用域除了实现接口不同、意义不同之外，它们的使用方法和作用都是相同的，
都是通过 getAttribute 和 setAttribute 方法进行信息传递。</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">作用域</td><td class="style_td">意义</td><td class="style_td">实现接口</td></tr><tr><td class="style_td">request</td><td class="style_td">HTTP请求内</td><td class="style_td">HttpServletRequest</td></tr><tr><td class="style_td">session</td><td class="style_td">HTTP会话内</td><td class="style_td">HttpSession</td></tr><tr><td class="style_td">application</td><td class="style_td">服务器生命周期内</td><td class="style_td">ServletContext</td></tr></tbody></table></div>
<p><strong>示例程序</strong></p>
<p>这一节的示例程序是一个用户登录的模拟程序。文件较多。</p>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li><strong>login.html</strong> 登录表单</li>
<li><strong>DoLogin.java</strong> 处理登录动作的Servlet</li>
<li><strong>LoginSuccess.java</strong> 用于显示登录成功信息的Servlet</li>
<li><strong>SessionTest.java</strong> 登录后的处理程序</li>
<li><strong>DoLogout.java</strong> 注销的处理程序</li></ul>
<p>为了演示 request、application、session 各个作用域的使用方法，
Servlet之间进行了数据传递，数据传递方式如下：</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">数据产生</td><td class="style_td">数据接受</td><td class="style_td">数据内容</td><td class="style_td">作用域</td></tr><tr><td class="style_td">DoLogin</td><td class="style_td">LoginSuccess</td><td class="style_td">登录时间</td><td class="style_td">request</td></tr><tr><td class="style_td">DoLogin</td><td class="style_td">SessionTest</td><td class="style_td">登录用户名</td><td class="style_td">session</td></tr><tr><td class="style_td">DoLogin</td><td class="style_td">SessionTest</td><td class="style_td">系统登录次数</td><td class="style_td">application</td></tr></tbody></table></div>
<p>访问 <a href="http://localhost:8080/LearnJSP/sessiontest">http://localhost:8080/LearnJSP/sessiontest</a>，
登录时输入用户名 charlee 和密码 123456 即可。</p>
<div class="img_margin" style="text-align:left"><a href="http://tech.idv2.com/wp-content/uploads/2007/09/session-test.zip" title="session-test.zip(2007/09/25 15:12:54 5.8KB)"><img src="http://tech.idv2.com/wp-content/plugins/wp-pukiwiki/img/attach.gif" width="16" height="16" alt="attach" style="border-width:0px" />session-test.zip</a></div>

<!-- end Pukiwiki generated code-->

]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p>几乎所有的Web开发语言都支持Session功能，Servlet也不例外。
Servlet/JSP中的Session功能是通过<strong>作用域</strong>(<strong>scope</strong>)这个概念来实现的。</p>
<p>作用域分为四种，分别为：</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">page</td><td class="style_td">在当前页面有效(仅用于JSP中)</td></tr><tr><td class="style_td">request</td><td class="style_td">在当前请求中有效</td></tr><tr><td class="style_td">session</td><td class="style_td">在当前会话中有效</td></tr><tr><td class="style_td">application</td><td class="style_td">在所有应用程序中有效</td></tr></tbody></table></div>
<!-- end Pukiwiki generated code--><span id="more-509"></span><!-- begin Pukiwiki generated code--><p>是不是看不太明白？page因为仅用于JSP中，这里只讲述其他三种作用域。
首先要声明的一点，所谓“作用域”就是“<strong>信息共享的范围</strong>”，
也就是说一个信息能够在多大的范围内有效。</p>
<p>话说武松一日来到景阳岗，见一旗帜迎风飘扬，旗子上书五个大字“三碗不过岗”。
武松叫道：“店家，拿三碗酒来，再切两斤熟牛肉！”店小二应声道：“三碗好酒，
二斤熟牛肉啰～～”里面厨师赶忙当当当当切好牛肉，店小二倒上三碗酒，店小二端上前来。</p>
<p>武松咕咚咕咚连干三碗，叫一声“好酒！店家，再来三碗！”小二忙又倒上三碗好酒，
武松一饮而尽。就这样前前后后武松一共喝了十八大腕。付了帐刚要走，店小二道：
“客官，这前面山上有大虫，客官刚刚喝完十八碗酒恐怕过不得岗，不如在小店暂住一夜，
待明天和猎户一同过岗岂不是好？”</p>
<p>之后武松说什么就留待各位看官自己去回忆啦。在这段武松打虎中，
大家有没有看到些熟悉的东西？</p>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li><strong>武松</strong>: 浏览器。</li>
<li><strong>酒馆</strong>: 服务器。</li>
<li><strong>店小二、厨师</strong>: Servlet或者JSP。</li>
<li><strong>来三碗好酒！</strong>: 浏览器向服务器发出HTTP请求。</li>
<li><strong>店小二上酒</strong>: 服务器的响应。</li>
<li><strong>武松从进店到离开</strong>: 一个HTTP对话。</li></ul>
<p>我们可以看到，Web交互的最基本单位为<strong>HTTP请求</strong>(<em>武松点菜</em>)。
每个用户从进入网站到离开网站这段过程称为一个<strong>HTTP会话</strong>
(<em>武松进店到出店</em>)，一个服务器的运行过程中会有多个用户访问，
就是多个HTTP会话(<em>酒馆当然不可能只接待武松一个客人</em>)。
那么作用域就可以理解为：</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">request</td><td class="style_td">HTTP请求开始到结束这段时间</td></tr><tr><td class="style_td">session</td><td class="style_td">HTTP会话开始到结束这段时间</td></tr><tr><td class="style_td">application</td><td class="style_td">服务器启动到停止这段时间</td></tr></tbody></table></div>
<p><strong>request</strong></p>
<p>一个HTTP请求的处理可能需要多个Servlet合作(<em>武松点菜时店小二就要吩咐厨房做菜</em>)，
几个Servlet之间可以通过某种方式传递信息(<em>店小二就用吆喝的方式通知厨房</em>)，
但这个信息在请求结束后就无效了(<em>厨房在做完菜之后就不用再管这道菜的事儿了</em>)。</p>
<p>Servlet之间的信息共享是通过HttpServletRequest接口的两个方法来实现的：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void setAttribute(String name, Object value)</dt>


<dd>将对象 value 以 name 为名称保存到request作用域中。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>Object getAttribute(String name)</dt>


<dd>从request作用域中取得指定名字的信息。</dd></dl>
<p>doGet()、doPost()函数的第一个参数就是 HttpServletRequest 对象，
使用这个对象的 setAttribute 即可传递信息。</p>
<p>那么设置好信息之后，如何将信息传给其他Servlet？
这就要用到 RequestDispatcher 接口的 forward 方法，将请求转发给其他Servlet。</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>RequestDispatcher ServletContext.getRequestDispatcher(String path)</dt>


<dd>取得Dispatcher以便转发。path为转发的目的Servlet。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void RequestDispatcher.forward(ServletRequest request, ServletResponse response)</dt>


<dd>将request和response转发。</dd></dl>
<p>因此，只要在当前Servlet中先 setAttribute，然后forward，最后在forward到的Servlet中
getAttribute即可实现信息传递。</p>
<p>PHP的程序员可能不太好理解这一段，因为PHP中没有转发的概念，
一个请求只能由一个PHP文件来处理，所以PHP中根本没有request作用域的概念。
而Servlet则不同，请求可以在应用程序中任意转发，所以用request作用域在不同Servlet之间传递信息。
需要注意两点：</p>
<ol class="list1" style="padding-left:16px;margin-left:16px"><li><strong>转发不是重定向</strong>，转发是在Web应用内部进行的。PHP支持重定向但没有转发。</li>
<li><strong>转发对浏览器是透明的</strong>，也就是说，无论在服务器上如何转发，浏览器地址栏中显示的仍然是最初那个Servlet的地址。</li></ol>
<p><strong>session</strong></p>
<p>session作用域比较容易理解，同一浏览器访问多次，在这多次访问之间传递信息，就是session作用域。
('''武松每次点菜帐房先生都要记一笔账，等武松走之前结帐用。
这笔帐在武松吃饭过程中始终有效，即位于session作用域中''')</p>
<p>session是通过HttpSession接口实现的。</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>Object HttpSession.getAttribute(String name)</dt>


<dd>从session中获取信息</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void HttpSession.setAttribute(String name, Object value)</dt>


<dd>向session中保存信息</dd></dl>
<p>而通过HttpServletRequest.getSession()方法可以获得HttpSession对象。</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>HttpSession HttpServletRequest.getSessio()</dt>


<dd>获取当前请求所在的session的对象。</dd></dl>
<p>session的开始容易判断(浏览器发出第一个HTTP请求即可认为会话开始)，
但结束就不好判断了(因为浏览器关闭时不会通知服务器“我关了，会话可以结束了”)，
所以只能通过这种方法判断：如果一定的时间内客户端没有反应，则认为会话结束。
Tomcat的默认值为120分钟，但这个值也可以通过 HttpSession 的 setMaxInactiveInterval 方法来设置。</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void setMaxInactiveInterval(int interval)</dt>


<dd>设置绘画的超时值。</dd></dl>
<p>如果想主动让会话结束，如用户单击“注销”的时候，可以使用 HttpSession 的 invalidate 方法：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>vooid invalidate()</dt>


<dd>强制结束当前session。</dd></dl>
<p><strong>application</strong></p>
<p>application作用域就是服务器启动到关闭的整段时间，
在这个作用域内设置的信息可以被所有应用程序使用。
(<em>餐馆打烊后结帐，用到的即是开张到打烊之间的所有信息。</em>)</p>
<p>还记得<a href="http://tech.idv2.com/2007/09/20/get-init-params/">上一节</a>提到的ServetContext吗？
application作用域上的信息传递就是通过ServetContext实现的。</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>Object getAttribute(String name)</dt>


<dd>从application中获取信息。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>void setAttribute(String name, Object value)</dt>


<dd>向application作用域中设置信息。</dd></dl>
<p><strong>总结</strong></p>
<p>可以看到，每个作用域除了实现接口不同、意义不同之外，它们的使用方法和作用都是相同的，
都是通过 getAttribute 和 setAttribute 方法进行信息传递。</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">作用域</td><td class="style_td">意义</td><td class="style_td">实现接口</td></tr><tr><td class="style_td">request</td><td class="style_td">HTTP请求内</td><td class="style_td">HttpServletRequest</td></tr><tr><td class="style_td">session</td><td class="style_td">HTTP会话内</td><td class="style_td">HttpSession</td></tr><tr><td class="style_td">application</td><td class="style_td">服务器生命周期内</td><td class="style_td">ServletContext</td></tr></tbody></table></div>
<p><strong>示例程序</strong></p>
<p>这一节的示例程序是一个用户登录的模拟程序。文件较多。</p>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li><strong>login.html</strong> 登录表单</li>
<li><strong>DoLogin.java</strong> 处理登录动作的Servlet</li>
<li><strong>LoginSuccess.java</strong> 用于显示登录成功信息的Servlet</li>
<li><strong>SessionTest.java</strong> 登录后的处理程序</li>
<li><strong>DoLogout.java</strong> 注销的处理程序</li></ul>
<p>为了演示 request、application、session 各个作用域的使用方法，
Servlet之间进行了数据传递，数据传递方式如下：</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">数据产生</td><td class="style_td">数据接受</td><td class="style_td">数据内容</td><td class="style_td">作用域</td></tr><tr><td class="style_td">DoLogin</td><td class="style_td">LoginSuccess</td><td class="style_td">登录时间</td><td class="style_td">request</td></tr><tr><td class="style_td">DoLogin</td><td class="style_td">SessionTest</td><td class="style_td">登录用户名</td><td class="style_td">session</td></tr><tr><td class="style_td">DoLogin</td><td class="style_td">SessionTest</td><td class="style_td">系统登录次数</td><td class="style_td">application</td></tr></tbody></table></div>
<p>访问 <a href="http://localhost:8080/LearnJSP/sessiontest">http://localhost:8080/LearnJSP/sessiontest</a>，
登录时输入用户名 charlee 和密码 123456 即可。</p>
<div class="img_margin" style="text-align:left"><a href="http://tech.idv2.com/wp-content/uploads/2007/09/session-test.zip" title="session-test.zip(2007/09/25 15:12:54 5.8KB)"><img src="http://tech.idv2.com/wp-content/plugins/wp-pukiwiki/img/attach.gif" width="16" height="16" alt="attach" style="border-width:0px" />session-test.zip</a></div>

<!-- end Pukiwiki generated code-->

]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2007/09/25/session-and-scope/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Servlet/JSP学习笔记(6)-从配置文件获取参数</title>
		<link>http://tech.idv2.com/2007/09/20/get-init-params/</link>
		<comments>http://tech.idv2.com/2007/09/20/get-init-params/#comments</comments>
		<pubDate>Thu, 20 Sep 2007 13:32:57 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[lomboz]]></category>
		<category><![CDATA[servlet]]></category>

		<guid isPermaLink="false">http://tech.idv2.com/2007/09/20/get-init-params/</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p>前两节(<a href="http://tech.idv2.com/2007/09/14/servlet-basic/">1</a>, <a href="http://tech.idv2.com/2007/09/16/httpservlet/">2</a>)
分别介绍了 GenericServlet 和 HttpServlet 的用法。
这一节将介绍 ServletContext 和 ServletConfig 这两个接口。
通过这两个接口，我们可以在web.xml中设置一些参数，如数据库地址、用户名密码等，供 Servlet 使用，
这样每次参数值变动时，不用重新编译Servlet了。</p>
<!-- end Pukiwiki generated code--><span id="more-494"></span><!-- begin Pukiwiki generated code--><p>javax.servlet.ServletContext接口(上下文参数)是针对整个项目的全局设置，
而javax.servlet.ServletConfig接口(初始化参数)是针对当前Servlet的设置。
两者的设置内容都写在web.xml中。在Lomboz中新建Servlet时，
可以看到设置初始化参数的位置，如下图：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/init-param-01.png" alt="init-param-01.png" title="init-param-01.png" width="423" height="479" /></div>

<p>而上下文参数就没这么方便，只能通过手工编辑web.xml来添加了。
好在Lomboz提供了方便的XML编辑器，
打开web.xml之后即可看到各个Servlet的配置情况，
右键单击最顶层的“web-app”元素，选择<strong>Add Child-&gt;context-param</strong>，
然后分别修改 param-name 和 param-value 即可。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/init-param-02.png" alt="init-param-02.png" title="init-param-02.png" width="500" height="452" /></div>

<p>那么在程序中如何取得这两类参数？请看这几个方法：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>javax.servlet.GenericServlet.getServletConfig</dt>


<dd>返回当前Servlet的ServletConfig对象。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>javax.servlet.ServletConfig.getServletContext</dt>


<dd>返回当前应用程序的ServletContext对象。</dd></dl>
<p>通过这两个方法，我们就可以获得当前Servlet的初始化参数对象和上下文参数对象。</p>
<p>ServletContext的主要方法：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>String getInitParameter(String name)</dt>


<dd>获取指定上下文参数的值。</dd></dl>
<p>ServletConfig的主要方法：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>String getInitParameter(String name)</dt>


<dd>获取指定初始化参数的值。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>java.util.Enumeration getInitParameterNames()</dt>


<dd>获取所有的初始化参数的名称。</dd></dl>
<p>示例程序分别通过ServletContext和ServletContent读出值并显示出来。
因为参数值在Servlet的生命周期中是不变的，仅需读取一次即可，
所以将取得参数的代码写在了 init() 方法而不是 doGet()方法中。
其他没什么特别需要说明的地方，参数追加的方法参考前文即可。</p>
<div class="img_margin" style="text-align:left"><a href="http://tech.idv2.com/wp-content/uploads/2007/09/initparam.zip" title="initparam.zip(2007/09/21 12:31:30 2.1KB)"><img src="http://tech.idv2.com/wp-content/plugins/wp-pukiwiki/img/attach.gif" width="16" height="16" alt="attach" style="border-width:0px" />initparam.zip</a></div>

<!-- end Pukiwiki generated code-->

]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p>前两节(<a href="http://tech.idv2.com/2007/09/14/servlet-basic/">1</a>, <a href="http://tech.idv2.com/2007/09/16/httpservlet/">2</a>)
分别介绍了 GenericServlet 和 HttpServlet 的用法。
这一节将介绍 ServletContext 和 ServletConfig 这两个接口。
通过这两个接口，我们可以在web.xml中设置一些参数，如数据库地址、用户名密码等，供 Servlet 使用，
这样每次参数值变动时，不用重新编译Servlet了。</p>
<!-- end Pukiwiki generated code--><span id="more-494"></span><!-- begin Pukiwiki generated code--><p>javax.servlet.ServletContext接口(上下文参数)是针对整个项目的全局设置，
而javax.servlet.ServletConfig接口(初始化参数)是针对当前Servlet的设置。
两者的设置内容都写在web.xml中。在Lomboz中新建Servlet时，
可以看到设置初始化参数的位置，如下图：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/init-param-01.png" alt="init-param-01.png" title="init-param-01.png" width="423" height="479" /></div>

<p>而上下文参数就没这么方便，只能通过手工编辑web.xml来添加了。
好在Lomboz提供了方便的XML编辑器，
打开web.xml之后即可看到各个Servlet的配置情况，
右键单击最顶层的“web-app”元素，选择<strong>Add Child-&gt;context-param</strong>，
然后分别修改 param-name 和 param-value 即可。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/init-param-02.png" alt="init-param-02.png" title="init-param-02.png" width="500" height="452" /></div>

<p>那么在程序中如何取得这两类参数？请看这几个方法：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>javax.servlet.GenericServlet.getServletConfig</dt>


<dd>返回当前Servlet的ServletConfig对象。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>javax.servlet.ServletConfig.getServletContext</dt>


<dd>返回当前应用程序的ServletContext对象。</dd></dl>
<p>通过这两个方法，我们就可以获得当前Servlet的初始化参数对象和上下文参数对象。</p>
<p>ServletContext的主要方法：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>String getInitParameter(String name)</dt>


<dd>获取指定上下文参数的值。</dd></dl>
<p>ServletConfig的主要方法：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>String getInitParameter(String name)</dt>


<dd>获取指定初始化参数的值。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>java.util.Enumeration getInitParameterNames()</dt>


<dd>获取所有的初始化参数的名称。</dd></dl>
<p>示例程序分别通过ServletContext和ServletContent读出值并显示出来。
因为参数值在Servlet的生命周期中是不变的，仅需读取一次即可，
所以将取得参数的代码写在了 init() 方法而不是 doGet()方法中。
其他没什么特别需要说明的地方，参数追加的方法参考前文即可。</p>
<div class="img_margin" style="text-align:left"><a href="http://tech.idv2.com/wp-content/uploads/2007/09/initparam.zip" title="initparam.zip(2007/09/21 12:31:30 2.1KB)"><img src="http://tech.idv2.com/wp-content/plugins/wp-pukiwiki/img/attach.gif" width="16" height="16" alt="attach" style="border-width:0px" />initparam.zip</a></div>

<!-- end Pukiwiki generated code-->

]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2007/09/20/get-init-params/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Servlet/JSP学习笔记(5)-HttpServlet</title>
		<link>http://tech.idv2.com/2007/09/16/httpservlet/</link>
		<comments>http://tech.idv2.com/2007/09/16/httpservlet/#comments</comments>
		<pubDate>Sun, 16 Sep 2007 10:46:17 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[lomboz]]></category>
		<category><![CDATA[servlet]]></category>

		<guid isPermaLink="false">http://tech.idv2.com/2007/09/16/httpservlet/</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p><a href="http://tech.idv2.com/2007/09/14/servlet-basic/">上一节</a>我们介绍了
javax.servlet.Servlet接口和继承javax.servlet.GenericServlet抽象类生成Servlet的方法。
而实际上，直接继承GenericServlet并不方便也不实用，
更多的情况下是继承javax.servlet.http.HttpServlet来生成Servlet。</p>
<!-- end Pukiwiki generated code--><span id="more-485"></span><!-- begin Pukiwiki generated code--><p><strong>HttpServlet</strong></p>
<p>先来复习一下上一节提到的类结构图：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-07.png" alt="servlet-basic-07.png" title="servlet-basic-07.png" width="453" height="342" /></div>

<p>可以看到，HttpServlet继承了GenericServlet，不过它也是一个抽象类，
不能直接使用，只能继承它。</p>
<p>HttpServlet中常用的方法有两个：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>doGet</dt>


<dd>void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException</dd>

<dd>当浏览器用GET方式访问时，该方法被调用。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>doPost</dt>


<dd>void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException</dd>

<dd>当浏览器用POST方式访问时，该方法被调用。</dd></dl>
<p>这两个函数内部的处理方法基本上与上一节介绍的GenericServlet.service()函数相同。</p>
<p>另外其他的HTTP请求也都有相应的方法：</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">HTTP请求类别</td><td class="style_td">HttpServlet的方法</td></tr><tr><td class="style_td">GET</td><td class="style_td">doGet()</td></tr><tr><td class="style_td">POST</td><td class="style_td">doPost()</td></tr><tr><td class="style_td">HEAD</td><td class="style_td">doHead()</td></tr><tr><td class="style_td">PUT</td><td class="style_td">doPut()</td></tr><tr><td class="style_td">DELETE</td><td class="style_td">doDelete()</td></tr></tbody></table></div>
<p><strong>HttpServletRequest</strong></p>
<p>doGet()和doPost()函数的两个参数为 HttpServletRequest和HttpServletResponse对象。</p>
<p>HttpServletRequest接口表示浏览器请求，你可以通过这个类获取浏览器发送到服务器的任何信息。
对于PHP程序员来说，这个类有点类似于 $_GET、$_POST、$_SERVER 等几个变量的内容。
它的常用方法如下：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getParameter</dt>


<dd>String getParameter(String name)</dd>

<dd>获取指定变量名name所对应的参数值。该方法实际上为父接口 javax.servlet.ServletRequest的方法。如果是GET请求则获取查询字符串后的参数，POST请求则获取&lt;form&gt;表单中的参数。类似于PHP的$_GET和$_POST数组。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getParameterValues</dt>


<dd>String[] getParameterValues(String name)</dd>

<dd>这个方法与getParameter()类似。当你要获取&lt;input type=&quot;check&quot;&gt;这类会返回多个值的表单属性时，就应当用这个方法。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getMethod</dt>


<dd>String getMethod()</dd>

<dd>返回字符串&quot;GET&quot;或&quot;POST&quot;。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getRequestURI</dt>


<dd>String getRequestURI()</dd>

<dd>获取请求的URI（不包括查询字符串）。相当于PHP的$_SERVER['REQUEST_URI']。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getServletPath</dt>


<dd>String getServletPath()</dd>

<dd>获取Servlet的路径。相当于PHP的$_SERVER['PHP_SELF']。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getPathInfo</dt>


<dd>String getPathInfo()</dd>

<dd>获取PathInfo。相当于PHP的$_SERVER['PATH_INFO']。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>setCharacterEncoding</dt>


<dd>void setCharacterEncoding(String new)</dd>

<dd>设置请求的编码。需要处理汉字时务必要通过该方法设置正确的字符编码，否则将无法正确读取浏览器发过来的文字。</dd></dl>
<p>还有好多有用的方法大家可以自己去参考接口文档。</p>
<p><strong>HttpServletResponse</strong></p>
<p>HttpServletResponse接口则用于控制服务器发送给客户端的内容，相当于PHP的echo、header等函数。</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>setContentType</dt>


<dd>void setContentType(String type)</dd>

<dd>设置返回值的类型。通常的HTML内容可设置为&quot;text/html; charset=UTF-8&quot;等，而动态生成的图片则可以设置为&quot;image/gif&quot;等。输出汉字之前，务必要通过该方法指定输出的字符编码。相当于在PHP中写 header(&quot;Content-Type: image/gif&quot;)。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>ServletOutputStream</dt>


<dd>ServletOutputStream getOutputStream() throws IOException</dd>

<dd>向客户端发送二进制数据时，需要通过此方法获取输出流。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getWriter</dt>


<dd>PrintWriter getWriter() throws IOException</dd>

<dd>向客户端发送文本数据时，需要通过此方法获取输出流。</dd></dl>
<p><strong>示例程序</strong></p>
<p>上一节建立Servlet时，我们先生成了Java代码，再将其添加到web.xml的Servlet节中。
实际上可以直接在web.xml的Servlet节中建立Servlet，Lomboz会自动帮我们生成Java代码。</p>
<p>我们这次将建立一个表单提交程序，通过一个HTML表单提交数据，然后在Servlet中读出数据并显示出来。</p>
<p>首先右键单击WebContent目录，选择<strong>New-&gt;HTML</strong>，新建一个HTML文档，命名为 htmlpost.html。
下一步是选择HTML模板，直接用默认值即可。</p>
<p>然后编辑 htmlpost.html，可参考本节的源代码。源代码下载：</p>
<div class="img_margin" style="text-align:left"><a href="http://tech.idv2.com/wp-content/uploads/2007/09/httppost.zip" title="httppost.zip(2007/09/17 09:44:56 3.0KB)"><img src="http://tech.idv2.com/wp-content/plugins/wp-pukiwiki/img/attach.gif" width="16" height="16" alt="attach" style="border-width:0px" />httppost.zip</a></div>

<p>右键单击Deployment Descriptor中的Servlets，选择<strong>New-&gt;Servlet</strong>。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/httpservlet-01.png" alt="httpservlet-01.png" title="httpservlet-01.png" width="302" height="174" /></div>

<p>按照下图的样子，在Java package处输入包名 com.idv2.learnjsp，在 Class name处输入类名 HttpPost，单击Next。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/httpservlet-02.png" alt="httpservlet-02.png" title="httpservlet-02.png" width="425" height="437" /></div>

<p>出现Servlet映射的配置界面，输入适当的Description。注意下方的 URL Mappings，这个就是从浏览器访问该Servlet时使用的URL。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/httpservlet-03.png" alt="httpservlet-03.png" title="httpservlet-03.png" width="432" height="484" /></div>

<p>下一步选择新建的类的属性，通常选择默认即可。
不过我们的Servlet只需要处理POST方法，所以下方的重载列表中只需选择doPost即可。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/httpservlet-04.png" alt="httpservlet-04.png" title="httpservlet-04.png" width="432" height="484" /></div>

<p>最后单击Finish，即可完成Servlet的建立，并且Lomboz会自动在Java代码的src目录中生成HttpPost.java文件的框架。</p>
<p>编辑java代码，可以参考下面的源代码下载。</p>
<div class="img_margin" style="text-align:left"><a href="http://tech.idv2.com/wp-content/uploads/2007/09/httppost.zip" title="httppost.zip(2007/09/17 09:44:56 3.0KB)"><img src="http://tech.idv2.com/wp-content/plugins/wp-pukiwiki/img/attach.gif" width="16" height="16" alt="attach" style="border-width:0px" />httppost.zip</a></div>

<p>其实这段代码的主要内容就是通过 getParameter 或者 getParameterValues 方法来获取客户端提交的数据。其代码片段如下；</p>
<pre>// 字符集
request.setCharacterEncoding(&quot;UTF-8&quot;);

// 从表单中获得数据
out.println(&quot;  &lt;li&gt;用户名: &quot; + request.getParameter(&quot;username&quot;));
out.println(&quot;  &lt;li&gt;密码: &quot; + request.getParameter(&quot;password&quot;));
out.println(&quot;  &lt;li&gt;确认密码: &quot; + request.getParameter(&quot;confpass&quot;));

// 获取复选框的表单选项
String interests[] = request.getParameterValues(&quot;interests&quot;);
out.println(&quot;  &lt;li&gt;兴趣爱好: &lt;br/&gt;&quot;);
if (interests != null) {
  for (int i = 0; i &lt; interests.length; i++) {
    out.println(interests[i] + &quot;&lt;br/&gt;&quot;);
  }
}</pre>
<p>编辑好代码之后，在Server视图中启动Tomcat，打开浏览器，输入 <a href="http://localhost:8080/LearnJSP/httppost.html">http://localhost:8080/LearnJSP/httppost.html</a>，
输入信息之后单击“注册”，即可看到输入的注册信息。</p>
<!-- end Pukiwiki generated code-->
]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p><a href="http://tech.idv2.com/2007/09/14/servlet-basic/">上一节</a>我们介绍了
javax.servlet.Servlet接口和继承javax.servlet.GenericServlet抽象类生成Servlet的方法。
而实际上，直接继承GenericServlet并不方便也不实用，
更多的情况下是继承javax.servlet.http.HttpServlet来生成Servlet。</p>
<!-- end Pukiwiki generated code--><span id="more-485"></span><!-- begin Pukiwiki generated code--><p><strong>HttpServlet</strong></p>
<p>先来复习一下上一节提到的类结构图：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-07.png" alt="servlet-basic-07.png" title="servlet-basic-07.png" width="453" height="342" /></div>

<p>可以看到，HttpServlet继承了GenericServlet，不过它也是一个抽象类，
不能直接使用，只能继承它。</p>
<p>HttpServlet中常用的方法有两个：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>doGet</dt>


<dd>void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException</dd>

<dd>当浏览器用GET方式访问时，该方法被调用。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>doPost</dt>


<dd>void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException</dd>

<dd>当浏览器用POST方式访问时，该方法被调用。</dd></dl>
<p>这两个函数内部的处理方法基本上与上一节介绍的GenericServlet.service()函数相同。</p>
<p>另外其他的HTTP请求也都有相应的方法：</p>
<div class="ie5"><table class="style_table" cellspacing="1" border="0"><tbody><tr><td class="style_td">HTTP请求类别</td><td class="style_td">HttpServlet的方法</td></tr><tr><td class="style_td">GET</td><td class="style_td">doGet()</td></tr><tr><td class="style_td">POST</td><td class="style_td">doPost()</td></tr><tr><td class="style_td">HEAD</td><td class="style_td">doHead()</td></tr><tr><td class="style_td">PUT</td><td class="style_td">doPut()</td></tr><tr><td class="style_td">DELETE</td><td class="style_td">doDelete()</td></tr></tbody></table></div>
<p><strong>HttpServletRequest</strong></p>
<p>doGet()和doPost()函数的两个参数为 HttpServletRequest和HttpServletResponse对象。</p>
<p>HttpServletRequest接口表示浏览器请求，你可以通过这个类获取浏览器发送到服务器的任何信息。
对于PHP程序员来说，这个类有点类似于 $_GET、$_POST、$_SERVER 等几个变量的内容。
它的常用方法如下：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getParameter</dt>


<dd>String getParameter(String name)</dd>

<dd>获取指定变量名name所对应的参数值。该方法实际上为父接口 javax.servlet.ServletRequest的方法。如果是GET请求则获取查询字符串后的参数，POST请求则获取&lt;form&gt;表单中的参数。类似于PHP的$_GET和$_POST数组。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getParameterValues</dt>


<dd>String[] getParameterValues(String name)</dd>

<dd>这个方法与getParameter()类似。当你要获取&lt;input type=&quot;check&quot;&gt;这类会返回多个值的表单属性时，就应当用这个方法。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getMethod</dt>


<dd>String getMethod()</dd>

<dd>返回字符串&quot;GET&quot;或&quot;POST&quot;。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getRequestURI</dt>


<dd>String getRequestURI()</dd>

<dd>获取请求的URI（不包括查询字符串）。相当于PHP的$_SERVER['REQUEST_URI']。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getServletPath</dt>


<dd>String getServletPath()</dd>

<dd>获取Servlet的路径。相当于PHP的$_SERVER['PHP_SELF']。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getPathInfo</dt>


<dd>String getPathInfo()</dd>

<dd>获取PathInfo。相当于PHP的$_SERVER['PATH_INFO']。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>setCharacterEncoding</dt>


<dd>void setCharacterEncoding(String new)</dd>

<dd>设置请求的编码。需要处理汉字时务必要通过该方法设置正确的字符编码，否则将无法正确读取浏览器发过来的文字。</dd></dl>
<p>还有好多有用的方法大家可以自己去参考接口文档。</p>
<p><strong>HttpServletResponse</strong></p>
<p>HttpServletResponse接口则用于控制服务器发送给客户端的内容，相当于PHP的echo、header等函数。</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>setContentType</dt>


<dd>void setContentType(String type)</dd>

<dd>设置返回值的类型。通常的HTML内容可设置为&quot;text/html; charset=UTF-8&quot;等，而动态生成的图片则可以设置为&quot;image/gif&quot;等。输出汉字之前，务必要通过该方法指定输出的字符编码。相当于在PHP中写 header(&quot;Content-Type: image/gif&quot;)。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>ServletOutputStream</dt>


<dd>ServletOutputStream getOutputStream() throws IOException</dd>

<dd>向客户端发送二进制数据时，需要通过此方法获取输出流。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getWriter</dt>


<dd>PrintWriter getWriter() throws IOException</dd>

<dd>向客户端发送文本数据时，需要通过此方法获取输出流。</dd></dl>
<p><strong>示例程序</strong></p>
<p>上一节建立Servlet时，我们先生成了Java代码，再将其添加到web.xml的Servlet节中。
实际上可以直接在web.xml的Servlet节中建立Servlet，Lomboz会自动帮我们生成Java代码。</p>
<p>我们这次将建立一个表单提交程序，通过一个HTML表单提交数据，然后在Servlet中读出数据并显示出来。</p>
<p>首先右键单击WebContent目录，选择<strong>New-&gt;HTML</strong>，新建一个HTML文档，命名为 htmlpost.html。
下一步是选择HTML模板，直接用默认值即可。</p>
<p>然后编辑 htmlpost.html，可参考本节的源代码。源代码下载：</p>
<div class="img_margin" style="text-align:left"><a href="http://tech.idv2.com/wp-content/uploads/2007/09/httppost.zip" title="httppost.zip(2007/09/17 09:44:56 3.0KB)"><img src="http://tech.idv2.com/wp-content/plugins/wp-pukiwiki/img/attach.gif" width="16" height="16" alt="attach" style="border-width:0px" />httppost.zip</a></div>

<p>右键单击Deployment Descriptor中的Servlets，选择<strong>New-&gt;Servlet</strong>。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/httpservlet-01.png" alt="httpservlet-01.png" title="httpservlet-01.png" width="302" height="174" /></div>

<p>按照下图的样子，在Java package处输入包名 com.idv2.learnjsp，在 Class name处输入类名 HttpPost，单击Next。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/httpservlet-02.png" alt="httpservlet-02.png" title="httpservlet-02.png" width="425" height="437" /></div>

<p>出现Servlet映射的配置界面，输入适当的Description。注意下方的 URL Mappings，这个就是从浏览器访问该Servlet时使用的URL。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/httpservlet-03.png" alt="httpservlet-03.png" title="httpservlet-03.png" width="432" height="484" /></div>

<p>下一步选择新建的类的属性，通常选择默认即可。
不过我们的Servlet只需要处理POST方法，所以下方的重载列表中只需选择doPost即可。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/httpservlet-04.png" alt="httpservlet-04.png" title="httpservlet-04.png" width="432" height="484" /></div>

<p>最后单击Finish，即可完成Servlet的建立，并且Lomboz会自动在Java代码的src目录中生成HttpPost.java文件的框架。</p>
<p>编辑java代码，可以参考下面的源代码下载。</p>
<div class="img_margin" style="text-align:left"><a href="http://tech.idv2.com/wp-content/uploads/2007/09/httppost.zip" title="httppost.zip(2007/09/17 09:44:56 3.0KB)"><img src="http://tech.idv2.com/wp-content/plugins/wp-pukiwiki/img/attach.gif" width="16" height="16" alt="attach" style="border-width:0px" />httppost.zip</a></div>

<p>其实这段代码的主要内容就是通过 getParameter 或者 getParameterValues 方法来获取客户端提交的数据。其代码片段如下；</p>
<pre>// 字符集
request.setCharacterEncoding(&quot;UTF-8&quot;);

// 从表单中获得数据
out.println(&quot;  &lt;li&gt;用户名: &quot; + request.getParameter(&quot;username&quot;));
out.println(&quot;  &lt;li&gt;密码: &quot; + request.getParameter(&quot;password&quot;));
out.println(&quot;  &lt;li&gt;确认密码: &quot; + request.getParameter(&quot;confpass&quot;));

// 获取复选框的表单选项
String interests[] = request.getParameterValues(&quot;interests&quot;);
out.println(&quot;  &lt;li&gt;兴趣爱好: &lt;br/&gt;&quot;);
if (interests != null) {
  for (int i = 0; i &lt; interests.length; i++) {
    out.println(interests[i] + &quot;&lt;br/&gt;&quot;);
  }
}</pre>
<p>编辑好代码之后，在Server视图中启动Tomcat，打开浏览器，输入 <a href="http://localhost:8080/LearnJSP/httppost.html">http://localhost:8080/LearnJSP/httppost.html</a>，
输入信息之后单击“注册”，即可看到输入的注册信息。</p>
<!-- end Pukiwiki generated code-->
]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2007/09/16/httpservlet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Servlet/JSP学习笔记(4)-Servlet入门</title>
		<link>http://tech.idv2.com/2007/09/14/servlet-basic/</link>
		<comments>http://tech.idv2.com/2007/09/14/servlet-basic/#comments</comments>
		<pubDate>Thu, 13 Sep 2007 16:23:48 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[lomboz]]></category>
		<category><![CDATA[servlet]]></category>

		<guid isPermaLink="false">http://tech.idv2.com/2007/09/14/servlet-basic/</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p>介绍完工具和基本概念，现在终于开始介绍Servlet的编写方法了。
为了便于理解，我们将采用eclipse+Lomboz作为开发环境，
一切的操作都可以在eclipse中完成。
如果你还没有安装好Lomboz，请参考前几篇文章配置好环境。</p>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li><a href="http://tech.idv2.com/2007/09/12/how-to-install-eclipse-and-tomcat/">tomcat和eclipse的安装</a></li>
<li><a href="http://tech.idv2.com/2007/09/12/basic-about-servlet-and-jsp/">基础知识</a></li>
<li><a href="http://tech.idv2.com/2007/09/13/install-lomboz/">Lomboz介绍+安装方法</a></li></ul>
<p>我们将建立一个名为 com.idv2.learnjsp 的包，用于容纳所有的示例程序。
下面我们就看看最基本的Servlet的创建方法。</p>
<!-- end Pukiwiki generated code--><span id="more-468"></span><!-- begin Pukiwiki generated code--><p><strong>创建项目</strong></p>
<p>启动eclipse，然后选择菜单<strong>File-&gt;New-&gt;Project...</strong>，在新建项目向导中选择
<strong>Web-&gt;Dynamic Web Project</strong>。该项目即为使用Servlet、JSP等技术开发动态网站的项目。
（如果你找不到这一项，说明Lomboz没有配置好，请参阅文章开头的链接进行配置。）</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-01.png" alt="新建一个Dynamic Web Project" title="新建一个Dynamic Web Project" width="378" height="428" /></div>

<p>下一步，输入项目名 LearnJSP。下面的<strong>Target Runtime</strong>指定运行这个项目的服务器，
如果你已经在<a href="http://tech.idv2.com/2007/09/13/install-lomboz/">配置Lomboz</a>
的一节中配置好了Tomcat服务器，那么在这里你可以看到相应的服务器配置，选择它即可。
如果选择框中只有&lt;none&gt;，说明你还没有配置服务器，可以单击右侧的<strong>New...</strong>按钮新建。</p>
<p><strong>Configurations</strong>项选择&lt;none&gt;即可。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-02.png" alt="项目名和配置" title="项目名和配置" width="457" height="451" /></div>

<p>下一步选择项目所需的特性，默认的<strong>Dynamic Web Module</strong>和<strong>Java</strong>就足够了。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-03.png" alt="选择项目特性" title="选择项目特性" width="395" height="418" /></div>

<p>下一步是输入相关的目录，这里也直接使用默认值即可。图略。</p>
<p>最后单击 Finish，完成项目创建。创建途中可能会有一个用户使用协议需要你同意，
单击<strong>I Agree</strong>即可。创建完成后会询问是否要切换到J2EE视图（下图），选择<strong>Yes</strong>，
完成项目创建。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-04.png" alt="是否要切换到J2EE视图" title="是否要切换到J2EE视图" width="441" height="160" /></div>

<p>项目建立完成后，请在左侧的 Project Explorer 中打开 LearnJSP 项目，
看看它各个部分的构成。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-05.png" alt="项目视图的各个组成部分" title="项目视图的各个组成部分" width="401" height="359" /></div>

<p>从<a href="http://tech.idv2.com/2007/09/12/basic-about-servlet-and-jsp/">基础知识</a>一节中
我们知道，应用程序由三部分组成，即Servlet、JSP及静态内容、配置文件web.xml。
项目视图中的 <strong>src</strong> 目录用来保存 Servlet 源代码，<strong>WebContent</strong> 目录用来保存JSP及静态内容，
web.xml则位于 WebContent/WEB-INF/web.xml。但手工编辑 web.xml 比较麻烦，
因此 Lomboz 提供了一套可视化工具用于编辑 web.xml，即最上方的<strong>Depolyment Descriptor</strong>，
里面包含的内容以后会陆续讲解。</p>
<p><strong>理解Servlet</strong></p>
<p>在Project Explorer中打开<strong>Java Resources: src -&gt; Libraries -&gt; Apache Tomcat 5.5 -&gt; servlet-api.jar</strong>
文件，可以看到其中包含两个包：<strong>javax.servlet</strong>和<strong>javax.servlet.http</strong>，
与Servlet有关的类和接口都位于这两个包里面。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-06.png" alt="Servlet API所在的包" title="Servlet API所在的包" width="281" height="306" /></div>

<p>Servlet是一个接口，位于 javax.servlet.Servlet，它规定了每个Servlet所必须实现的方法。
实际应用时我们需要从 javax.servlet.GenericServlet 和 javax.servlet.http.HttpServlet 两个抽象类
继承出自己的Servlet类，并实现所需的功能。这几个类的关系如下（绿色斜体字为抽象类）：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-07.png" alt="Servlet相关类的关系" title="Servlet相关类的关系" width="453" height="342" /></div>

<p>上图中，Servlet依赖于ServletRequest和ServletResponse接口，这两个接口负责为Servlet接受和发送信息。
HttpServlet也类似。</p>
<p><strong>Servlet接口</strong></p>
<p>javax.servlet.Servlet接口包含以下的方法：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>init()</dt>


<dd><strong>void init(ServletConfig config) throws ServletException</strong></dd>

<dd>init方法用于初始化，在Servlet启动时调用。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>service()</dt>


<dd><strong>void service(ServletRequest req, ServiceResponse res) throws ServletException, IOException</strong></dd>

<dd>Servlet通过这个方法，从req获得客户端请求，处理并生成结果，再通过res发送给客户端。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>destroy()</dt>


<dd><strong>void destroy()</strong></dd>

<dd>Servlet销毁时执行的方法。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getServletInfo()</dt>


<dd><strong>String getServletInfo()</strong></dd>

<dd>将Servlet的信息通过字符串返回。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getServletConfig()</dt>


<dd><strong>ServletConfig getServletConfig()</strong></dd>

<dd>获取包含Servlet各种信息的ServletConfig对象。</dd></dl>
<p>当某个Servlet第一次被请求时，服务器（Servlet容器）会生成该Servlet并调用它的init()方法，
再调用其service()方法处理请求。处理结束后该Servlet会常驻于容器中，下一个请求则不再
重新生成Servlet，而是直接调用常驻的Servlet对象的service()方法。
服务器停止时，会调用该Servlet的destroy()方法。</p>
<p>因此，在Servlet的一个生命周期中，init()和destroy()仅会被调用一次，
而service()则会被调用多次。</p>
<p><strong>GenericServlet抽象类</strong></p>
<p>javax.servlet.GenericServlet为我们实现了Servlet接口的大部分方法，除了service()方法之外。
因此，我们在制作自己的Servlet时，只需要继承GenericServlet并重载service()方法即可。</p>
<p><strong>典型的Servlet示例</strong></p>
<p>下面我们来做一个典型的Servlet。</p>
<p>在eclipse左侧的Project Explorer中，右键单击<strong>Java Resources: src</strong>目录（以后简称<strong>src</strong>目录），
选择<strong>New-&gt;Class</strong>，建立如下所示的类。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-08.png" alt="建立Servlet类" title="建立Servlet类" width="495" height="592" /></div>

<p>包名输入我们要建立的 com.idv2.learnjsp，类名为 HelloServlet，父类为 javax.servlet.http.GenericServlet。
在输入父类名时，你会看到输入框左侧有个小灯泡的图标，这说明可以通过 <strong>Alt-/</strong>键自动补齐，
因此你只需输入 GenericSer 几个字母，然后按 Alt-/ 组合键，系统会自动查找开头为 GenericSer 的类
并补齐剩余部分。</p>
<p>Finish之后eclipse会为我们生成代码框架，我们只需填入实际的处理代码即可。
代码可以从这里下载。</p>
<div class="img_margin" style="text-align:left"><a href="http://tech.idv2.com/wp-content/uploads/2007/09/helloservlet.zip" title="helloservlet.zip(2007/09/14 15:19:48 1.2KB)"><img src="http://tech.idv2.com/wp-content/plugins/wp-pukiwiki/img/attach.gif" width="16" height="16" alt="attach" style="border-width:0px" />helloservlet.zip</a></div>

<p>上述代码是UTF-8编码，如果你直接放到src目录中有可能出现乱码，
这时请选择<strong>Windows-&gt;Preferences...</strong>菜单，选择左侧的<strong>General-&gt;Workspace</strong>，
然后将<strong>Text file encoding</strong>设置为<strong>UTF-8</strong>即可。</p>
<p>代码写好后，从Project Explorer中打开项目的 build 目录，可以看到eclipse自动编译了
HelloServlet.java并生成了 com/idv2/learnjsp/HelloServlet.class 文件。</p>
<p>那么如何在服务器上运行它呢？首先必须要做的就是在配置文件 web.xml 中登记这个Servlet。
刚才我们在建立 HelloServlet 类时，并没有声明它是一个Servlet，这样服务器就无法将它
作为Servlet执行，因此必须先登记，并为它指定一个URL（即Servlet Mapping）。</p>
<p>右键单击<strong>Depolyment Descriptor</strong>中的<strong>Servlets</strong>，选择<strong>New-&gt;Servlet</strong>，出现下面的画面。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-09.png" alt="登记Servlet" title="登记Servlet" width="422" height="429" /></div>

<p>因为我们已经写好了HelloServlet类，因此选中<strong>Use existing Servlet class</strong>，
然后单击右侧的<strong>Browse...</strong>按钮，选择HelloServlet类。下一步。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-10.png" alt="设置Servlet名称和URL映射" title="设置Servlet名称和URL映射" width="422" height="481" /></div>

<p>URL映射是指，浏览器通过哪个URL能访问到这个Servlet。
默认与Servlet名称相同，为了演示，我们这里将他修改为小写的 /helloservlet 。
实际的URL格式为 http://主机名/应用程序名/Servlet的URL映射，
我们这个Servlet的URL就应当是 <a href="http://localhost:8080/LearnJSP/helloservlet">http://localhost:8080/LearnJSP/helloservlet</a>。</p>
<p>单击Finish完成添加Servlet。如果你有兴趣可以打开 WebContent/WEB-INF/web.xml，
可以看到刚才的修改在web.xml中是怎样的结果。</p>
<p>下一步我们需要将它部署到服务器上。打开eclipse下方的<strong>Servet</strong>栏，
可以看到系统中的服务器列表。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-11.png" alt="Server栏" title="Server栏" width="483" height="87" /></div>

<p>如果你找不到Server栏，请通过主菜单<strong>Window-&gt;Show View-&gt;Others</strong>添加Server栏；
如果你的Server栏中什么都没有，请在Server栏中单击右键然后 <strong>New-&gt;Server</strong>。</p>
<p>右键单击服务器，选择<strong>Add and Remove Projects...</strong>，将 LearnJSP项目添加到服务器上。
添加之后的结果如下：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-12.png" alt="Server栏" title="Server栏" width="476" height="92" /></div>

<p>最后右键单击服务器，选择<strong>Start</strong>，片刻即可看到在Console栏中输出大量的信息，服务器启动了。
打开浏览器，访问 <a href="http://localhost:8080/LearnJSP/helloservlet">http://localhost:8080/LearnJSP/helloservlet</a>。
如果能看到“Hello Servlet”的输出，则恭喜你，第一个Servlet成功运行了！</p>
<p>刷新浏览器页面几次，然后回到eclipse下侧的Console栏，可以看到下面的字样：</p>
<pre>init() was called.
service() was called.
service() was called.
service() was called.</pre>
<p>这是我们加入的调试信息。这些信息说明了Servlet的一个生命周期中
init、service和destroy函数的执行过程。
如果在Server栏中停止服务器，那么你可以在Console栏中的信息中找到 destroy() 函数的执行。</p>
<p><strong>结语</strong></p>
<p>这一节重点结合Lomboz的用法，讲述了Servlet的基本原理和最简单的Servlet的编写方法。
以后的内容可能就不会这么详细地说明Lomboz的用法了。</p>
<!-- end Pukiwiki generated code-->
]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p>介绍完工具和基本概念，现在终于开始介绍Servlet的编写方法了。
为了便于理解，我们将采用eclipse+Lomboz作为开发环境，
一切的操作都可以在eclipse中完成。
如果你还没有安装好Lomboz，请参考前几篇文章配置好环境。</p>
<ul class="list1" style="padding-left:16px;margin-left:16px"><li><a href="http://tech.idv2.com/2007/09/12/how-to-install-eclipse-and-tomcat/">tomcat和eclipse的安装</a></li>
<li><a href="http://tech.idv2.com/2007/09/12/basic-about-servlet-and-jsp/">基础知识</a></li>
<li><a href="http://tech.idv2.com/2007/09/13/install-lomboz/">Lomboz介绍+安装方法</a></li></ul>
<p>我们将建立一个名为 com.idv2.learnjsp 的包，用于容纳所有的示例程序。
下面我们就看看最基本的Servlet的创建方法。</p>
<!-- end Pukiwiki generated code--><span id="more-468"></span><!-- begin Pukiwiki generated code--><p><strong>创建项目</strong></p>
<p>启动eclipse，然后选择菜单<strong>File-&gt;New-&gt;Project...</strong>，在新建项目向导中选择
<strong>Web-&gt;Dynamic Web Project</strong>。该项目即为使用Servlet、JSP等技术开发动态网站的项目。
（如果你找不到这一项，说明Lomboz没有配置好，请参阅文章开头的链接进行配置。）</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-01.png" alt="新建一个Dynamic Web Project" title="新建一个Dynamic Web Project" width="378" height="428" /></div>

<p>下一步，输入项目名 LearnJSP。下面的<strong>Target Runtime</strong>指定运行这个项目的服务器，
如果你已经在<a href="http://tech.idv2.com/2007/09/13/install-lomboz/">配置Lomboz</a>
的一节中配置好了Tomcat服务器，那么在这里你可以看到相应的服务器配置，选择它即可。
如果选择框中只有&lt;none&gt;，说明你还没有配置服务器，可以单击右侧的<strong>New...</strong>按钮新建。</p>
<p><strong>Configurations</strong>项选择&lt;none&gt;即可。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-02.png" alt="项目名和配置" title="项目名和配置" width="457" height="451" /></div>

<p>下一步选择项目所需的特性，默认的<strong>Dynamic Web Module</strong>和<strong>Java</strong>就足够了。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-03.png" alt="选择项目特性" title="选择项目特性" width="395" height="418" /></div>

<p>下一步是输入相关的目录，这里也直接使用默认值即可。图略。</p>
<p>最后单击 Finish，完成项目创建。创建途中可能会有一个用户使用协议需要你同意，
单击<strong>I Agree</strong>即可。创建完成后会询问是否要切换到J2EE视图（下图），选择<strong>Yes</strong>，
完成项目创建。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-04.png" alt="是否要切换到J2EE视图" title="是否要切换到J2EE视图" width="441" height="160" /></div>

<p>项目建立完成后，请在左侧的 Project Explorer 中打开 LearnJSP 项目，
看看它各个部分的构成。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-05.png" alt="项目视图的各个组成部分" title="项目视图的各个组成部分" width="401" height="359" /></div>

<p>从<a href="http://tech.idv2.com/2007/09/12/basic-about-servlet-and-jsp/">基础知识</a>一节中
我们知道，应用程序由三部分组成，即Servlet、JSP及静态内容、配置文件web.xml。
项目视图中的 <strong>src</strong> 目录用来保存 Servlet 源代码，<strong>WebContent</strong> 目录用来保存JSP及静态内容，
web.xml则位于 WebContent/WEB-INF/web.xml。但手工编辑 web.xml 比较麻烦，
因此 Lomboz 提供了一套可视化工具用于编辑 web.xml，即最上方的<strong>Depolyment Descriptor</strong>，
里面包含的内容以后会陆续讲解。</p>
<p><strong>理解Servlet</strong></p>
<p>在Project Explorer中打开<strong>Java Resources: src -&gt; Libraries -&gt; Apache Tomcat 5.5 -&gt; servlet-api.jar</strong>
文件，可以看到其中包含两个包：<strong>javax.servlet</strong>和<strong>javax.servlet.http</strong>，
与Servlet有关的类和接口都位于这两个包里面。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-06.png" alt="Servlet API所在的包" title="Servlet API所在的包" width="281" height="306" /></div>

<p>Servlet是一个接口，位于 javax.servlet.Servlet，它规定了每个Servlet所必须实现的方法。
实际应用时我们需要从 javax.servlet.GenericServlet 和 javax.servlet.http.HttpServlet 两个抽象类
继承出自己的Servlet类，并实现所需的功能。这几个类的关系如下（绿色斜体字为抽象类）：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-07.png" alt="Servlet相关类的关系" title="Servlet相关类的关系" width="453" height="342" /></div>

<p>上图中，Servlet依赖于ServletRequest和ServletResponse接口，这两个接口负责为Servlet接受和发送信息。
HttpServlet也类似。</p>
<p><strong>Servlet接口</strong></p>
<p>javax.servlet.Servlet接口包含以下的方法：</p>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>init()</dt>


<dd><strong>void init(ServletConfig config) throws ServletException</strong></dd>

<dd>init方法用于初始化，在Servlet启动时调用。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>service()</dt>


<dd><strong>void service(ServletRequest req, ServiceResponse res) throws ServletException, IOException</strong></dd>

<dd>Servlet通过这个方法，从req获得客户端请求，处理并生成结果，再通过res发送给客户端。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>destroy()</dt>


<dd><strong>void destroy()</strong></dd>

<dd>Servlet销毁时执行的方法。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getServletInfo()</dt>


<dd><strong>String getServletInfo()</strong></dd>

<dd>将Servlet的信息通过字符串返回。</dd></dl>
<dl class="list1" style="padding-left:16px;margin-left:16px"><dt>getServletConfig()</dt>


<dd><strong>ServletConfig getServletConfig()</strong></dd>

<dd>获取包含Servlet各种信息的ServletConfig对象。</dd></dl>
<p>当某个Servlet第一次被请求时，服务器（Servlet容器）会生成该Servlet并调用它的init()方法，
再调用其service()方法处理请求。处理结束后该Servlet会常驻于容器中，下一个请求则不再
重新生成Servlet，而是直接调用常驻的Servlet对象的service()方法。
服务器停止时，会调用该Servlet的destroy()方法。</p>
<p>因此，在Servlet的一个生命周期中，init()和destroy()仅会被调用一次，
而service()则会被调用多次。</p>
<p><strong>GenericServlet抽象类</strong></p>
<p>javax.servlet.GenericServlet为我们实现了Servlet接口的大部分方法，除了service()方法之外。
因此，我们在制作自己的Servlet时，只需要继承GenericServlet并重载service()方法即可。</p>
<p><strong>典型的Servlet示例</strong></p>
<p>下面我们来做一个典型的Servlet。</p>
<p>在eclipse左侧的Project Explorer中，右键单击<strong>Java Resources: src</strong>目录（以后简称<strong>src</strong>目录），
选择<strong>New-&gt;Class</strong>，建立如下所示的类。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-08.png" alt="建立Servlet类" title="建立Servlet类" width="495" height="592" /></div>

<p>包名输入我们要建立的 com.idv2.learnjsp，类名为 HelloServlet，父类为 javax.servlet.http.GenericServlet。
在输入父类名时，你会看到输入框左侧有个小灯泡的图标，这说明可以通过 <strong>Alt-/</strong>键自动补齐，
因此你只需输入 GenericSer 几个字母，然后按 Alt-/ 组合键，系统会自动查找开头为 GenericSer 的类
并补齐剩余部分。</p>
<p>Finish之后eclipse会为我们生成代码框架，我们只需填入实际的处理代码即可。
代码可以从这里下载。</p>
<div class="img_margin" style="text-align:left"><a href="http://tech.idv2.com/wp-content/uploads/2007/09/helloservlet.zip" title="helloservlet.zip(2007/09/14 15:19:48 1.2KB)"><img src="http://tech.idv2.com/wp-content/plugins/wp-pukiwiki/img/attach.gif" width="16" height="16" alt="attach" style="border-width:0px" />helloservlet.zip</a></div>

<p>上述代码是UTF-8编码，如果你直接放到src目录中有可能出现乱码，
这时请选择<strong>Windows-&gt;Preferences...</strong>菜单，选择左侧的<strong>General-&gt;Workspace</strong>，
然后将<strong>Text file encoding</strong>设置为<strong>UTF-8</strong>即可。</p>
<p>代码写好后，从Project Explorer中打开项目的 build 目录，可以看到eclipse自动编译了
HelloServlet.java并生成了 com/idv2/learnjsp/HelloServlet.class 文件。</p>
<p>那么如何在服务器上运行它呢？首先必须要做的就是在配置文件 web.xml 中登记这个Servlet。
刚才我们在建立 HelloServlet 类时，并没有声明它是一个Servlet，这样服务器就无法将它
作为Servlet执行，因此必须先登记，并为它指定一个URL（即Servlet Mapping）。</p>
<p>右键单击<strong>Depolyment Descriptor</strong>中的<strong>Servlets</strong>，选择<strong>New-&gt;Servlet</strong>，出现下面的画面。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-09.png" alt="登记Servlet" title="登记Servlet" width="422" height="429" /></div>

<p>因为我们已经写好了HelloServlet类，因此选中<strong>Use existing Servlet class</strong>，
然后单击右侧的<strong>Browse...</strong>按钮，选择HelloServlet类。下一步。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-10.png" alt="设置Servlet名称和URL映射" title="设置Servlet名称和URL映射" width="422" height="481" /></div>

<p>URL映射是指，浏览器通过哪个URL能访问到这个Servlet。
默认与Servlet名称相同，为了演示，我们这里将他修改为小写的 /helloservlet 。
实际的URL格式为 http://主机名/应用程序名/Servlet的URL映射，
我们这个Servlet的URL就应当是 <a href="http://localhost:8080/LearnJSP/helloservlet">http://localhost:8080/LearnJSP/helloservlet</a>。</p>
<p>单击Finish完成添加Servlet。如果你有兴趣可以打开 WebContent/WEB-INF/web.xml，
可以看到刚才的修改在web.xml中是怎样的结果。</p>
<p>下一步我们需要将它部署到服务器上。打开eclipse下方的<strong>Servet</strong>栏，
可以看到系统中的服务器列表。</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-11.png" alt="Server栏" title="Server栏" width="483" height="87" /></div>

<p>如果你找不到Server栏，请通过主菜单<strong>Window-&gt;Show View-&gt;Others</strong>添加Server栏；
如果你的Server栏中什么都没有，请在Server栏中单击右键然后 <strong>New-&gt;Server</strong>。</p>
<p>右键单击服务器，选择<strong>Add and Remove Projects...</strong>，将 LearnJSP项目添加到服务器上。
添加之后的结果如下：</p>
<div class="img_margin" style="text-align:left"><img src="http://tech.idv2.com/wp-content/uploads/2007/09/servlet-basic-12.png" alt="Server栏" title="Server栏" width="476" height="92" /></div>

<p>最后右键单击服务器，选择<strong>Start</strong>，片刻即可看到在Console栏中输出大量的信息，服务器启动了。
打开浏览器，访问 <a href="http://localhost:8080/LearnJSP/helloservlet">http://localhost:8080/LearnJSP/helloservlet</a>。
如果能看到“Hello Servlet”的输出，则恭喜你，第一个Servlet成功运行了！</p>
<p>刷新浏览器页面几次，然后回到eclipse下侧的Console栏，可以看到下面的字样：</p>
<pre>init() was called.
service() was called.
service() was called.
service() was called.</pre>
<p>这是我们加入的调试信息。这些信息说明了Servlet的一个生命周期中
init、service和destroy函数的执行过程。
如果在Server栏中停止服务器，那么你可以在Console栏中的信息中找到 destroy() 函数的执行。</p>
<p><strong>结语</strong></p>
<p>这一节重点结合Lomboz的用法，讲述了Servlet的基本原理和最简单的Servlet的编写方法。
以后的内容可能就不会这么详细地说明Lomboz的用法了。</p>
<!-- end Pukiwiki generated code-->
]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2007/09/14/servlet-basic/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Servlet/JSP学习笔记(3)-Lomboz介绍+安装方法</title>
		<link>http://tech.idv2.com/2007/09/13/install-lomboz/</link>
		<comments>http://tech.idv2.com/2007/09/13/install-lomboz/#comments</comments>
		<pubDate>Wed, 12 Sep 2007 16:44:12 +0000</pubDate>
		<dc:creator>charlee</dc:creator>
				<category><![CDATA[编程开发]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[lomboz]]></category>

		<guid isPermaLink="false">http://tech.idv2.com/2007/09/13/install-lomboz/</guid>
		<description><![CDATA[<!-- begin Pukiwiki generated code--><p>在<a href="http://tech.idv2.com/2007/09/12/how-to-install-eclipse-and-tomcat/">Servlet/JSP学习笔记(1)-tomcat和eclipse的安装</a>中，
我介绍了eclipse和tomcatPlugin的安装和配置方法。
但今天发现，使用tomcatPlugin创建项目时，不会自动生成web.xml，需要手工编辑，这多少有些不方便。
（关于web.xml的简单介绍参考<a href="http://tech.idv2.com/2007/09/12/basic-about-servlet-and-jsp/">这里</a>。）</p>
<p>实际上，开发和调试Servlet/JSP程序时，一个叫做Lomboz的插件更为强大、更好用。
Lomboz其实是一个开发J2EE程序的强大插件，Servlet/JSP只是小菜一碟而已。</p>
<p>下面就来介绍一下Lomboz的安装方法。关于 eclipse 和 Tomcat 的安装请参考
<a href="http://tech.idv2.com/2007/09/12/how-to-install-eclipse-and-tomcat/">前一篇文章</a>。</p>
<!-- end Pukiwiki generated code--><span id="more-467"></span><!-- begin Pukiwiki generated code--><p><strong>安装</strong></p>
<p>Lomboz可以从<a href="http://forge.objectweb.org/projects/lomboz">官方主页</a>上下载。
选择对应于你的 eclipse 版本的lomboz，我用的是eclipse 3.2.2，所以安装了
Lomboz for Eclipse 3.2。</p>
<p>点击下载链接进入后会发现有多个文件，应该下哪一个呢？
最原始的形如 org.objectweb.lomboz-R-3.2.2-200706042126.zip 的，
是仅有lomboz的独立安装包；带有all-in-one的是连eclipse都包含在内的一站式文件；
带有prereqs字样的是lomboz和它依赖的包。Lomboz运行时需要另外一些插件的支持，
因此仅安装原始版本的lomboz是不能运行的。推荐新手下载prereqs版本，
只要安装就能用了。再懒一些的可以直接用all-in-one。</p>
<p>安装很简单，可以将其直接解压缩到eclipse目录下，也可以通过links目录安装。
关于links目录的安装方法，<a href="http://tech.idv2.com/2007/09/12/how-to-install-eclipse-and-tomcat/">上一篇文章</a>
已经提到过，这里不再重述。只说一点，lomboz内的文件层次结构很深，
如果直接解压到 D:\eclipse\plugins-dir 下，WinRAR和7-zip都会报错，说目录名太长。
因此只能先将其解压到根目录下，再移动到 D:\eclipse\plugins-dir 中。</p>
<p>装完Lomboz之后，tomcatPlugin就可以卸载了。只要删掉links目录下的相关文件即可。</p>
<p>启动eclipse，在<strong>Window-&gt;Preferences</strong>中看到左侧树形目录中多出了“Web and XML”、
“Web Services”、“XDocklet”等菜单，说明安装成功了。</p>
<p><strong>配置</strong></p>
<p>在<strong>Window-&gt;Preferences</strong>中打开<strong>Server-&gt;Installed Runtimes</strong>项，
如果右边列表是空的，则单击<strong>Add...</strong>，选择服务器为Tomcat，版本为你安装的版本，
Next之后设置好服务器路径。</p>
<!-- end Pukiwiki generated code-->
]]></description>
			<content:encoded><![CDATA[<!-- begin Pukiwiki generated code--><p>在<a href="http://tech.idv2.com/2007/09/12/how-to-install-eclipse-and-tomcat/">Servlet/JSP学习笔记(1)-tomcat和eclipse的安装</a>中，
我介绍了eclipse和tomcatPlugin的安装和配置方法。
但今天发现，使用tomcatPlugin创建项目时，不会自动生成web.xml，需要手工编辑，这多少有些不方便。
（关于web.xml的简单介绍参考<a href="http://tech.idv2.com/2007/09/12/basic-about-servlet-and-jsp/">这里</a>。）</p>
<p>实际上，开发和调试Servlet/JSP程序时，一个叫做Lomboz的插件更为强大、更好用。
Lomboz其实是一个开发J2EE程序的强大插件，Servlet/JSP只是小菜一碟而已。</p>
<p>下面就来介绍一下Lomboz的安装方法。关于 eclipse 和 Tomcat 的安装请参考
<a href="http://tech.idv2.com/2007/09/12/how-to-install-eclipse-and-tomcat/">前一篇文章</a>。</p>
<!-- end Pukiwiki generated code--><span id="more-467"></span><!-- begin Pukiwiki generated code--><p><strong>安装</strong></p>
<p>Lomboz可以从<a href="http://forge.objectweb.org/projects/lomboz">官方主页</a>上下载。
选择对应于你的 eclipse 版本的lomboz，我用的是eclipse 3.2.2，所以安装了
Lomboz for Eclipse 3.2。</p>
<p>点击下载链接进入后会发现有多个文件，应该下哪一个呢？
最原始的形如 org.objectweb.lomboz-R-3.2.2-200706042126.zip 的，
是仅有lomboz的独立安装包；带有all-in-one的是连eclipse都包含在内的一站式文件；
带有prereqs字样的是lomboz和它依赖的包。Lomboz运行时需要另外一些插件的支持，
因此仅安装原始版本的lomboz是不能运行的。推荐新手下载prereqs版本，
只要安装就能用了。再懒一些的可以直接用all-in-one。</p>
<p>安装很简单，可以将其直接解压缩到eclipse目录下，也可以通过links目录安装。
关于links目录的安装方法，<a href="http://tech.idv2.com/2007/09/12/how-to-install-eclipse-and-tomcat/">上一篇文章</a>
已经提到过，这里不再重述。只说一点，lomboz内的文件层次结构很深，
如果直接解压到 D:\eclipse\plugins-dir 下，WinRAR和7-zip都会报错，说目录名太长。
因此只能先将其解压到根目录下，再移动到 D:\eclipse\plugins-dir 中。</p>
<p>装完Lomboz之后，tomcatPlugin就可以卸载了。只要删掉links目录下的相关文件即可。</p>
<p>启动eclipse，在<strong>Window-&gt;Preferences</strong>中看到左侧树形目录中多出了“Web and XML”、
“Web Services”、“XDocklet”等菜单，说明安装成功了。</p>
<p><strong>配置</strong></p>
<p>在<strong>Window-&gt;Preferences</strong>中打开<strong>Server-&gt;Installed Runtimes</strong>项，
如果右边列表是空的，则单击<strong>Add...</strong>，选择服务器为Tomcat，版本为你安装的版本，
Next之后设置好服务器路径。</p>
<!-- end Pukiwiki generated code-->
]]></content:encoded>
			<wfw:commentRss>http://tech.idv2.com/2007/09/13/install-lomboz/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
