Struts2系统学习笔记三

来源:互联网 发布:微信支付源码 编辑:程序博客网 时间:2024/06/14 08:22

标签

内容
- 使用数据标签
- 使用控制标签控制流程
- 其他标签
- OGNL表达式语言

1 入门

所有Struts2的领域数据,都保存在ValueStack中,而ValueStack和一些基础性的数据,都保存在ActionContext对象中。

1.1 ActionContext 和 OGNL

我们使用OGNL表达式将表单字段名绑定到对象的具体属性。action对象被放在ValueStack对象,OGNL表达式指向这个栈上的属性。实际上 OGNL可以用来求更宽泛的值的对象为ActionContext。

ActionContext包含了框架的请求处理过程中可以访问的所有数据。
img
ActionContext包含了丰富的数据,其中最重要的是ValueStack。其他的数据都对应着Servlet API中的概念。

名字 描述 parameters 当前请求中请求参数的映射 request 请求作用域的属性的映射 session 会话作用于的属性的映射 application 应用程序作用域的属性和映射 attr 按照页面、请求、会话、应用程序作用于的顺序,返回第一个出现的属性 ValueStack 包含当前请求的应用程序特定领域的所有数据

为OGNL选择根对象
OGNL表达式必须选择ActionContext中的一个对象作为它的根对象。
#session[‘user’]
OGNL通过#操作符主动命名为ActionContext中的会话映射。

1.2 虚拟对象ValueStack

当Struts 2接收到一个请求时,它立即创建一个ActionContext、一个ValueStack和一个动作对象。

如图,action的name由于是最底层的模型对象,所以他不会被访问。

也可以将其他内容放入ValueStack中,通常通过push标签来把期望的对象放入ValueStack上。

2 Struts2 标签概要

Struts2的标签可以分为4种类别:数据标签(data tag)、流程控制标签(control-flow tag)、UI标签(UI tag)和其他标签(miscellaneous tag)。

2.1 Struts2标签API语法

1. JSP语法
Struts 2标签的JSP版本与其他JSP标签一样。

<s:property value = "name" />

标签声明:

<%@ page contentType="text/html; charset=UTF-8" %><%@ taglib prefix="s" uri="/struts-tags" %>

2. Velocity语法

#sproperty( "value=name" )#sform ("action=Register")#stextfield ("label=Username" "name=username")#spassword ( "label=Password" "name=password")#stextfield ( "label=Enter a name" "name=portfolioName")#ssubmit ("value=Submit")#end

3. FreeMarker语法

<@s.property value="name"/>

2.2 使用OGNL设置标签属性

向标签的属性设置值时有两点内容必须理解。最基本的问题是,这个属性期望一个字符串字面值,还是一个指向ValueStack上有具体类型的值的OGNL表达式。
1.字符串和非字符串类型的属性
如果一个属性的类型是String,那么在JSP或者Velocity页面中,写入属性的值会被作为字符串字面值解析。如果属性不是String类型,那么就会被当做OGNL表达式。

nonExistingProperty on the ValueStack = <s:property value="nonExistingProperty" />nonExistingProperty on the ValueStack = <s:property value="nonExistingProperty" default="doesNotExist" />

第一个标签由于没有使用#操作符指明ActionContext中的特定对象,所以会在ValueStack上查找。如果nonExistingProperty属性在ValueStack上不存在,那么一个空值会转换为空字符串。

第二个标签仍然尝试从ValueStack上取出nonExistingProperty指向的属性,这个属性为空。然而该标签指定了default属性,在value指定的属性不存在的情况下会返回default属性指定的内容。由于default属性的作用是提供一个用来在页面显示的默认值,它是String类型。

使用%{expression}的语法可以强制让字符串属性当做OGNL表达式解析。

2. 强制使用OGNL解析

Struts 2 OGNL语法 JSTL 表达式语法 %{expression} ${expression}

3 数据标签

数据标签能从ValueStack上去的数据,或者将变量、对象放在ValueStack上。

3.1 property标签

属性 是否必须 默认值 类型 描述 value 否 栈最顶端 Object 被显示的值 default 否 空 String 值为空时使用的默认值 escape 否 True Boolean 是否转义HTML
<body>    <h4>Property Tag</h4>    The current user is <s:property value="user.username"/>.    </body>

3.2 set标签

设置set意味着给一个属性指定一个别名。使用后,该属性变为ActionContext中的一个命名对象。

