《基于JavaEE的电子商务网站建设》课件第5章_第1页
《基于JavaEE的电子商务网站建设》课件第5章_第2页
《基于JavaEE的电子商务网站建设》课件第5章_第3页
《基于JavaEE的电子商务网站建设》课件第5章_第4页
《基于JavaEE的电子商务网站建设》课件第5章_第5页
已阅读5页,还剩144页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第5章Struts2框架基础5.1Struts2注册功能的实现5.2struts.xml配置详解5.3增加模型组件与权限分离的方法

5.1Struts2注册功能的实现

5.1.1Struts2框架在Web应用中的环境搭建

【步骤1】下载Struts2使用的相关Jar包。

登录/download.cgi站点,查找所需版本,一般下载完整版,即FullDistribution;然后将下载的Zip文件解压缩。以下为struts-2.0.14-all.zip解压后包含的文件结构:

apps:包含基于Struts2框架的示例应用,可以直接部署到服务器上运行;

docs:包含所有Struts2框架的相关文档;

lib:包含Struts2框架的核心类库,以及其所依赖的第三方插件类库;

src:包含Struts2框架的所有源代码(开源)。

【步骤2】把Web应用需要的Jar包配置到项目中。

配置一个基本的Struts2应用至少包含以下Jar包:

freemaker-2.3.8.jar:Struts2的UI标签模板使用FreeMaker编写;

ognl-2.6.11.jar:对象图导航语言,Struts2使用的一种表达式语言;

struts2-core-2.0.14.jar:Struts2的核心类库;

xwork-2.0.7.jar:Struts2在XWork类库上构建;

commons-logging-1.0.4.jar:Struts2日志包。它们来自Struts2解压缩包的Lib文件夹。每个基于Struts2框架的应用都要先提供所需要的Jar包。

按第4章的讲解,建立Web工程ch05并将以上的5个Jar文件复制到工程的WEB-INF/lib路径下,则这些包会自动配置到环境变量中,如图5-1所示。图5-1Jar包的导入若看不到【ReferencedLibraries】中的内容,可以选中工程并点击右键,在弹出的快捷菜单中选择【BuildPath】中的【ConfigBuildPath】,将打开如图5-2所示的界面,则说明导入成功。图5-2Libraries目录

【步骤3】配置web.xml文件。

打开工程中如图5-1所示的WEB-INF/web.xml文件,增加Struts2的核心Filter配置,代码片段如下:

<?xmlversion="1.0"encoding="UTF-8"?>

<web-appversion="2.4"

xmlns="/xml/ns/j2ee"

xmlns:xsi="/2001/XMLSchema-instance"

xsi:schemaLocation="/xml/ns/j2ee

/xml/ns/j2ee/web-app_2_4.xsd">

<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>

</web-app>5.1.2视图表单页面

Struts2支持大部分视图技术,当然也支持最传统的JSP视图技术。

以下Struts2标签实现登录表单提交和显示功能。登录信息包括两个表单域:用户名(username)和密码(password)。

1.登录表单请求页面

【步骤1】建立login.jsp文件。

使用第4章讲解的方法在ch05中新建login.jsp文件,注意文件的放置目录为ch05/WebRoot。在login.jsp页面的【Design】视图中把JSP页面的pageEncoding属性修改为“gb2312”(第一行),同时加入struts标签导入语句(第二行),代码如下:

<%@taglibprefix="s"uri="/struts-tags"%>页面代码如下:

<%@pagelanguage="java"import="java.util.*"

pageEncoding="gb2312"%>

<%@taglibprefix="s"uri="/struts-tags"%>

……

<body>

<s:formaction="loginAction">

<s:textfieldname="username"label="username">

</s:textfield>

<s:passwordname="password"

label="password"></s:password>

<s:submitname=“submit”></s:submit>

</s:form>

</body>

【步骤2】运行注册页面。

用第4章讲解的方法在MyEclipse中部署ch05工程,并启动Tomcat,运行工程http://localhost/ch05/,显示如图5-3所示的界面。读者在今后的学习中也可用此方法来避免文件名的错误输入。图5-3ch05工程运行界面点击login.jsp的超链接,显示表单如图5-4所示。

图5-4登录表单页面图

2.注册表单响应页面

