176142998

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  116 Posts :: 0 Stories :: 45 Comments :: 0 Trackbacks

#

(1)模板 + 数据模型 = 输出

FreeMarker基于设计者和程序员是具有不同专业技能的不同个体的观念他们是分工劳动的:
设计者专注于表示——创建HTML文件、图片、Web页面的其它可视化方面;
程序员创建系统,生成设计页面要显示的数据。
经常会遇到的问题是:在Web页面(或其它类型的文档)中显示的信息在设计页面时是无效的,是基于动态数据的。在这里,你可以在HTML(或其它要输出的文本)中加入一些特定指令,FreeMarker会在输出页面给最终用户时,用适当的数据替代这些代码。

下面是一个例子:

<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>Welcome ${user}!</h1>
<p>Our latest product:
<a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>
这个例子是在简单的HTML中加入了一些由${…}包围的特定代码,这些特定代码是FreeMarker的指令,而包含FreeMarker的指令的文件就称为模板(Template)。
至于user、latestProduct.url和latestProduct.name来自于数据模型(data model)。
数据模型由程序员编程来创建,向模板提供变化的信息,这些信息来自于数据库、文件,甚至于在程序中直接生成。
模板设计者不关心数据从那儿来,只知道使用已经建立的数据模型。

下面是一个可能的数据模型:

(root)
|
+- user = "Big Joe"
|
+- latestProduct
|
+- url = "products/greenmouse.html"
|
+- name = "green mouse"
数据模型类似于计算机的文件系统,latestProduct可以看作是目录。

2、数据模型

(1)基础

在快速入门中介绍了在模板中使用的三种基本对象类型:scalars、hashes 和sequences,其实还可以有其它更多的能力:

  • scalars:存储单值
  • hashes:充当其它对象的容器,每个都关联一个唯一的查询名字
  • sequences:充当其它对象的容器,按次序访问
  • 方法:通过传递的参数进行计算,以新对象返回结果
  • 用户自定义FTL标记:宏和变换器

通常每个变量只具有上述的一种能力,但一个变量可以具有多个上述能力,如下面的例子:

(root)
|
+- mouse = "Yerri"
|
+- age = 12
|
+- color = "brown">
mouse既是scalars又是hashes,将上面的数据模型合并到下面的模板:
${mouse}       <#-- use mouse as scalar -->
${mouse.age}   <#-- use mouse as hash -->
${mouse.color} <#-- use mouse as hash -->
输出结果是:
Yerri
12
brown

(2)Scalar变量

Scalar变量存储单值,可以是:

  • 字符串:简单文本,在模板中使用引号(单引号或双引号)括起
  • 数字:在模板中直接使用数字值
  • 日期:存储日期/时间相关的数据,可以是日期、时间或日期-时间(Timestamp);通常情况,日期值由程序员加到数据模型中,设计者只需要显示它们
  • 布尔值:true或false,通常在<#if …>标记中使用

(3)hashes 、sequences和集合

有些变量不包含任何可显示的内容,而是作为容器包含其它变量,者有两种类型:

  • hashes:具有一个唯一的查询名字和它包含的每个变量相关联
  • sequences:使用数字和它包含的每个变量相关联,索引值从0开始

集合变量通常类似sequences,除非无法访问它的大小和不能使用索引来获得它的子变量;集合可以看作只能由<#list …>指令使用的受限sequences

(4)方法

方法变量通常是基于给出的参数计算值。

下面的例子假设程序员已经将方法变量avg放到数据模型中,用来计算数字平均值:

The average of 3 and 5 is: ${avg(3, 5)}
The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
The average of the price of python and elephant is:
${avg(animals.python.price, animals.elephant.price)}

(5)宏和变换器

宏和变换器变量是用户自定义指令(自定义FTL标记),会在后面讲述这些高级特性

(6)节点

节点变量表示为树型结构中的一个节点,通常在XML处理中使用,会在后面的专门章节中讲

3、模板

(1)整体结构

模板使用FTL(FreeMarker模板语言)编写,是下面各部分的一个组合:

  • 文本:直接输出
  • Interpolation:由${和},或#{和}来限定,计算值替代输出
  • FTL标记:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出
  • 注释:由<#--和-->限定,不会输出

下面是以一个具体模板例子:

<html>
<head>
<title>Welcome!</title>
</head>
<body>
<#-- Greet the user with his/her name -->
<h1>Welcome ${user}!</h1>
<p>We have these animals:
<ul>
<#list animals as being>
<li>${being.name} for ${being.price} Euros
</#list>
</ul>
</body>
</html>

注意事项:

  • FTL区分大小写,所以list是正确的FTL指令,而List不是;${name}和${NAME}是不同的
  • Interpolation只能在文本中使用
  • FTL标记不能位于另一个FTL标记内部,例如:
<#if <#include 'foo'>='bar'>...</if>
  • 注释可以位于FTL标记和Interpolation内部,如下面的例子:
<h1>Welcome ${user <#-- The name of user -->}!</h1>
<p>We have these animals:
<ul>
<#list <#-- some comment... --> animals as <#-- again... --> being>
...
  • 余的空白字符会在模板输出时移除

(2)指令

在FreeMarker中,使用FTL标记引用指令。有三种FTL标记,这和HTML标记是类似的:

  • 开始标记:<#directivename parameters>
  • 结束标记:</#directivename>
  • 空内容指令标记:<#directivename parameters/>

有两种类型的指令:预定义指令和用户定义指令。

用户定义指令要使用@替换#,如<@mydirective>...</@mydirective>(会在后面讲述)。

FTL标记不能够交叉,而应该正确的嵌套,如下面的代码是错误的:

<ul>
<#list animals as being>
<li>${being.name} for ${being.price} Euros
<#if use = "Big Joe">
(except for you)
</#list>
</#if> <#-- WRONG! -->
</ul>
如果使用不存在的指令,FreeMarker不会使用模板输出,而是产生一个错误消息。

FreeMarker会忽略FTL标记中的空白字符,如下面的例子:

<#list
animals       as
being
>
${being.name} for ${being.price} Euros
</#list    >
但是,<、</和指令之间不允许有空白字符。

(3)表达式

直接指定值

  • 字符串
使用单引号或双引号限定

如果包含特殊字符需要转义,如下面的例子:

${"It's \"quoted\" and
this is a backslash: \\"}
${'It\'s "quoted" and
this is a backslash: \\'}
输出结果是:
It's "quoted" and
this is a backslash: \
It's "quoted" and
this is a backslash: \
下面是支持的转义序列:

转义序列 含义
\" 双引号(u0022)
\' 单引号(u0027)

反斜杠(u005C)
\n 换行(u000A)
\r Return (u000D)
\t Tab (u0009)
\b Backspace (u0008)
\f Form feed (u000C)
\l <
\g >
\a &
\{ {
\xCode 4位16进制Unicode代码

有一类特殊的字符串称为raw字符串,被认为是纯文本,其中的\和{等不具有特殊含义,该类字符串在引号前面加r,下面是一个例子:

${r"${foo}"}
${r"C:\foo\bar"}
输出的结果是:
${foo}
C:\foo\bar
  • 数字

直接输入,不需要引号

精度数字使用“.”分隔,不能使用分组符号

目前版本不支持科学计数法,所以“1E3”是错误的

不能省略小数点前面的0,所以“.5”是错误的

数字8、+8、08和8.00都是相同的

  • 布尔值

true和false,不使用引号

  • 序列

由逗号分隔的子变量列表,由方括号限定,下面是一个例子:

<#list ["winter", "spring", "summer", "autumn"] as x>
${x}
</#list>
输出的结果是:
winter
spring
summer
autumn
列表的项目是表达式,所以可以有下面的例子:
[2 + 2, [1, 2, 3, 4], "whatnot"]
可以使用数字范围定义数字序列,例如2..5等同于[2, 3, 4, 5],但是更有效率,注意数字范围没有方括号

可以定义反递增的数字范围,如5..2

  • 散列(hash)
由逗号分隔的键/值列表,由大括号限定,键和值之间用冒号分隔,下面是一个例子:
{"name":"green mouse", "price":150}
键和值都是表达式,但是键必须是字符串

获取变量

  • 顶层变量: ${variable},变量名只能是字母、数字、下划线、$、@和#的组合,且不能以数字开头
  • 从散列中获取数据

可以使用点语法或方括号语法,假设有下面的数据模型:

(root)
|
+- book
|   |
|   +- title = "Breeding green mouses"
|   |
|   +- author
|       |
|       +- name = "Julia Smith"
|       |
|       +- info = "Biologist, 1923-1985, Canada"
|
+- test = "title"
下面都是等价的:
book.author.name
book["author"].name
book.author.["name"]
book["author"]["name"]
使用点语法,变量名字有顶层变量一样的限制,但方括号语法没有该限制,因为名字是任意表达式的结果
  • 从序列获得数据:和散列的方括号语法语法一样,只是方括号中的表达式值必须是数字;注意:第一个项目的索引是0

序列片断:使用[startIndex..endIndex]语法,从序列中获得序列片断(也是序列);startIndex和endIndex是结果为数字的表达式

  • 特殊变量:FreeMarker内定义变量,使用.variablename语法访问

字符串操作

  • Interpolation(或连接操作)

可以使用${..}(或#{..})在文本部分插入表达式的值,例如:

${"Hello ${user}!"}
${"${user}${user}${user}${user}"}
可以使用+操作符获得同样的结果
${"Hello " + user + "!"}
${user + user + user + user}
${..}只能用于文本部分,下面的代码是错误的:
<#if ${isBig}>Wow!</#if>
<#if "${isBig}">Wow!</#if>
应该写成:
<#if isBig>Wow!</#if>
  • 子串

例子(假设user的值为“Big Joe”):

${user[0]}${user[4]}
${user[1..4]}
结果是(注意第一个字符的索引是0):
BJ
ig J
序列操作
  • 连接操作:和字符串一样,使用+,下面是一个例子:
<#list ["Joe", "Fred"] + ["Julia", "Kate"] as user>
- ${user}
</#list>
输出结果是:
- Joe
- Fred
- Julia
- Kate
散列操作
  • 连接操作:和字符串一样,使用+,如果具有相同的key,右边的值替代左边的值,例如:
<#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}>
- Joe is ${ages.Joe}
- Fred is ${ages.Fred}
- Julia is ${ages.Julia}
输出结果是:
- Joe is 30
- Fred is 25
- Julia is 18
算术运算
  • +、-、×、/、%,下面是一个例子:
${x * x - 100}
${x / 2}
${12 % 10}
输出结果是(假设x为5):
-75
2.5
2
操作符两边必须是数字,因此下面的代码是错误的:
${3 * "5"} <#-- WRONG! -->
使用+操作符时,如果一边是数字,一边是字符串,就会自动将数字转换为字符串,例如:
${3 + "5"}
输出结果是:
35
使用内建的int(后面讲述)获得整数部分,例如:
${(x/2)?int}
${1.1?int}
${1.999?int}
${-1.1?int}
${-1.999?int}
输出结果是(假设x为5):
2
1
1
-1
-1
  • 比较操作符

使用=(或==,完全相等)测试两个值是否相等,使用!= 测试两个值是否不相等

=和!=两边必须是相同类型的值,否则会产生错误,例如<#if 1 = "1">会引起错误

Freemarker是精确比较,所以对"x"、"x "和"X"是不相等的

对数字和日期可以使用<、<=、>和>=,但不能用于字符串

由于Freemarker会将>解释成FTL标记的结束字符,所以对于>和>=可以使用括号来避免这种情况,例如<#if (x > y)>

另一种替代的方法是,使用lt、lte、gt和gte来替代<、<=、>和>=

  • 逻辑操作符

&&(and)、||(or)、!(not),只能用于布尔值,否则会产生错误

例子:

<#if x < 12 && color = "green">
We have less than 12 things, and they are green.
</#if>
<#if !hot> <#-- here hot must be a boolean -->
It's not hot.
</#if>
  • 内建函数

内建函数的用法类似访问散列的子变量,只是使用“?”替代“.”,下面列出常用的一些函数

    • 字符串使用的:

html:对字符串进行HTML编码

cap_first:使字符串第一个字母大写

lower_case:将字符串转换成小写

upper_case:将字符串转换成大写

trim:去掉字符串前后的空白字符

    • 序列使用的:

size:获得序列中元素的数目

    • 数字使用的:

int:取得数字的整数部分(如-1.9?int的结果是-1)

例子(假设test保存字符串"Tom & Jerry"):

${test?html}
${test?upper_case?html}
输出结果是:
Tom &amp; Jerry
TOM &amp; JERRY
  • 操作符优先顺序

操作符组 操作符
后缀 [subvarName] [subStringRange] . (methodParams)
一元 +expr、-expr、!
内建 ?
乘法 *、 / 、%
加法 +、-
关系 <、>、<=、>=(lt、lte、gt、gte)
相等 ==(=)、!=
逻辑and &&
逻辑or 双竖线
数字范围 ..

(4)Interpolation

Interpolation有两种类型:

  1. 通用Interpolation:${expr}
  1. 数字Interpolation:#{expr}或#{expr; format}

注意:Interpolation只能用于文本部分

  • 通用Interpolation

插入字符串值:直接输出表达式结果

插入数字值:根据缺省格式(由#setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string格式化单个Interpolation,下面是一个例子:

<#setting number_format="currency"/>
<#assign answer=42/>
${answer}
${answer?string}  <#-- the same as ${answer} -->
${answer?string.number}
${answer?string.currency}
${answer?string.percent}
输出结果是:
$42.00
$42.00
42
$42.00
4,200%
插入日期值:根据缺省格式(由#setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string格式化单个Interpolation,下面是一个使用格式模式的例子:
${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")}
${lastUpdated?string("EEE, MMM d, ''yy")}
${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")}
输出的结果类似下面的格式:
2003-04-08 21:24:44 Pacific Daylight Time
Tue, Apr 8, '03
Tuesday, April 08, 2003, 09:24:44 PM (PDT)
插入布尔值:根据缺省格式(由#setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string格式化单个Interpolation,下面是一个例子:
<#assign foo=true/>
${foo?string("yes", "no")}
输出结果是:
yes
  • 数字Interpolation的#{expr; format}形式可以用来格式化数字,format可以是:

mX:小数部分最小X位

MX:小数部分最大X位

例子:

<#-- If the language is US English the output is: -->
<#assign x=2.582/>
<#assign y=4/>
#{x; M2}   <#-- 2.58 -->
#{y; M2}   <#-- 4    -->
#{x; m1}   <#-- 2.6 -->
#{y; m1}   <#-- 4.0 -->
#{x; m1M2} <#-- 2.58 -->
#{y; m1M2} <#-- 4.0  -->

4、杂项

(1)用户定义指令

宏和变换器变量是两种不同类型的用户定义指令,它们之间的区别是宏是在模板中使用macro指令定义,而变换器是在模板外由程序定义,这里只介绍宏

  • 基本用法

宏是和某个变量关联的模板片断,以便在模板中通过用户定义指令使用该变量,下面是一个例子:

<#macro greet>
<font size="+2">Hello Joe!</font>
</#macro>
作为用户定义指令使用宏变量时,使用@替代FTL标记中的#
<@greet></@greet>
如果没有体内容,也可以使用:
<@greet/>
  • 参数

在macro指令中可以在宏变量之后定义参数,如:

<#macro greet person>
<font size="+2">Hello ${person}!</font>
</#macro>
可以这样使用这个宏变量:
<@greet person="Fred"/> and <@greet person="Batman"/>
输出结果是:
  <font size="+2">Hello Fred!</font>
and   <font size="+2">Hello Batman!</font>

宏的参数是FTL表达式,所以下面的代码具有不同的意思:

<@greet person=Fred/>
这意味着将Fred变量的值传给person参数,该值不仅是字符串,还可以是其它类型,甚至是复杂的表达式

可以有多参数,下面是一个例子:

<#macro greet person color>
<font size="+2" color="${color}">Hello ${person}!</font>
</#macro>
可以这样使用该宏变量:
<@greet person="Fred" color="black"/>
其中参数的次序是无关的,因此下面是等价的:
<@greet color="black" person="Fred"/>
只能使用在macro指令中定义的参数,并且对所有参数赋值,所以下面的代码是错误的:
<@greet person="Fred" color="black" background="green"/>
<@greet person="Fred"/>
可以在定义参数时指定缺省值,如:
<#macro greet person color="black">
<font size="+2" color="${color}">Hello ${person}!</font>
</#macro>
这样<@greet person="Fred"/>就正确了

宏的参数是局部变量,只能在宏定义中有效

  • 嵌套内容

用户定义指令可以有嵌套内容,使用<#nested>指令执行指令开始和结束标记之间的模板片断

例子:

<#macro border>
<table border=4 cellspacing=0 cellpadding=4><tr><td>
<#nested>
</tr></td></table>
</#macro>
这样使用该宏变量:
<@border>The bordered text</@border>
输出结果:
  <table border=4 cellspacing=0 cellpadding=4><tr><td>
The bordered text
</tr></td></table>

<#nested>指令可以被多次调用,例如:

<#macro do_thrice>
<#nested>
<#nested>
<#nested>
</#macro>
<@do_thrice>
Anything.
</@do_thrice>
输出结果:
  Anything.
Anything.
Anything.
嵌套内容可以是有效的FTL,下面是一个有些复杂的例子: <@border> <ul> <@do_thrice> <li><@greet person="Joe"/> </@do_thrice> </ul> </@border> }}} 输出结果:
  <table border=4 cellspacing=0 cellpadding=4><tr><td>
<ul>
<li><font size="+2">Hello Joe!</font>
<li><font size="+2">Hello Joe!</font>
<li><font size="+2">Hello Joe!</font>
</ul>
</tr></td></table>
宏定义中的局部变量对嵌套内容是不可见的,例如:
<#macro repeat count>
<#local y = "test">
<#list 1..count as x>
${y} ${count}/${x}: <#nested>
</#list>
</#macro>
<@repeat count=3>${y?default("?")} ${x?default("?")} ${count?default("?")}</@repeat>
输出结果:
    test 3/1: ? ? ?
test 3/2: ? ? ?
test 3/3: ? ? ?
  • 在宏定义中使用循环变量

用户定义指令可以有循环变量,通常用于重复嵌套内容,基本用法是:作为nested指令的参数传递循环变量的实际值,而在调用用户定义指令时,在<@…>开始标记的参数后面指定循环变量的名字

例子:

<#macro repeat count>
<#list 1..count as x>
<#nested x, x/2, x==count>
</#list>
</#macro>
<@repeat count=4 ; c, halfc, last>
${c}. ${halfc}<#if last> Last!</#if>
</@repeat>
输出结果:
  1. 0.5
2. 1
3. 1.5
4. 2 Last!

指定的循环变量的数目和用户定义指令开始标记指定的不同不会有问题

调用时少指定循环变量,则多指定的值不可见

调用时多指定循环变量,多余的循环变量不会被创建

(2)在模板中定义变量

在模板中定义的变量有三种类型:

  • plain变量:可以在模板的任何地方访问,包括使用include指令插入的模板,使用assign指令创建和替换
  • 局部变量:在宏定义体中有效,使用local指令创建和替换
  • 循环变量:只能存在于指令的嵌套内容,由指令(如list)自动创建

宏的参数是局部变量,而不是循环变量;局部变量隐藏(而不是覆盖)同名的plain变量;循环变量隐藏同名的局部变量和plain变量,下面是一个例子:

<#assign x = "plain">
1. ${x}  <#-- we see the plain var. here -->
<@test/>
6. ${x}  <#-- the value of plain var. was not changed -->
<#list ["loop"] as x>
7. ${x}  <#-- now the loop var. hides the plain var. -->
<#assign x = "plain2"> <#-- replace the plain var, hiding does not mater here -->
8. ${x}  <#-- it still hides the plain var. -->
</#list>
9. ${x}  <#-- the new value of plain var. -->
<#macro test>
2. ${x}  <#-- we still see the plain var. here -->
<#local x = "local">
3. ${x}  <#-- now the local var. hides it -->
<#list ["loop"] as x>
4. ${x}  <#-- now the loop var. hides the local var. -->
</#list>
5. ${x}  <#-- now we see the local var. again -->
</#macro>
输出结果:
1. plain
2. plain
3. local
4. loop
5. local
6. plain
7. loop
8. loop
9. plain2

内部循环变量隐藏同名的外部循环变量,如:

<#list ["loop 1"] as x>
${x}
<#list ["loop 2"] as x>
${x}
<#list ["loop 3"] as x>
${x}
</#list>
${x}
</#list>
${x}
</#list>
输出结果:
  loop 1
loop 2
loop 3
loop 2
loop 1
模板中的变量会隐藏(而不是覆盖)数据模型中同名变量,如果需要访问数据模型中的同名变量,使用特殊变量global,下面的例子假设数据模型中的user的值是Big Joe:
<#assign user = "Joe Hider">
${user}          <#-- prints: Joe Hider -->
${.globals.user} <#-- prints: Big Joe -->

(3)名字空间

通常情况,只使用一个名字空间,称为主名字空间

为了创建可重用的宏、变换器或其它变量的集合(通常称库),必须使用多名字空间,其目的是防止同名冲突

  • 创建库

下面是一个创建库的例子(假设保存在lib/my_test.ftl中):

<#macro copyright date>
<p>Copyright (C) ${date} Julia Smith. All rights reserved.
<br>Email: ${mail}</p>
</#macro>
<#assign mail = "jsmith@acme.com">
使用import指令导入库到模板中,Freemarker会为导入的库创建新的名字空间,并可以通过import指令中指定的散列变量访问库中的变量:
<#import "/lib/my_test.ftl" as my>
<#assign mail="fred@acme.com">
<@my.copyright date="1999-2002"/>
${my.mail}
${mail}
输出结果:
  <p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.
<br>Email: jsmith@acme.com</p>
jsmith@acme.com
fred@acme.com
可以看到例子中使用的两个同名变量并没有冲突,因为它们位于不同的名字空间

可以使用assign指令在导入的名字空间中创建或替代变量,下面是一个例子:

<#import "/lib/my_test.ftl" as my>
${my.mail}
<#assign mail="jsmith@other.com" in my>
${my.mail}
输出结果:
jsmith@acme.com
jsmith@other.com
数据模型中的变量任何地方都可见,也包括不同的名字空间,下面是修改的库:
<#macro copyright date>
<p>Copyright (C) ${date} ${user}. All rights reserved.</p>
</#macro>
<#assign mail = "${user}@acme.com">
假设数据模型中的user变量的值是Fred,则下面的代码:
<#import "/lib/my_test.ftl" as my>
<@my.copyright date="1999-2002"/>
${my.mail}
输出结果:
  <p>Copyright (C) 1999-2002 Fred. All rights reserved.</p>
Fred@acme.com
posted @ 2008-08-12 14:14 飞飞 阅读(212) | 评论 (0)编辑 收藏

<a href="javascript:void(window.open('1.htm','_blank','toolbar=no,scrollbar=no,top=50,left=50,width=100,height=100'));" >Open 1.htm</a>

<a href="javascript: var win=window.open
('1.htm','_blank','toolbar=no,scrollbar=no,top=50,left=50,width=100,height=100')" >Open
1.htm</a>
最好。
<a href="#" onclick="window.open('1.htm','_blank','toolbar=no,scrollbar=no,top=50,left=50,width=100,height=100')" >Open 1.htm</a>
点击后,原窗口的联接地址会发生变化,加上了#,感觉不太好:)虽然也能实现功能
posted @ 2008-08-11 18:44 飞飞 阅读(965) | 评论 (2)编辑 收藏

视图解析器的一些属性

<bean id="viewResolver"

      class="org.springframework.web.servlet.view.InternalResourceViewResolver">

    <property name="exposeSpringMacroHelpers" value="true"/>

    <property name="requestContextAttribute" value="rc"/>

    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>

    <property name="prefix" value="/"/>

    <property name="suffix" value=".jsp"/>

</bean>

在视图解析器的定义中,“exposeSpringMacroHelpers”设置是否通过Spring的宏库暴露一个RequestContext(名为springBindRequestContext)供外部使用,默认值为false。它暴露了处理表单和验证错误信息的宏操作;

requestContextAttribute”把SpringRequestContext对象暴露为变量rc。利用${rc.contextPath}来获取应用程序的contextPath(也就是/MyUsers);利用${rc.getMessage("user.name")}读取/WEB-INF/classes/messages.properties本地化信息。此对象对于那些不访问serlvet请求的View技术(也就是VelocityFreeMarker模板)来说是必不可少的。

还有一些属性:

exposeRequestAttributes:默认值false,设置是否所有的request属性在与模板进行合并之前添加到model中。(可以理解为request范围内包含的所有对象,而不是一个真正的Request对象。)

exposeSessionAttributes:默认值false,设置是否所有的session属性在与模板进行合并之前添加到model中。(理解同上)

posted @ 2008-08-11 17:20 飞飞 阅读(461) | 评论 (0)编辑 收藏

Step 1:配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>


    
<display-name>springapp</display-name>
        
    
<servlet>
        
<servlet-name>springMVC</servlet-name>
        
<servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        
</servlet-class>
        
<load-on-startup>1</load-on-startup>
    
</servlet>

    
<servlet-mapping>
        
<servlet-name>springMVC</servlet-name>
        
<url-pattern>/page/*</url-pattern>
    
</servlet-mapping>

</web-app>
servlet-mapping定义所有以/page/开头的url请求都会被spring 的DispatcherServlet处理转发。默认情况下DispatcherServlet会读取<servlet-name>-servlet.xml文件的配置信息初始化,该文件中urlMapping的定义决定当前请求转发给哪个controller来处理。

Step2:
定义/WEB-INF/springMVC-servlet.xml
 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    
<!-- 方法名解析器 -->
    
<bean id="InternalPathMethodNameResolver"
        class
="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver" />
        
    
<!-- 视图解析器 -->
    
<bean id="viewResolver"
        class
="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
<property name="viewClass">
            
<value>org.springframework.web.servlet.view.JstlView</value>
        
</property>
    
</bean>
    
    
<bean id="controller" class="com.controller.IndexController">
        
<property name="methodNameResolver">
            
<ref bean="InternalPathMethodNameResolver" />
        
</property>
    
</bean>

    
<bean id="urlMapping"
        class
="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        
<property name="mappings">
            
<props>
                
<prop key="/controller/*">controller</prop>
            
</props>
        
</property>
    
</bean>
</beans>
urlMapping定义/controller/开头的url请求由名字为controller的控制器来处理,因为是多动作处理器,所以要定义MethodNameResolver来告诉springMVC应该调用controller的哪个方法,这里用的是InternalPathMethodNameResolver,该方法名解释器会把整个URL中最后一个"/"和最后一个"."之间的部分作为要调用的方法名

Step3:定义controller类并继承MultiActionController 
package com.controller;

import
 java.io.IOException;
import
 java.util.HashMap;
import
 java.util.Map;

import
 javax.servlet.ServletException;
import
 javax.servlet.http.HttpServletRequest;
import
 javax.servlet.http.HttpServletResponse;

import
 org.springframework.web.servlet.ModelAndView;
import
 org.springframework.web.servlet.mvc.multiaction.MultiActionController;

public class IndexController extends MultiActionController 
{
    
    
public
 ModelAndView method1(HttpServletRequest request,
            HttpServletResponse respnose) 
throws ServletException, IOException 
{
        Map model 
= new
 HashMap();
        model.put(
"message""你调用的是方法1"
);
        
return new ModelAndView("/index.jsp""model"
, model);
    }

    
    
public ModelAndView method2(HttpServletRequest request,
            HttpServletResponse respnose) 
throws ServletException, IOException 
{
        Map model 
= new
 HashMap();
        model.put(
"message""你调用的是方法2"
);
        
return new ModelAndView("/index.jsp""model"
, model);
    }

}


通过配置文件,访问上面这个controller中某个方法的url即为:localhost:8080/page/controller/方法名


Step4:/index.jsp
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt"%> 


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head></head>  
<body>

    
<c:out value="${model.message}"/>
</body>
</html>
因为InternalPathMethodNameResolver方法名解释器会把整个URL中最后一个"/"和最后一个"."之间的部分作为要调用的方法名,所以你可以在这个URL后面加任意文件格式的后缀,比如:
localhost:8080/page/controller/method1.jsp

localhost:8080/page/controller/method2.html
很爽吧,和真实的URL地址一样。


另:开发环境:MyEclipse5.0M2+tomcat5.5
  需要用到spring.jar和jstl.jar两个包。
posted @ 2008-08-11 16:02 飞飞 阅读(206) | 评论 (0)编辑 收藏

servlet 2.5的写法
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd"
version="2.5">

别以为看到这里就结束了,很可惜地告诉你,这段代码是错误的。不信你尝试打开一下这个链接http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd,你会发现是no page found。

那为什么tomcat6的范例程序能够工作呢,那是因为在tomcat6的lib里面,已经存在这个文件,所以也不需要从网络上面抓取。其实你按照这个web.xml写了servlet 2.5的程序,在tomcat6里面也是可以运行的。

可是当我使用eclipse+xmlbuddy的时候,问题就出来了,因为web-app_2_5.xsd一直不能下载,xmlbuddy一直报错,并且没有语法提示功能。通过搜索,我发现了web-app_2_5.xsd的真实地址其实是http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd,而它的namespace是http://java.sun.com/xml/ns/javaee,于是代码应该改成:

    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">

留意一下不同的部分,其实是因为sun把j2ee改名为javaee。

ps,另外附上servlet 2.4的写法

    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
posted @ 2008-08-11 10:13 飞飞 阅读(528) | 评论 (0)编辑 收藏

1. 实体(表)的命名
  1) 表以名词或名词短语命名,确定表名是采用复数还是单数形式,此外给表的别名定义简单规则(比方说,如果表名是一个单词,别名就取单词的前4 个字母;如果表名是两个单词,就各取两个单词的前两个字母组成4 个字母长的别名;如果表的名字由3 个单词组成,从头两个单词中各取一个然后从最后一个单词中再取出两个字母,结果还是组成4 字母长的别名,其余依次类推)
  对工作用表来说,表名可以加上前缀WORK_ 后面附上采用该表的应用程序的名字。在命名过程当中,根据语义拼凑缩写即可。注意,由于ORCLE会将字段名称统一成大写或者小写中的一种,所以要求加上下划线。
  举例:
  定义的缩写 Sales: Sal 销售;
  Order: Ord 订单;
  Detail: Dtl 明细;
  则销售订单明细表命名为:Sal_Ord_Dtl;
  2) 如果表或者是字段的名称仅有一个单词,那么建议不使用缩写,而是用完整的单词。
  举例:
  定义的缩写 Material Ma 物品;
  物品表名为:Material, 而不是 Ma.
  但是字段物品编码则是:Ma_ID;而不是Material_ID
  3) 所有的存储值列表的表前面加上前缀Z
  目的是将这些值列表类排序在数据库最后。
  4) 所有的冗余类的命名(主要是累计表)前面加上前缀X
  冗余类是为了提高数据库效率,非规范化数据库的时候加入的字段或者表
  5) 关联类通过用下划线连接两个基本类之后,再加前缀R的方式命名,后面按照字母顺序罗列两个表名或者表名的缩写。
  关联表用于保存多对多关系。
  如果被关联的表名大于10个字母,必须将原来的表名的进行缩写。如果没有其他原因,建议都使用缩写。
  举例:表Object与自身存在多对多的关系,则保存多对多关系的表命名为:R_Object;
  表 Depart和Employee;存在多对多的关系;则关联表命名为R_Dept_Emp
  2. 属性(列)的命名
  1) 采用有意义的列名,表内的列要针对键采用一整套设计规则。每一个表都将有一个自动ID作为主健,逻辑上的主健作为第一组候选主健来定义,如果是数据库自动生成的编码,统一命名为:ID;如果是自定义的逻辑上的编码则用缩写加“ID”的方法命名。如果键是数字类型,你可以用_NO 作为后缀;如果是字符类型则可以采用_CODE 后缀。对列名应该采用标准的前缀和后缀。
  举例:销售订单的编号字段命名:Sal_Ord_ID;如果还存在一个数据库生成的自动编号,则命名为:ID。
  2) 所有的属性加上有关类型的后缀,注意,如果还需要其它的后缀,都放在类型后缀之前。
  注: 数据类型是文本的字段,类型后缀TX可以不写。有些类型比较明显的字段,可以不写类型后缀。
  3) 采用前缀命名
  给每个表的列名都采用统一的前缀,那么在编写SQL表达式的时候会得到大大的简化。这样做也确实有缺点,比如破坏了自动表连接工具的作用,后者把公共列名同某些数据库联系起来。
  3. 视图的命名
  1) 视图以V作为前缀,其他命名规则和表的命名类似;
  2) 命名应尽量体现各视图的功能
  4. 触发器的命名
  触发器以TR作为前缀,触发器名为相应的表名加上后缀,Insert触发器加"_I",Delete触发器加"_D",Update触发器加"_U",如:

  TR_Customer_I,TR_Customer_D,TR_Customer_U。
  5. 存储过程名
  存储过程应以"UP_"开头,和系统的存储过程区分,后续部分主要以动宾形式构成,并用下划线分割各个组成部分。如增加代理商的帐户的存储过程为"UP_Ins_Agent_Account"。
  6. 变量名
  变量名采用小写,若属于词组形式,用下划线分隔每个单词,如@my_err_no。
  7. 命名中其他注意事项
  1)  以上命名都不得超过30个字符的系统限制。变量名的长度限制为29(不包括标识字符@)。
  2)  数据对象、变量的命名都采用英文字符,禁止使用中文命名。绝对不要在对象名的字符之间留空格。
  3) 小心保留词,要保证你的字段名没有和保留词、数据库系统或者常用访问方法冲突
  5) 保持字段名和类型的一致性,在命名字段并为其指定数据类型的时候一定要保证一致性。假如数据类型在一个表里是整数,那在另一个表里可就别变成字符型了。

posted @ 2008-08-08 10:00 飞飞 阅读(433) | 评论 (0)编辑 收藏

如果底层数据库(如Oracle)支持存储过程,也可以通过存储过程来执行批量更新。存储过程直接在数据库中运行,速度更加快。在Oracle数据库中可以定义一个名为batchUpdateStudent()的存储过程,代码如下:

create or replace procedure batchUpdateStudent(p_age in number) as
begin
update STUDENT set AGE=AGE+1 where AGE>p_age;
end;

以上存储过程有一个参数p_age,代表学生的年龄,应用程序可按照以下方式调用存储过程:

tx = session.beginTransaction();
Connection con=session.connection();

String procedure = "{call batchUpdateStudent(?) }";
CallableStatement cstmt = con.prepareCall(procedure);
cstmt.setInt(1,0); //把年龄参数设为0
cstmt.executeUpdate();
tx.commit();

在以上代码中,用的是Hibernate的 Transaction接口来声明事务,而不是采用JDBC API来声明事务。

posted @ 2008-08-08 09:53 飞飞 阅读(325) | 评论 (0)编辑 收藏

BUG1
2008-08-07 11:25:01,015 DEBUG (FacesSetupInterceptor.java:136) - Unable to initialize faces
 java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory: javax.faces.context.FacesContextFactory
 at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:256)
 at org.apache.struts2.jsf.FacesSetupInterceptor.init(FacesSetupInterceptor.java:133)
 at com.opensymphony.xwork2.ObjectFactory.buildInterceptor(ObjectFactory.java:186)
 at com.opensymphony.xwork2.config.providers.InterceptorBuilder.constructInterceptorReference(InterceptorBuilder.java:57)
 at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.lookupInterceptorReference(XmlConfigurationProvider.java:905)
 at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadInterceptorStack(XmlConfigurationProvider.java:743)
 at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadInterceptorStacks(XmlConfigurationProvider.java:756)
 at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadInterceptors(XmlConfigurationProvider.java:777)
 at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.addPackage(XmlConfigurationProvider.java:410)
 at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadPackages(XmlConfigurationProvider.java:239)
 at org.apache.struts2.config.StrutsXmlConfigurationProvider.loadPackages(StrutsXmlConfigurationProvider.java:111)
 at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reload(DefaultConfiguration.java:152)
 at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:52)
 at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:395)
 at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:452)
 at org.apache.struts2.dispatcher.FilterDispatcher.init(FilterDispatcher.java:201)
 at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:275)
 at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:397)
 at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
 at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:3693)
 at org.apache.catalina.core.StandardContext.start(StandardContext.java:4340)
 at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
 at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
 at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
 at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920)
 at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883)
 at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
 at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
 at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
 at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
 at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
 at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
 at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
 at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
 at org.apache.catalina.core.StandardService.start(StandardService.java:516)
 at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
 at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
 at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)

这个错误是由配置文件引起。在session-factory段加入:
<property name="current_session_context_class">thread</property>
posted @ 2008-08-07 11:31 飞飞 阅读(408) | 评论 (0)编辑 收藏

     摘要: 一. 简介 1. 简介 目前的版本是:4.0 正式版 发布于2008-05-30 2. 注意事项 My97DatePicker目录是一个整体,不可破坏里面的目录结构,也不可对里面的文件改名,可以改目录名 My97DatePicker.htm是必须文件,不可删除 各目录及文件的用途: WdatePicker.js 配置文件,在调用的地方仅需使用该文...  阅读全文
posted @ 2008-08-06 09:09 飞飞 阅读(2980) | 评论 (0)编辑 收藏

1、MyEclipse下建立新的Web Porject

2、Copy Struts2的lib文件到工程的WEB-INF/lib下非*-plugin-2.0.6.jar的所有的包加上struts2-spring- plugin-2.0.6.jar,最小的包可以在struts-2.0.6\apps\struts2-blank-2.0.6\WEB-INF\ lib下找到,不过因为使用Spring、Hiberate那点包是不够用的

3.1、工程名上右键->MyEclipse->Add Spring Capabilities点击出现对话框

3.2、由于我用的MyEclipse中Spring的插件是1.2的,所以没使用MyEclipse下的包,不选择MyEclipse Libraries

3.3、选中Copy checked library contents to project folder (TLDs always copied)

3.4、使用默认的Library Folder:/WebRoot/WEB-INF/lib,Next

3.5、Folder点周Brower选中项目的WebRoot/WEB-INF/

3.6、点击Finish

4、配置MyEclipse数据库设置

4.1、菜单Windows->Preferences->MyEclipse->Database Explorer->Drivers

4.2、点击New设置数据库连接,例:
Driver template : Oracle (Thin driver)
Driver name : Oracle (Thin driver)
Connection URL : jdbc:oracle:thin:@<server>[:<1521>]:<database_name>
Driver JARs: ojdbc14.jar
Dirver classname : oracle.jdbc.driver.OracleDriver

4.3、点击OK、OK

5、忘了Copy Spring 2的jar包到工程中了,不过没关系,现在Copy也一样,Copy spring-framework-2.0.3\dist\spring.jar 到/WebRoot/WEB-INF/lib下就可以了,如果想Copy专用的包可以Copy spring-framework-2.0.3\dist\modules下的

5.1、菜单Windows->Open perspective->MyEclipse Database Explorer

5.2、在DB Brower点右键->New

5.3、配置例子如下:
Profile name: test
Driver: Oracle (Thin driver)
URL: jdbc:oracle:thin:@127.0.0.1:1521:test
User name: test
Password: test
选中Save password

5.4、点击Finish

6.1、配置Hibernate

6.2 工程名上右键->MyEclipse->Add Hiberate Capabilities点击出现对话框

6.3、选中Copy checked Library Jars to project forlder and add to build-path 点击Next

6.4、选中Spring configuration file (applicationContext.xml)点击Next

6.5、选中Existing Spring configuration file,MyEclipse会帮你自动找到Spring Config文件的

6.6、SessionFactory ID填写sessionFactory点击Next

6.7、Bean Id填写dataSource,选中DB Profile下刚才建好的test,点击Next

6.8、不选择Create SessionFactory class?点击Finish

7、这时候会提示你某些类没发现,Copy commons-dbcp-1.2.1.jar到lib下就OK了


8 配置struts.properties文件,指定spring作为struts的IoC容器
struts.objectFactory = spring
(1)默认的autowiring模式是:by name
即如果applicationContext.xml文件中的bean id与struts.xml文件中的action name相同,就
(2)如果要改为其他模式:
struts.objectFactory.spring.autoWire = name|type|auto|constructor

例:

struts.i18n.encoding=ISO-8859-1
struts.locale=de_DE
struts.objectFactory=spring
### Load custom default resource bundles
struts.custom.i18n.resources=testmessages
### XSLT Cache
struts.xslt.nocache = true


9配置web.xml文件,启动Spring侦听器
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

10 在WEB-INF目录下的applicationContext.xml文件
例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="autodetect">
<bean id="personManager" class="com.acme.PersonManager"/>
</beans >

11 设置由Spring来初始化action
11.1  在Spring的applicationContext.xml文件中配置bean(即action类)
11.2  将struts.xml中的action的class属性,由class名改为Spring中定义的bean名
例如:
(1)applicationContext.xml中,定义bean id是bar
<beans default-autowire="autodetect">
<bean id="bar" class="com.my.BarClass" singleton="false"/>
...
</beans>
(2)struts.xml中,action的class="bar",而不是通常的类名
<package name="secure" namespace="/secure" extends="default">
<action name="bar" class="bar">
<result>bar.ftl</result>
</action>
</package >

启动运行:
报错
log4j:WARN No appenders could be found for logger (org.springframework.core.CollectionFactory).
log4j:WARN Please initialize the log4j system properly.
2008-8-6 9:29:16 org.apache.catalina.core.ApplicationContext log
信息: Initializing Spring root WebApplicationContext
2008-8-6 9:29:18 org.apache.catalina.core.StandardContext listenerStart
严重: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:883)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:839)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:440)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
 at java.security.AccessController.doPrivileged(Native Method)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
 at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
 at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
 at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729)
 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381)
 at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
 at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
 at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
 at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3827)
 at org.apache.catalina.core.StandardContext.start(StandardContext.java:4334)
 at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
 at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
 at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
 at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920)
 at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883)
 at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
 at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
 at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
 at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
 at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
 at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
 at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
 at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
 at org.apache.catalina.core.StandardService.start(StandardService.java:516)
 at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
 at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
 at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool
 at java.lang.Class.getDeclaredConstructors0(Native Method)
 at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
 at java.lang.Class.getConstructor0(Unknown Source)
 at java.lang.Class.getDeclaredConstructor(Unknown Source)
 at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:54)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:877)
 ... 40 more
2008-8-6 9:29:18 org.apache.catalina.core.StandardContext start
严重: Error listenerStart
2008-8-6 9:29:18 org.apache.catalina.core.StandardContext start
严重: Context [/ssh] startup failed due to previous errors

原因:
找不到 Caused by: java.lang.NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool
就Apache所提供的基本对象池。

解决:
到这里http://commons.apache.org/downloads/download_pool.cgi下载包,然后,把里面的commons-pool-x.jar复制到项目的lib文件夹下

错误:
log4j:WARN No appenders could be found for logger (org.springframework.core.CollectionFactory).
log4j:WARN Please initialize the log4j system properly.

解决:
在WEB-INF/class 目录下建立一个log4j.properties文件,内容如下:
log4j.rootLogger=DEBUG,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %5p (%F:%L) - %m%n

警告:

信息: Starting Servlet Engine: Apache Tomcat/6.0.13
log4j:WARN No appenders could be found for logger (org.apache.struts.util.PropertyMessageResources).
log4j:WARN Please initialize the log4j system properly.
2008-8-6 9:40:09 org.apache.catalina.core.ApplicationContext log
信息: Initializing WebApplicationContext for Struts ActionServlet 'action', module ''
2008-08-06 09:40:29,859 DEBUG (CollectionFactory.java:195) - Creating [java.util.concurrent.ConcurrentHashMap]
 2008-8-6 9:40:29 org.apache.catalina.core.ApplicationContext log
信息: Initializing Spring root WebApplicationContext
2008-08-06 09:40:29,906  INFO (ContextLoader.java:189) - Root WebApplicationContext: initialization started
 2008-08-06 09:40:30,203  INFO (AbstractApplicationContext.java:412) - Refreshing org.springframework.web.context.support.XmlWebApplicationContext@1df59bd: display name [Root WebApplicationContext]; startup date [Wed Aug 06 09:40:30 CST 2008]; root of context hierarchy
 2008-08-06 09:40:30,406 DEBUG (CollectionFactory.java:195) - Creating [java.util.concurrent.ConcurrentHashMap]


index.jsp

<%@ page language="java" pageEncoding="GBK"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
 <head>
  <title>登录</title>
  <style type="text/css">
.label {
 font-style: italic;
}

.errorLabel {
 font-style: italic;
 color: red;
}

.errorMessage {
 font-weight: bold;
 color: red;
}
</style>
 </head>
 <s:head theme="ajax" />
 <body>
 <s:debug>
  <s:form action="First">
   <s:textfield name="username" label="用户名" />
   <s:textfield name="password" label="密码" />
   <s:submit value="登录" />
   <s:a href="First.action">登录</s:a>
  </s:form>
</s:debug>
 </body>
</html>



BUG:
2008-8-6 10:58:02 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet jsp threw exception
The Struts dispatcher cannot be found.  This is usually caused by using Struts tags without the associated filter. Struts tags are only usable when the request has passed through its servlet filter, which initializes the Struts dispatcher needed for this tag. - [unknown location]
 at org.apache.struts2.views.jsp.TagUtils.getStack(TagUtils.java:60)
 at org.apache.struts2.views.jsp.StrutsBodyTagSupport.getStack(StrutsBodyTagSupport.java:52)
 at org.apache.struts2.views.jsp.ComponentTagSupport.doStartTag(ComponentTagSupport.java:49)
 at org.apache.jsp.index_jsp._jspx_meth_s_005fhead_005f0(index_jsp.java:126)
 at org.apache.jsp.index_jsp._jspService(index_jsp.java:94)
 at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
 at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
 at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
 at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
 at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
 at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
 at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
 at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)
 at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
 at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
 at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
 at java.lang.Thread.run(Unknown Source)

解决:web.xml添加
<filter>
  <filter-name>struts2</filter-name>
  <filter-class>
   org.apache.struts2.dispatcher.FilterDispatcher
  </filter-class>
 </filter>
 <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>


posted @ 2008-08-06 09:07 飞飞 阅读(1981) | 评论 (0)编辑 收藏

仅列出标题
共12页: 上一页 1 2 3 4 5 6 7 8 9 下一页 Last