属性 是否必须 类型 描述 name 是 String 引用名 scope 否 String application、session、request、page或者action、默认值为action value 否 Object 设置值的表达式
<s:set name="username" value="user.username"/>Your username is <s:property value="#username"/>. 

3.3 push标签

set标签允许你创建指向值的新引用,而push标签允许你将属性放到ValueStack上。

属性 是否必须 类型 描述 value 是 Object 放到ValueStack中的值
<s:push value="user">    <h2>This is the "<s:property value="portfolioName"/>"portfolio</h2>    It was created by none other than <s:property value="firstName"/>       <s:property value="lastName"/>.     </s:push>

3.4 bean标签

bean标签像是set标签和push标签的混合标签。主要的不同是不需要使用一个已存在的对象。可以创建一个对象的实例,把它放到ValueStack上或者设置为ActionContext的顶级引用。

<s:bean name="org.apache.struts2.util.Counter" id="counter">    <s:param name="last" value="100"/></s:bean><s:iterator value="#counter">    <!-- Remember, the struts2 property tag defaults to the             top of the stack if a 'value' attribute is not set. -->    <li><s:property/></li></s:iterator>

该例子将bean创建在ActionContext中。

下面这个例子是将bean创建到ValueStack上而不是存储在ActionContext上。

<s:bean name="com.alan.web.uitags.utils.JokeBean" >    <s:param name="jokeType">adult</s:param>            <s:property value="startAJoke()"/>  </s:bean>
属性 是否必须 类型 描述 name 是 String 被创建bean的包名和类名 var 否 String 在结束标签作用域之外引用这个bean时使用的变量名

3.5 action标签

action标签允许我们从当前的视图层调用其他的动作。

属性 是否必须 类型 描述 name 是 String 动作名 namespace 否 String 动作的命名空间,默认使用当前页面的命名空间 var 否 String 在页面后续代码中使用的动作对象的引用名 executeResult 否 Boolean 设置为true时排除动作的结果(默认为false) flush 否 Boolean 设置为true时会在action标签的结尾会刷新写出缓冲(默认true) ignoreContextParams 否 Boolean 调用时不包含请求参数(默认为false)

包含辅助动作的结果示例:

<body>    <h3>Action Tag</h3>    <hr/>    <h4>This line is from the ActionTag action's result.</h4>    <s:action name="TargetAction" executeResult="true"/>    <hr/></body>

如果想把动作的结果包含到当前页面,那么其他动作的结果应该是一个HTML片段。

4 控制标签

4.1 iterator标签

iterator标签可以非常容易地遍历集合对象。它可以遍历任何的Collection、Map、Enumeration、Iterator或者数组。
这个标签也支持在ActionContext中定义一个保存遍历状态的变量。

属性 是否必须 类型 描述 value 是 Object 被遍历的对象 status 否 String 如果指定,IteratorStatus对象会使用这个属性指定的名字被放到ActionContext中
<s:iterator value="users" status="itStatus">    <li>        <s:property value="#itStatus.count" />        <s:property value="portfolioName"/>    </li></s:iterator>

iterator标签通过指定的status属性声明了IteratorStatus对象。而itStatus是保存在ActionContext中的,所以需要用#来获取。
IteratorStatus可获得的信息:

方法名 返回值 getCount int getIndex int isEven boolean isFirst boolean isLast boolean isOdd boolean modulus(int operand) int

4.2 if和else标签

属性 是否必须 类型 描述 test 是 Boolean 被求值和测试的布尔表达式
<body>    <h4>If/Else Tags</h4>    <s:if test="user.age > 35">This user is too old.</s:if>    <s:elseif test="user.age < 35">This user is too young</s:elseif>        <s:else>This user is just right</s:else>    </body>

5 其他标签

有用但不容易分类的标签,include标签、URL标签、i18n标签和text标签。

5.1 include标签

属性 是否必须 类型 描述 value 是 String 页面、动作、Servlet以及其他可以被引用的URL名字

如JSP的<jsp:include>,Struts2 提供了个更高特性的include标签。
和action标签不同,include标签可以引用任何的Servlet资源。

使用include标签时,需要牢记正在直接包含一个JSP、Servlet或者其他的Web资源。包含其他Web资源的语义来源于Servlet API。

5.2 URL标签

