Struts2系统学习笔记三

15 篇文章 0 订阅
本文深入探讨Struts2框架的核心技术,包括ValueStack、ActionContext、OGNL表达式语言及其应用,同时覆盖了Struts2标签库的详细分类与使用方法,帮助开发者快速掌握Struts2的关键特性。
摘要由CSDN通过智能技术生成

标签

内容
- 使用数据标签
- 使用控制标签控制流程
- 其他标签
- 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被显示的值
defaultString值为空时使用的默认值
escapeTrueBoolean是否转义HTML
<body>
    <h4>Property Tag</h4>
    The current user is <s:property value="user.username"/>.    
</body>

3.2 set标签

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

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

3.3 push标签

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

属性是否必须类型描述
valueObject放到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>
属性是否必须类型描述
nameString被创建bean的包名和类名
varString在结束标签作用域之外引用这个bean时使用的变量名

3.5 action标签

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

属性是否必须类型描述
nameString动作名
namespaceString动作的命名空间,默认使用当前页面的命名空间
varString在页面后续代码中使用的动作对象的引用名
executeResultBoolean设置为true时排除动作的结果(默认为false)
flushBoolean设置为true时会在action标签的结尾会刷新写出缓冲(默认true)
ignoreContextParamsBoolean调用时不包含请求参数(默认为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中定义一个保存遍历状态的变量。

属性是否必须类型描述
valueObject被遍历的对象
statusString如果指定,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可获得的信息:

方法名返回值
getCountint
getIndexint
isEvenboolean
isFirstboolean
isLastboolean
isOddboolean
modulus(int operand)int

4.2 if和else标签

属性是否必须类型描述
testBoolean被求值和测试的布尔表达式
<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标签

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

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

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

5.2 URL标签

属性是否必须类型描述
valueString基础URL,默认为呈现当前页面的URL
actionString生成的URL指向的动作名,使用声明式架构中配置的动作名
varString如果指定,URL不会被写出,而会存储在ActionContext留待后用
includeParamsString从all、get、none中选择参数,默认为get
includeContextBoolean默认true,生成的URL会以Context为前缀。
encodeBoolean如果用户浏览器不支持Cookie,会将Session ID追加到生成的URL中
schemeString指定协议,默认为当前协议(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标签属性:

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

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

i18n标签属性:

属性是否必须类型描述
nameStringResourceBundle的名字
<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.lengtharray.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”
Booleantrue、false
int123
double123.5
BigDecimal123b
BigInteger123h

操作符:

操作符示例
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 常用的结果类型

结果类型用例参数
dispatcherJSP,其他web application资源,如Servletlocation、parse
redirect告诉浏览器重定向到另一个URLlocation、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的动作、拦截器以及结果的创建。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值