同请求页面生成一样,新建loginok.jsp,仅把【步骤1】的代码换成如下代码:

<%@pagelanguage="java"import="java.util.*"

pageEncoding="gb2312"%>

<%@taglibprefix="s"uri="/struts-tags"%>

……

<body>

欢迎<s:propertyvalue="username"/>!!

</body>由于尚未配置Struts2控制器,注册响应界面无值传入,因此运行界面如图5-5所示。图5-5登录响应页面

3. Struts2标签简介

1)标签库的导入

Struts2标签库的描述文件包含在Struts2的核心JAR包(struts2-core-2.0.14.jar)中,在META-INF目录下,文件名为struts-tags.tld。

JSP2.0规范中规定,标签库部署在JAR包中时,标签库描述符文件必须放在META-INF目录或其子目录下,放在META-INF目录下的TLD文件会被容器自动加载。在struts-tags.tld文件中,设置了<uri>元素,如下所示:

<uri>/struts-tags</uri>

在JSP页面中引用Struts2标签库时,需要使用taglib指令,该指令的uri属性的值设为这里的<uri>元素的内容。至于prefix属性,通常设为“s”,如上面jsp页面的设置。

<%@taglibprefix="s"uri="/struts-tags"%>

2) form标签

Struts2的表单标签可以分为两类:form标签本身和包装HTML表单元素的其他标签。下面先介绍form标签。

form标签常用的属性如表5-1所示。

3)表单元素的其他标签

登录功能的表单填写页面用到两个表单标签:textfield和password。这两个标签相当于HTML表单标签中的text和password标签。这两个标签常用的属性如表5-2所示。

4)数据标签property

在上面的loginok.jsp中使用了property标签,很明显,property标签用于输出值栈中的对象属性值,使用value属性来指定要输出的对象属性。property标签常用的属性如表5-3所示。

4.注册页面的纯JSP实现下面提供以上Struts2实现表单的纯JSP编码,让读者用熟悉的语言来对照Struts2标签的功效。

login_jsp.jsp代码如下:

<body>

<formaction="loginAction.action">

<tableborder="0"><tr>

<td>username</td>

<td><inputtype="text"name="username"/></td></tr>

<tr><td>password</td>

<td><inputtype="password"name="password"/>

</td></tr>

<tr><td><inputtype="submit"value="submit"/></td>

<td></td></tr>

</table>

</form>

</body>

loginok_jsp.jsp代码如下:

<body>

欢迎<%=request.getParameter("username")%>!!

</body>当表单提交loginAction.action时,Struts2的FilterDispatcher将自动起作用,将用户请求转发到对应的Struts2Action,Struts2Action默认拦截所有后缀为.action的请求。在Struts2中,struts2-core-2.0.14.jar包中的org.apache.struts2包中有个perties文件,它定义了Struts2Action默认拦截的请求后缀。5.1.3控制器类的实现

1.代码实现

下面就是建立Struts2控制器类的步骤:

【步骤1】建立控制器类com.action.LoginAction.java。

在ch05工程的src目录下,右键单击【New】的【Class】子菜单,填写如图5-6所示的页面,新建com.action包中的Action文件LoginAction.java,并实现Action接口。图5-6新建控制器类

【步骤2】初步完成表单属性和execute方法。

在新建的LoginAction.java文件中输入如下代码:

packagecom.action;

importcom.opensymphony.xwork2.Action;

publicclassLoginActionimplementsAction{

privateStringusername;

privateStringpassword;

publicStringexecute()throwsException{

returnSUCCESS;

}

}

【步骤3】生成属性的get/set方法。

在文件中要插入属性的get/set方法处点击鼠标右键,选择【Source】的【GenerateGettersandSetters】,在出现的如图5-7所示的界面中选中所有属性。图5-7get/set方法产生器点击【OK】按钮,则会自动产生如下代码:

publicStringgetUsername(){

returnusername;}

publicvoidsetUsername(Stringusername){

this.username=username;}

publicStringgetPassword(){

returnpassword;}

publicvoidsetPassword(Stringpassword){

this.password=password;

}

2.实现原理

Struts2的Action接口里定义了五个常量,一个execute方法。这五个常量就是在日常开发中业务逻辑方法返回的字符串,execute方法则是Action接口定义的一个默认的业务逻辑方法。五个常量分别代表特定的含义:● SUCCESS:表示请求处理成功;