属性 是否必须 类型 描述 value 否 String 基础URL,默认为呈现当前页面的URL action 否 String 生成的URL指向的动作名,使用声明式架构中配置的动作名 var 否 String 如果指定,URL不会被写出,而会存储在ActionContext留待后用 includeParams 否 String 从all、get、none中选择参数,默认为get includeContext 否 Boolean 默认true,生成的URL会以Context为前缀。 encode 否 Boolean 如果用户浏览器不支持Cookie,会将Session ID追加到生成的URL中 scheme 否 String 指定协议,默认为当前协议(HTTP/HTTPS)
    <h4>Url Tag</h4>                    <hr/>    <h5>Url Tag Direct Usage</h5>                           URL = <s:url value="IteratorTag.action"/><br/>          <a href='<s:url value="IteratorTag.action" />'> Click Me </a>       <hr/>

输出如下:

URL = IteratorTag.action<a href='IteratorTag.action'> Click Me </a>
    <h5>Url Tag Stashed in ActionContext</h5>               URL =   <s:url action="IteratorTag" id="myUrl">                 <s:param name="id" value="2"/>             </s:url>       <a href='<s:property value="#myUrl" />'> Click Me </a>    <hr/>   

输出如下:

URL =<a href='/manningHelloWorld/chapterSix/IteratorTag.action?id=2'>Click Me</a>

可以使用includeParams属性来指定参数是否传递到新的URL中。get的意思是只有URL中的查询字符串会传递到生成的URL中。post为表单。

5.3 i18n和text标签

i18n用来设置国际化。
text标签用来显示与具体语言相关的文本,这个标签从由框架的国际化机制公开的ResourceBundle中取得消息值。

text标签属性:

属性 是否必须 类型 描述 name 是 String 在ResourceBundle中查找用的关键字 var 否 String 如果找到,文本会使用这个名字保存在ActionContext

可以命名一个特别的ReourceBundle来解析text标签。如果想手动指定应该使用的ResourceBundle,可使用i18n标签。

i18n标签属性:

属性 是否必须 类型 描述 name 是 String ResourceBundle的名字
<s:i18n name="manning.chapterSix.myResourceBundle_tr">    <!-- The text tag can be used to output a resource inline or, if the 'id' attribute is used, the returned resource value will be stored in the action context for later use.-->     In <s:text name="language"/>,    <s:text name="girl" id="foreignWord"/> </s:i18n>"<s:property value="#foreignWord"/>" means girl.

i18n标签指定了一个需要使用的资源包。这个资源包仅在内部使用。

5.4 param标签

param是配置name和value的标签。

6 使用JSTL和其他文本标签

可以支持

7 OGNL表达式语言的基础知识

7.1 Struts 2中常用的表达式语言特性

1. 引用bean属性
OGNL表达式语言就是所谓的属性链 (chain of properties),如:
person.father.father.firstName

2.设置或取得

当数据设置时:

<s:form action="Register">    <s:textfield name="username" label="Username"/>    <s:password name="password" label="Password"/>    <s:textfield name="portfolioName" label="Enter a portfolio name."/>    <s:submit/></s:form>

比如这个例子,每一个输入字段的name属性都是一个OGNL表达式。这些表达式指向了OGNL跟对象公开的属性,而根对象就是ValueStack。

当情况开始复杂,可考虑深层表达式:
user.portfolio.name
当框架发现属性类有null属性时,他会尝试创建一个合适类型的新实例,并且将这个实例设置到对应的属性上。但是这个属性类型必须满足JavaBean规范的类,并且提供一个没有参数的构造方法。

当数据离开框架时,我们也使用OGNL表达式。

<h5>Congratulations! You have created </h5><h3>The <s:property value="portfolioName" /> Portfolio</h3>

3.使用Collection类型,数组与List
引用数组或者List属性元素的OGNL表达式语言语法:

Java代码 OGNL表达式 list.get(0) list[0] array[0] array[0] ((User)list.get(0)).getName() list[0].name array.length array.lenght list.size() list.size list.isEmpty() list.isEmpty

OGNL中动态创建List:
{1,2,3}

可见使用OGNL来表达数组或者list非常的直观与易用。

4.使用Map

Java代码 OGNL表达式 map.get(“foo”) map[‘foo’] map.get(new Integer(1)) map[1] User user = (User)map.get(“userA”);
return user.getName() map[‘userA’].name map.size() map.size map.isEmpty() map.isEmpty map.get(“foo”) map.foo

最后一行是一种特殊用法,如果key是String类型,则可直接使用.keystr。

OGNL动态创建Map
#{“foo”:”bar”,”baz”:”whazzit”}
#{1:”one”,2:”two”,3:”three”}

如果想提供true/false但现实为Yes/No,则可以使用#{true:’yes’,false:’No’}