● ERROR:表示请求处理失败;

● NONE:表示请求处理完成后不跳转到任何页面;

● INPUT:表示输入时如果验证失败应该跳转到什么地方;

● LOGIN:表示登录失败后跳转的目标。

这些常量可以简化和标准化execute方法的返回值,避免直接返回字符串,但是如果有特殊返回意义,则还可以自定义字符串。5.1.4struts.xml配置的实现

与大部分Java框架类似,Struts2框架也采用XML配置文件来管理Struts2资源。Struts2默认配置文件名为struts.xml,该文件要求放在Web应用的类加载路径下,通常放在WEB-INF/classes路径下。struts.xml配置文件最大的作用就是配置Action和请求之间的对应关系,并配置逻辑视图名和物理视图资源之间的对应关系。

【步骤1】创建struts.xml文件。

由于MyEclipse的IDE会自动把src目录下的文件编译到WEB-INF/classes文件中,所以只要在ch05工程的src文件夹根目录下建立struts.xml文件即可。右击src文件夹,选择【New】菜单下的【XML(BasicTemplates)】,在弹出的图5-8中把文件名改成struts.xml,直接点击【Finish】即可。图5-8生成struts.xml文件

【步骤2】完成struts.xml的文档类型声明。

struts.xml和Struts2核心包(struts2-core-2.0.14.jar)中的struts-default.xml文件的结构是一样的,都是由struts-2.0.dtd来定义的。struts-default.xml给出了适合大多数Web应用程序的基本配置,而struts.xml通常从struts-default.xml中继承默认的包定义,并给出特定Web应用程序的action配置。所以,我们可以打开struts-default.xml,把它的DTD申明拷贝过来,代码如下:

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEstrutsPUBLIC

"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN"

"/dtds/struts-2.0.dtd">

【步骤3】完成registerAction转发的配置。

<struts>

<constantname="struts.i18n.encoding"value="gbk"></constant>

<packagename="struts2"extends="struts-default"namespace="">

<actionname="loginAction"class="com.action.LoginAction">

<resultname="input">/login.jsp</result>

<resultname="success">/loginok.jsp</result>

</action>

</package>

</struts>

【步骤4】项目运行

完成配置后可以运行本项目。启动服务器,在IE中输入地址http://localhost/ch05/login.jsp,将显示如图5-9所示的界面。填好信息后,点击【submit】,将进入如图5-10所示的界面。注意,此时地址栏的名字为http://localhost/ch05/loginAction.action,但界面内容却是loginok.jsp,说明struts.xml的配置起作用了。

图5-9运行输入界面图5-10提交转入页面对于整个登录的处理流程,可以简化如下:用户输入两个参数username和password,然后向login.action发送请求,该请求被FilterDispatcher转发给LoginAction处理。如果LoginAction处理用户请求后返回success,则返回给用户loginok.jsp页面;如果输入错误,则系统默认返回login.jsp页面,并要求重新输入。5.1.5Struts2框架的工作流程

Struts2框架按照模块,可以分为ServletFilters、Struts核心模块、拦截器和用户实现部分。Struts2官方站点提供的Struts2的整体结构如图5-11所示。图5-11Struts2结构图一个请求在Struts2框架中的处理大概分为以下几个步骤:

(1)客户端提交一个(HttpServletRequest)请求。如上文中提交注册信息后,在浏览器中地址为http://localhost/ch05/loginAction.action,就是提交一个(HttpServletRequest)请求。

(2)请求被提交到一系列(主要是3层)的过滤器(Filter),如ActionContextCleanUp、其他过滤器(SiteMesh等)、FilterDispatcher。注意:这里是有顺序的,先ActionContextCleanUp,然后为其他过滤器(OtherFilters、SiteMesh等),最后到FilterDispatcher。

(3) FilterDispatcher是控制器的核心,就是MVC的Struts2实现中控制层(Controller)的核心。

(4) FilterDispatcher询问ActionMapper是否需要调用某个Action来处理这个(HttpServletRequest)请求,如果ActionMapper决定需要调用某个Action,FilterDispatcher则把请求的处理交给ActionProxy。

(5) ActionProxy通过ConfigurationManager(struts.xml)询问框架的配置文件,找到需要调用的Action类。例如,注册示例将找到LoginAction.java类。

(6) ActionProxy创建一个ActionInvocation实例,同时ActionInvocation通过代理模式调用Action。如果在struts.xml文件中配置method参数,则调用method参数对应的Action类中的method方法,否则调用通用的execute()方法来处理用户请求;但在调用之前,ActionInvocation会根据配置加载Action相关的所有Interceptor(拦截器)。

(7)一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果result。

5.2struts.xml配置详解

5.2.1struts.xml文件的元素结构

struts.xml文件的元素结构图如图5-12所示。

在图5-12中,星号(*)表示0个或多个元素,问号(?)表示该元素是可选的,加号(+)表示该元素至少有一个或多个,没有添加这三种符号的元素表明该元素是必需的。图5-12struts.xml文件的元素结构图5.2.2包含(include)的配置

在默认情况下,Struts2框架将自动加载放在WEB-INF/classes路径下的struts.xml文件中。在大部分应用里,随着应用规模的增加,系统中Action的数量也将大量增加,导致struts.xml配置文件变得非常臃肿。

为了避免struts.xml文件过于庞大,提高struts.xml文件的可读性,可以将一个struts.xml配置文件分解成多个配置文件,然后在struts.xml文件中包含其他配置文件。<?xmlversion="1.0"encoding="UTF-8"?>

<!--指定Struts2配置文件的DTD信息-->

<!DOCTYPEstrutsPUBLIC

"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN"

"/dtds/struts-2.0.dtd">

<!--下面是Struts2配置文件的根元素-->

<struts>

<!--通过include元素导入其他配置文件-->

<includefile="com/action/cart/struts-cart.xml"/>

...

</struts>5.2.3常量(constant)的配置

常量可以在多个文件中声明,分别为:

① struts-default.xml;

② struts-plugin.xml;

③ struts.xml;

④ perties;

⑤ web.xml。

1. struts.xml配置常量

struts.xml配置常量使用constant标签,其包含两个属性值:name和value。其中,name是常量的名字,如果定义的常量是Struts2内置的属性,如编码(struts.i18n.encoding)、国际化资源包文件基名(struts.custom.i18n.resources)等,则可以在perties中查找对应的常量名;value就是常量的值。

<struts>

<constantname="struts.i18n.encoding"value="gb2312"></constant>

<constantname="struts.custom.i18n.resources"

value="message"></constant>

</struts>

2.属性(properties)文件

perties文件中,每一个键-值对就是一个常量

设置。对于以上的struts.custom.i18n.resources的常量值为message,这表示在Struts2中定义了一个名为perties的属性文件,此文件必须放在WEB-INF/classes的根目录下。建立属性文件的步骤为:

【步骤1】新建文件perties。

选择src文件夹,右击【New】下的【File】子菜单,在出现的如图5-13所示的界面中输入文件名perties,点击【Finish】即可。

【步骤2】设置编码值。

在打开的perties文件中输入以下代码即可。

struts.i18n.encoding=gb2312图5-13新建属性文件图

3. web.xml配置常量

<filter>

<filter-name>struts2</filter-name>

<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>

<init-param>

<param-name>struts.i18n.encoding</param-name>

<param-value>gb2312</param-value>

</init-param>

</filter>5.2.4包(package)和名称空间(namespace)的配置

1. package配置

Struts2中的包(package)类似于Java中的包,每个包都包含了将要用到的action、result和拦截器的定义。但是和Java中的包不同的是,Struts2的包可以扩展另外的包,从而“继承”原有包的所有定义,并可添加自己包特有的配置,以及修改原有包的部分配置。struts.xml中的package元素包含的属性如表5-4所示。在以上属性中,name的值必须是唯一的,在一个struts.xml中不能出现两个同名的包。extends属性允许一个包继承一个或多个先前定义的包的配置,如果定义多个,则用逗号隔开。在注册示例的配置中,表示名为struts2的包继承struts-default包,这个包位于struts-default.xml中,是Struts2框架自动加载的。 <packagename="struts2"extends="struts-default">

</package>

<packagename="struts-cart"extends="struts2">

</package>

2. namespace配置