5.过滤(filtering)和投影(projecting)集合
过滤语法: collectionName.{? expression}

投影语法: collectionName.{ expression}

常用:

OGNL表达式 描述 users.{? #this.age > 30} 过滤,返回一个30岁以上用户的新集合 users.{username} 投影,返回一个用户名字符串的新集合 user.{firstName + ’ ’ + lastName} 投影,返回每一个用户全名字符串的新集合 users.{?#this.age > 30}.{username} 先过滤,后投影,返回年龄在30岁以上的用户名字符串的新集合

7.2 高级特性

1.字面值和操作符

字面值类型 示例 Char ‘a’ String ‘hello’、”hello” Boolean true、false int 123 double 123.5 BigDecimal 123b BigInteger 123h

操作符:

操作符 示例 add(+) 2 + 4 ‘hello’ + ‘world’ subtract(-) 5 - 3 multiply(*) 8 * 2 divide(/) 9 / 3 modulus(%) 9 % 3 increment(++) ++foo,foo++ decrement(–) bar–,–bar equality(==) foo == bar less than(<) 1 < 2 greater than(>) 2 > 1

2. 调用方法

Java代码 OGNL表达式 utilityBean.makeRandomNumber() makeRandomNumber() utilityBean.getRandomNumberSeed() getRandomNumberSeed()
randomNumberSeed

假定utilityBean这个随机数生成器已经被压入了ValueStack

3.访问静态方法和字段
OGNL可通过指定完全限定的类名,以及ValueStack解析。
语法:@[fullClassName]@[property or methodCall]
示例:@manning.utils.Struts2PortfolioConstants@USER
@manning.utils.PortfolioUitiityBean@startImageWrapper( )


UI组件标签

内容:
- 使用UI组件生成HTML
- 构建表单以及其他内容
- 使用模板和主题增强效果
- 各式各样的组件

1 UI组件标签的作用

Struts2的UI组件不仅仅是表单元素,他还有以下功能:
- 生成HTML标记
- 绑定HTML表单字段和Java端属性
- 与框架提供的类型转换关联起来
- 与框架提供的验证关联起来
- 与框架提供的国际化功能关联起来

2 标签、模板和主题

Alt text

3 UI组件标签

这些都不做详细描述,而作为一个概括的目录来展示这些组件。

3.1 通用属性

name、value、key、label、labelPosition、required、id、cssClass、cssStyle、disabled、tabindex、theme、templateDir、template

3.2 简单组件

1.head组件

<head>    <title>Portfolio Registration</title>    <s:head/></head>
<link rel="stylesheet" href=" . . . styles.css" type="text/css"/><script language="JavaScript" type="text/javascript" src=". . .dojo.js"/><script language="JavaScript" type="text/javascript" src="dojoRequire.js"/>

2.form组件
属性:action、namespace、method、target、enctype(上传文件时设置为multipart/form-data)、validate。

<s:form action="Login">    <s:textfield name="username" label="Username"/>    <s:password name="password" label="Password"/>    <s:submit/></s:form>

3.textfield组件

<s:form action="Login">    <s:textfield key="username"/>    <s:password name="password" label="Password"/>    <s:submit/></s:form>

4.password组件
属性:maxlength、readonly、size、showPassword

5.textarea组件
属性:cols、rows、readonly、wrap

6.checkbox组件
属性:fieldValue、value

3.3 基于集合的组件

1.select组件
下拉列表组件

<s:select name="user.name" list="{'Mike','Payal','Silas'}" />

2.radio组件

3.checkboxlist组件

4.预填充基于集合的组件

<s:form action="SelectPortfolio" >    <s:radio name="username" list='users' value="defaultUsername"listKey="username" listValue="username" label="Select an artist" />    <s:submit value="Browse"/></s:form>

3.4 额外的组件

1.label组件

<s:label name="username" label="Username" />

这个组件很像一个只读的textfield组件

2.hidden组件

<s:hidden name="username" />

3.doubleselect组件

    <h4>Select a portfolio to view.</h4>    <s:form action="ViewPortfolio">        <s:doubleselect name="username" list='users' listKey="username" listValue="username" doubleName="portfolioName"doubleList="portfolios" doubleListValue="name" />        <s:submit value="View"/>    </s:form>

8 结果

内容
- 使用结果
- 分发和重定向请求
- 构建自定义结果
- 使用Velocity或者FreeMarker结果

8.1 动作之后

<action name="PortfolioHomePage" class=". . . PortfolioHomePage">    <result>/chapterEight/PortfolioHomePage.jsp</result></action>

8.1.1 构建Struts 2 Ajax应用程序

传统的Web应用程序:
Alt text
响应的内容是一个完整的HTML页面,客户浏览器使用这个完整的页面呈现了整个窗口。

Ajax应用程序:
Alt text
他只返回数据,当Ajax客户接受响应时,它不会让浏览器重新呈现整个HTML页面,而是仔细检查序列化为XML或者JSON的数据,对这些数据在当前浏览器页面上受影响的区域进行有目的的更新。

8.1.2 实现JSON结果类型

JSON(JavaScript Object Notation)提供了一种简洁的、基于文本的数据对象序列化的方式。JSON是Web应用程序服务器和Ajax客户之间数据通信的一种非常简洁和轻量级的方式。
1.Ajax例子
https://github.com/xu509/Alan/blob/master/src/main/webapp/page/result/ajaxUserBrowser.jsp
https://github.com/xu509/Alan/blob/master/src/main/webapp/page/result/ajaxUserBrowser.js

<action name="AjaxUserBrowser" class="com.alan.web.result.AjaxUserBrowser">    <result>/page/result/ajaxUserBrowser.jsp</result></action><action name="AjaxRetrieveUser" class="com.alan.web.result.RetrieveUser">    <result type="customJSON">artist</result></action>

2 常用的结果类型

结果类型 用例 参数 dispatcher JSP,其他web application资源,如Servlet location、parse redirect 告诉浏览器重定向到另一个URL location、parse redirectAction 告诉浏览器重定向到另一个Struts动作 actionName、namespace,额外的参数会变成查询字符串的参数

2.1 RequestDispatcher,也叫做dispatcher

所有的示例代码都使用了这个类型,这是默认类型。

1.DispatcherResult的Servlet核心
DispatcherResut结果类型的核心是javax.servlet.RequestDispatcher。RequestDispatcher公开了两个方法来执行转交给其他的Servlet:include( )和forward( )。

2. 普通工作流,使用forward()分发

3. 迁移到其他servlet

4.通过include( )方法分发

5.建立RequestDispatcher结果类型

<action name="SelectPortfolio" class="manning.chapterSeven.SelectPortfolio">    <result type="dispatcher" >        <param name="location">/chapterSeven/SelectPortfolio.jsp</param>        <param name="parse">true</param>    </result></action>

2.2 ServletRedirectResult,也叫做redirect

1.建立重定向的结果类型

<action name="SendUserToSearchEngineAction" class="myActionClass">    <result type='redirect'>http://www.google.com</result></action>

2.嵌入OGNL表达式创建动态的位置

<action name="SendUserToSearchEngineAction" class="myActionClass">    <result type='redirect' >        http://www.google.com/?myParam=${defaultUsername}    </result></action>

2.3 ServletActionRedirectResult

redirectAction结果与简单的redirect结果做相同的事情。

<action name="Login" class="manning.chapterSeven.Login">    <result type="redirect">        /chapterSeven/secure/AdminPortfolio.action    </result>    <result name="input">/chapterSeven/Login.jsp</result></action>
<action name="Login" class="manning.chapterEight.Login">    <result type="redirectAction">        <param name="actionName">AdminPortfolio</param>        <param name="namespace">/chapterEight/secure</param>    </result>    <result name="input">/chapterEight/Login.jsp</result></action>

redirectAction能支持多种不同的URL模式的变更。

4 全局结果

<global-results>    <result name="error">/chapterFour/Error.jsp</result></global-results>

集成Spring

1 配置

相应jar包
需要Spring插件, struts2-spring-plugin-2.x.x.jar。
maven配置:

<dependency>   <groupId>org.apache.struts</groupId>   <artifactId>struts2-spring-plugin</artifactId>   <version>2.0.11</version></dependency>

web.xml配置

<listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>

applicationContext配置
该文件位于web-inf文件夹下

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">    <bean id = "loginService" class="com.template.service.impl.LoginServiceImpl"/>    <bean id="loginAction" class="com.template.web.LoginAction" scope="prototype">        <property name="loginService" ref="loginService"/>    </bean></beans>
<action name="Login" class="springManagedLoginAction">    <result type="redirectAction">        <param name="actionName">AdminPortfolio</param>        <param name="namespace">/chapterEight/secure</param>    </result>    <result name="input">/chapterEight/Login.jsp</result></action>

可用Spring管理Struts的动作、拦截器以及结果的创建。

0 0
原创粉丝点击