package元素的namespace属性可以将包中的action配置为不同的名称空间,这样在不同名称空间中可以使用同名action。Struts2框架使用action名字和它所在的名称空间来标识一个action。而namespace可以不定义,就是默认名称空间,当请求在自己的名称空间没有找到对应的action时,就会自动查找默认名称空间中相同名字的请求,如以下编码:<packagename="struts2"extends="struts-default">

<actionname="loginAction"class="com.action.LoginAction">

……

</action>

</package>

<packagename="struts-cart"extends="struts-default"namespace="/cart">

<actionname="registerAction"class="com.action.RegisterAction">

……

</action>

</package>当请求/cart/loginAction.action发生时,Struts2框架首先查找/cart名称空间的loginAction.action,如果找到了,就执行;如果像以上代码中一样没有找到,就会到默认的名称空间继续查找,找到后再执行。5.2.5action的配置

Struts的核心是action,通常action类都要实现com.opensymphony.xwork2.Action接口,实现该接口的execute()方法。但在实际开发中很少直接实现Action接口,而是继承ActionSupport类(详解见第6章)。开发好action后,就要配置action映射,用来通知Struts2框架,针对某个URL的请求应该交由哪个action进行处理。

1. action映射

action映射就是将一个请求URI(即action名字)映射到一个action类,当一个请求匹配某个action名字时,框架就使用这个映射来确定如何处理请求。struts.xml文件中的每一个action元素就是一个action映射。Action元素的完整属性如表5-5所示。如5.1.4中的配置:

<actionname="

loginAction"

class="

com.action.LoginAction">

<resultname="input">/login.jsp</result>

<resultname="success">/loginok.jsp</result>

</action>

要注意避免以下事项:

■一般不允许出现斜杠(/);

■名字中尽量不要使用点号(.)和连字符(-)。

2.使用method属性

在业务逻辑开发中,为了节省action的数量,通常在一个action类中编写多个业务方法,如数据库的CRUD操作(Create、Read、Update、Delete)。大家到目前也应该清楚,在执行action时,默认调用的方法是execute(),那么如何让不同请求到来时,使用框架去调用同一个action的不同方

法呢?我们先看以下action代码片段(来源于5.3节的示例):

publicclassLoginActionimplementsAction{

publicStringexecute()throwsException{

returnSUCCESS;}

publicStringlogin()throwsException{

returnSUCCESS;}

}

LoginAction.java中定义了两个逻辑方法execute()和login()。注意,login()的结构必须符合execute()的结构publicStringexecute()throwsException{}。那么在配置action时,可以通过method属性来指定action调用的方法,见struts.xml片段(来源于5.3节的示例):<actionname="loginAction"class="com.action.LoginAction">

<resultname="input">/login.jsp</result>

<resultname="success">/loginok.jsp</result>

</action>

<actionname="isUMAction"class="com.action.LoginAction"method="login">

<resultname="input">/login.jsp</result>

<resultname="success">/user.jsp</result>

</action>

3.通配符映射

随着Web应用规模的增大,Action的数量会非常庞大,这时可使用通配符映射来减少action配置的数量。

代码如下:

<actionname="*Crud"class="example.Crud"

method="{1}">

这里,当在应用中将action指定为“editCrud”时,将调用editCrudAction处理类实例中的edit方法。另外一种方法是通过action的后缀来匹配方法名,并且通过感叹号、下划线或者其它特殊字符将其分开,如action="/Crud_input.action"或action="/Crud_delete.action"。下面的代码片断演示了在action名称的最后使用星号通配符的示例:

<actionname="Crud_*"class="example.Crud"method=

"{1}">

当然通配符除了*号外,还有其他内容:

*:匹配0个或多个字符,斜杠(/)字符除外;

**:匹配0个或多个字符,包括斜杠(/)字符;

\:反斜杠字符被用作转义序列,例如,\*匹配星号(*),\\匹配反斜杠字符(\)。5.2.6Result的配置

1.结构映射

在struts.xml文件中,使用result元素来配置result映射。result元素的属性如表5-6所示。

2.常用结果类型

1) dispatcher结果类型

Struts2将dispatcher设为默认的结果类型,就像在登录示例中没有定义结果类型,但都默认使用dispatcher转发。

dispatcher转发地址中可以使用OGNL表达式(参见第6章),例如在购物车系统中,每个商品都有一个id号来标识,当用户点击购买时,此请求一定带有id号,传送此id的地址可以写成:

<result>/cart.jsp?id=${id}</result>

2) redirect结果类型

redirect结果类型相当于使用HttpServletResponse的sendRedirect方法将请求重定向到指定的URL,就是重定向后的URL地址是实际访问的页面地址,而不是action的名字。由于这个原因,使用redirect结果类型可以避免重复提交表单的操作。

3) redirectAction结果类型

redirectAction结果类型和redirect结果类型的后台工作原理是一样的,都是使用HttpServletResponse的sendRedirect方法将请求重定向到指定的URL。但是redirectAction结果类型主要用于重定向到action。具体示例请参照下面第3点“动态结果”的内容。

3.动态结果

所谓动态结果,是指在配置时你不知道要执行哪个结果,在运行时才能确定执行的结果。也就是说,利用表达式来配置结果,在运行时,框架解析并计算表达式,根据表达式的值来确定要执行的结果。

例如在登录功能中,如果一个系统有多个不同的角色管理,那么登录成功后应该进入不同的操作界面,以达到操作权限的分离。分析下面的代码片段(来源于5.3节的示例):

publicclassLoginActionimplementsAction{

……

//用于保存请求重定向到的action名字;

privateStringnextAction;

……

publicStringgetNextAction(){

returnnextAction;}

publicStringlogin()throwsException{

……

if(…){//验证用户是否为管理员;

nextAction=“manager”;

}else{

nextAction=“user”;}

returnSUCCESS;

……

}

}

LoginAction在用户登录验证成功后,判断用户的权限,根据用户是管理者还是普通用户来设置示例变量nextAction的值。

以下是struts.xml文件的代码片段(来源于5.3节的示例):

<actionname="isUMAction"class=“com.action.LoginAction"method="login">

<resultname="input">/login.jsp</result>

<resulttype="redirectAction">${nextAction}</result>

</action>

<actionname=“manager”>

<result>/manager.jsp</result>

</action>

<actionname=“user”>

<result>/user.jsp</result>

</action>

使用${nextAction}来获取Action中的nextAction属性的值,而这个值要到运行时刻才能确定。

5.3增加模型组件与权限分离的方法

5.3.1增加虚拟模型

【步骤1】新建模型组件。

在src目录下新建com.service.ProductService.java文件,此模型中定义了判断权限的userOrManager()方法和获取产品的getProducts()方法。一般Struts2的模型组件就是用来定义各种业务逻辑方法的,这样方便代码测试。代码如下:

packagecom.service;

publicclassProductService{

//以一个常量数组模拟登陆后从数据库中取出的数据;

privateStringproducts[]=newString[]{"a","a2","b1","b2"};

//业务逻辑方法,该方法返回全部产品;

publicString[]getProducts(){

returnproducts;

}

//业务逻辑方法,该方法返回0为普通用户,1为管

理员;

publicintuserOrManager(Stringusername,String

password){

if(“张三”.equals(username)&&

“123456”.equals(password)){return1;

}else{

return0;

}

}

}

【步骤2】修改action文件。

修改action文件com.action.LoginAction.java,增加与execute()方法结构一样的方法login(),在此方法中把登录名放进session范围变量,并根据登录权限设置登录成功的action转发名,另外还可取得模型中的产品变量的数据。代码如下:

packagecom.action;

importjavax.servlet.http.HttpServletRequest;

importorg.apache.struts2.ServletActionContext;

importcom.opensymphony.xwork2.Action;

importcom.opensymphony.xwork2.ActionContext;

importcom.service.ProductService;

publicclassLoginActionimplementsAction{

privateStringusername;

privateStringpassword;

privateStringproducts[];

//用于保存请求重定向到的action名字;

privateStringnextAction;

……//省略username与password的get/set方法

publicvoidsetProducts(String[]products){

ducts=products;}

publicString[]getProducts(){

returnproducts;}

publicStringgetNextAction(){

returnnextAction;}

publicStringexecute()throwsException{

returnSUCCESS;

}

publicStringlogin()throwsException{

ActionContextct=ActionContext.getContext();

HttpServletRequestrequest=

(HttpServletRequest)ct.get(ServletActionContext.

HTTP_REQUEST);

if(getUsername()!=null){

request.getSession().setAttribute(“session_name”,getUsername());

ProductServiceproductService=newProductService();

//判断是否管理者

if(productService.userOrManager(getUsername(),getPassword())==1){

nextAction="manager";

}else{

nextAction=“user";}

//设置用户购买的产品

setProducts(productService.getProducts());

returnSUCCESS;

}else{

returnINPUT;

}}}

【步骤3】修改struts.xml配置。

为了运行action文件中的login()方法,需要对struts.xml文件进行修改,使得登录成功后管理员转入manager.jsp页面,用户转入user.jsp页面。代码如下:

<packagename="struts2"extends="struts-default"

namespace="">

<actionname="loginAction"

class="com.action.LoginAction">

<resultname="input">/login.jsp</result>

<resultname="success">/loginok.jsp</result>

</action>

<actionname="isUMAction"

class="com.action.LoginAction"method="

login">

<resultname="input">/login.jsp</result>

<resulttype="redirectAction">${nextAction}</result>

</action>

<actionname="manager">

<result>/manager.jsp</result>

</action>

<actionname="user">

<result>/user.jsp</result>

</action>

</package>

useraction和manageraction没有指定类名,只是利用Action进行转发,因此默认使用com.opensymphony.xwork2.ActionSupport类。

【步骤4】修改和新增视图。

(1)修改login.jsp表单。需要把登录提交的action改为isUMAction.action。代码如下:

<%@pagelanguage="java"import="java.util.*"

pageEncoding="GB2312"%>

<%@taglibprefix="s"uri="/struts-tags"%>

<body>

<s:formaction="isUMAction">

<s:textfieldname="username"

label="username"></s:textfield>

<s:passwordname="password"

label="password"></s:password>

<s:submitname="submit"></s:submit>

</s:form>

</body>

(2)新增manager.jsp页面。在manager.jsp中显示session范围的变量session_name的值,使用OGNL表单式(见第6章)。代码如下:

<%@pagelanguage="java"import="java.util.*"

pageEncoding="GB2312"%>

<%@taglibprefix="s"uri="/struts-tags"%>

<body>

欢迎管理员:${sessionScope.session_name}!!

</body>

(3)新增user.jsp页面。在user.jsp页面中除了显示登录名外,还要显示用户购买的商品,其中使用Struts2标签完成循环和判断的操作。代码如下:

<%@pagelanguage="java"import="java.util.*"

pageEncoding=“GB2312”%>

<%@taglibprefix="s"uri="/struts-tags"%>

<body>

欢迎用户:${sessionScope.session_name}!!<br>您购买的商品中排在偶数位的物品清单如下:<br>

<s:iteratorvalue="#ducts"status="index"id="product_index">

<!--判断序号是否为偶数-->

<s:iftest="#index.odd==false">

<s:propertyvalue="product_index"/>

</s:if>

<s:else><br></s:else>

</s:iterator>

</body>■ iterator标签

iterator标签用于迭代一个集合(包括Collection、Map、Enumeration、Iterator或者array数组)。iterator标签在迭代过程中,会把迭代的每一个对象暂时压入值栈,这样在标签内部就可以直接访问对象的属性和方法,在标签执行完毕后,位于栈顶的对象就会被删除;在第二次迭代过程中,再压入新的对象。

iterator标签的属性如表5-7所示。■ if/else-if/else标签

if标签用于基本的流程控制,它可以单独使用,也可

以和一个或多个else-if标签,或者和一个else标签一起使

用。if/else-if/else标签类似于Java中的if/else-if/else语句,可根据一定的条件(Boolean表达式)来选择执行或跳过标签体的内容。

if标签的属性如表5-8所示。

【步骤5】运行结果和调试。

重新启动Tomcat服务器,运行程序,管理员登录页面与登录成功页面分别如图5-14和图5-15所示。图5-14管理员登录图5-15管理员登录成功一般用户登录页面与登录成功页面分别如图5-16和图5-17所示。

图5-16用户登录图5-17用户登录成功在图5-17所示的页面中没有出现物品清单,这是怎么回事?究其原因,请读者仔细观察,在struts.xml中是通过redirectAction转发action来进入用户登录页面的,而在user.action的配置中没有对应的action类,只有转发页面。前面我们提到,在Struts2中访问的属性一定要在Action中存在,并且要有其对应的get×××()方法才能访问到,因此这里访问不到products变量。那么如何修改呢?最理想的方法就是在login()中把products也放入session范围,在login()的returnSUCCESS;语句前增加以下代码:

request.getSession().setAttribute(“products”,getProducts());

把user.jsp代码中的黑体部分修改如下:

<s:iteratorvalue="#ducts"status="index"id="product_index">

再次运行,用户登录成功的界面如图5-18所示。图5-18修改用户登录成功5.3.2访问request、session和application对象

在上一小节中,当用户登录成功后,我们将用户信息保存到Session中,这是ServletAPI中的HttpSession,一般Web开发中常用ServletAPI中的HttpServletRequest、HttpSession和ServletContext。Struts2框架让我们可以直接访问和设置action及模型对象的数据,这降低了对HttpServletRequest对象的使用需求。

1.与ServletAPI解耦的访问方式

为了避免与ServletAPI耦合在一起,方便action类做单页测试,Struts2框架构造了三个Map对象来代替HttpServletRequest、HttpSession和ServletContext。这可以在以下的action中验证,com.action.sessionway.LoginAction1.java代码如下:

packagecom.action.sessionway;

importjava.util.Map;

importcom.opensymphony.xwork2.Action;

importcom.opensymphony.xwork2.ActionContext;

publicclassLoginAction1implementsAction{

privateStringuser;

publicStringgetUser(){

returnuser;

}

publicvoidsetUser(Stringuser){

this.user=user;

}

publicStringexecute()throwsException{

ActionContextcontext=ActionContext.getContext();

Maprequest=(Map)context.get(“request”);

Mapsession=context.getSession();

Mapapplication=context.getApplication();

//在请求中放置欢迎信息

request.put("greeting","欢迎来到清风书苑");

//在session中保存对象

session.put(“user”,user);

//统计用户访问量,在application中保存用户访问量数据

Integercount=(Integer)application.get("counter");

if(null==count)

count=newInteger(1);

else

count=newInteger(Value()+1);

application.put("counter",count);

returnSUCCESS;

}

}

2.与ServletAPI耦合的访问方式

有时候程序中又确实需要直接访问这些对象,则可以使用org.apache.struts2.ServletActionContext类。com.action.sessionway.LoginAction2.java代码如下:

packagecom.action.sessionway;

importjavax.servlet.ServletContext;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpSession;

importorg.apache.struts2.ServletActionContext;

importcom.opensymphony.xwork2.Action;

importcom.opensymphony.xwork2.ActionContext;

publicclassLoginAction2implementsAction{

privateStringuser;

publicStringgetUser(){

returnuser;

}

publicvoidsetUser(Stringuser){

this.user=user;

}

publicStringexecute()throwsException{

ActionContextctx=ActionContext.getContext();

HttpServletRequestrequest=(HttpServletRequest)

ctx.get(ServletActionContext.HTTP_REQUEST);

HttpSessionsession=request.getSession();

ServletContextcontext=(ServletContext)

ctx.get(ServletActionContext.SERVLET_CONTEXT);

//在请求中放置欢迎信息

request.setAttribute("greeting","欢迎来到清风书苑");

//在session中保存user对象

session.setAttribute("user",user);

//统计用户访问量,在application中保存用户访问量数据

Integercount=(Integer)context.getAttribute("counter");

if(null==count)

count=newInteger(1);

else

count=newInteger(Value()+1);

context.setAttribute(“counter”,count);

returnSUCCESS;

}

}

3.完善以上action配置

对以上两个action,需要一个输出页面来显示和配置struts.xml,如果输出页面能正常显示保存在action中的request、session、application对象中的数据,则说明对象操作成功。

【步骤1】完成访问页面session.jsp和输出页面sessionok.jsp。

session.jsp中使用超链接传值的方式传输user对象,这种方法在程序中经常用到,代码如下:

<body>

使用与ServletAPI解耦的访问方式

<ahref="

session1.action?user=hellen">request、session和application对象</a>

<br>

使用与ServletAPI耦合的访问方式

<ahref="

session2.action?user=john">request、session和application对象</a>

</body>

sessionok.jsp中使用EL表达式来获取三个值,这种方式简单好用,代码如下:

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论