一、基础实验——Action的自定义方法
(一)实验目的
1、掌握Struts2 的Action 类中自定义方法的使用;
2、掌握Struts2 中Action 类的不同调用方式和相应的配置方法;
3、掌握Action 的实例化情况,理解Action 与Servlet 在实例化上的区别;
4、理解JSP 文件中获取Action 属性的过程;
5、了解Struts2 支持的Action 处理结束后的结果类型。
(二)基本知识和原理
1、Action 类中的默认方法名是execute()方法,可以被自动调用;
2、在Action 中也允许定义其它方法名,可以同时定义多个方法,分别处理不同的逻辑;
3、当Action 中使用了自定义方法,则该Action 就需要特定的配置,一般有四种调用方式:
(1)在struts.xml 文件中通过method 属性指定方法名;
(2)使用动态方法调用方式(DMI);
(3)使用提交按钮的method 属性;
(4)使用通配符配置Action;
4、Action 类是多实例的,Action 类的属性是线程安全的;
5、在JSP 页面中,可以通过Struts2 标签调用Action 中对应的getter 方法,从而输出Action 的属性值;
6、当一个Action 处理用户请求结束后,返回一个字符串作为逻辑视图名,再通过struts.xml 文件中的配置将逻辑视图名与物理视图资源关联起来;Struts2默认提供了一系列的结果类型(struts-default.xml 配置文件的result-types 标签里列出了所支持的结果类型),结果类型决定了Action 处理结束后,将调用哪种视图资源来呈现处理结果。
(三)实验内容及步骤
- 新建Web 工程struts-prj2,并将Struts2 中的8 个核心包添加到工程中;
- 在struts-prj2中新建login.jsp页面,作为用户登录的视图;新建loginFail.jsp页面,作为登录失败的视图;新建loginSucess.jsp视图,作为登录成功的视图;
#login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>登录</title>
</head>
<body>
<s:form method="post" action="login.action">
<s:textfield name="loginUser.account" key="login.account.lable"/>
<s:password name="loginUser.password" key="login.password.lable"/>
<s:submit name="submit" key="login.submit.button"/>
</s:form>
</body>
</html>#loginFail.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登陆失败</title>
</head>
<body>
登陆失败
</body>
</html>#loginSuccess.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功</title>
</head>
<body>
登录成功
</body>
</html>- 在struts-prj2中新建register.jsp页面,作为用户注册的视图;新建regFail.jsp页面,作为注册失败的视图;新建regSuccess.jsp页面,作为注册成功的视图;
#register.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ taglib prefix="sx" uri="/struts-dojo-tags"%>
<html>
<head>
<s:head theme="xhtml"/>
<sx:head parseContent="true" extraLocales="UTF-8"/>
</head>
<body>
<s:form action="register.action" method="post" onsubmit="return check()">
<s:textfield name="loginUser.account" key="register.account.lable"/>
<s:password name="loginUser.password" key="register.password.lable"/>
<s:password name="loginUser.repassword" key="register.repassword.lable"/>
<s:radio name="loginUser.sex" list="#{1:'男', 0:'女'}" key="register.sex.lable"/>
<sx:datetimepicker name="loginUser.birthday" displayFormat="yyyy-MM-dd" key="register.birthday.lable"/>
<s:textfield name="loginUser.address" key="register.address.lable"/>
<s:textfield name="loginUser.phone" key="register.phone.lable"/>
<s:textfield name="loginUser.email" key="register.email.lable"/>
<s:submit name="sign up" key="register.submit.button"/>
<s:reset name="reset" key="register.reset.button"/>
</s:form>
</body>
</html>#regFail.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册失败</title>
</head>
<body>
注册失败
</body>
</html>#regSuccess.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>注册成功</title>
</head>
<body>
<s:property value=""/>
<s:if test="%{loginUser.sex==\"1\"}">
<s:text name="先生, "/>
</s:if>
<s:else>
<s:text name="女士, "/>
</s:else>
您注册成功了!
<s:set name="user" value="loginUser" scope="session"/>
</body>
</html>- 在struts-prj2 中新建cn.edu.zjut.bean 包,并在其中创建UserBean.java,用于记录用户信息;
package cn.edu.zjut.bean;
public class UserBean {
private String account="";
private String password="";
private String repassword="";
private String name="";
private String sex="";
private String birthday="";
private String address="";
private String phone="";
private String email="";
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRepassword() {
return repassword;
}
public void setRepassword(String repassword) {
this.repassword = repassword;
}
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}- 在struts-prj2 中新建cn.edu.zjut.service 包,并在其中创建UserService.java,用于实现登录逻辑和注册逻辑;
package cn.edu.zjut.service;
import cn.edu.zjut.bean.UserBean;
public class UserService {
public boolean login(UserBean loginUser){
if(loginUser.getAccount().equals(loginUser.getPassword())){
return true;
}
return false;
}
public boolean register(UserBean registerUser){
if(registerUser.getAccount().equals(registerUser.getPassword()) && registerUser.getPassword().equals(registerUser.getRepassword()) && !registerUser.getAccount().equals("")){
return true;
}
return false;
}
}- 在struts-prj2 中新建cn.edu.zjut.action 包,并在其中创建UserAction.java,定义login()方法和register()方法,参照“实验二Struts 基础应用”写入代码,分别用于调用登录逻辑和注册逻辑;
package cn.edu.zjut.action;
import cn.edu.zjut.bean.UserBean;
import cn.edu.zjut.service.UserService;
public class UserAction {
private UserBean loginUser;
public UserBean getLoginUser(){
return loginUser;
}
public void setLoginUser(UserBean loginUser){
this.loginUser = loginUser;
}
public String login(){
UserService userService = new UserService();
if(userService.login(loginUser)){
return "success";
}
return "fail";
}
public String register(){
UserService userService = new UserService();
if(userService.register(loginUser)){
return "success";
}
return "fail";
}
}- 在工程struts-prj2的src目录中创建struts.xml文件,配置Action并设置页面导航,通过action标签中method属性指定方法名;
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<!-- <package> 元素用于进行包配置,在 Struts2 框架中,包用于组织 Action 和拦截器等信息,每个包都是由零个或多个拦截器以及 Action 所组成的集合。-->
<!-- name:必填属性,用于指定该包的名称,此名称是该包被其他包引用的Key-->
<!-- namespace:可选属性,用于定义包的命名空间-->
<!-- extends:可选属性,用于指定该包继承自其他包,其属性值必须是另一个包的name属性值,但该属性值通常设置为struts-default,这样该包中的Action就具有了Struts框架默认的拦截器等功能-->
<package name="strutsBean" extends="struts-default">
<!-- action配置指定了需要初始化哪个action类进行处理-->
<!-- result则指定了对应字符串的处理结果-->
<action name="login" class="cn.edu.zjut.action.UserAction" method="login">
<result name="success">/loginSuccess.jsp</result>
<result name="fail">/loginFail.jsp</result>
</action>
<action name="register" class="cn.edu.zjut.action.UserAction" method="register">
<result name="success">/regSuccess.jsp</result>
<result name="fail">/regFail.jsp</result>
</action>
</package>
</struts>- 编辑Web的web.xml文件,增加Struts2核心Filter的配置;
- 配置struts-prj2部署在Tomcat服务器上,访问login.jsp和register.jsp页面,并记录运行结果;

- 动态方法调用方式(DMI)
#struts.xml
<action name="UserAction" class="cn.edu.zjut.action.UserAction">
<result name="loginsuccess">/loginSuccess.jsp</result>
<result name="loginfail">/loginFail.jsp</result>
<result name="registersuccess">/regSuccess.jsp</result>
<result name="registerfail">/regFail.jsp</result>
</action>
#需写入以下语句不然会出现500错误
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>#login.jsp
<s:form method="post" action="UserAction!login">
<s:textfield name="loginUser.account" key="login.account.lable"/>
<s:password name="loginUser.password" key="login.password.lable"/>
<s:submit name="submit" key="login.submit.button"/>
</s:form>- 提交按钮方式
struts.xml的配置方法同DMI方式
<s:form method="post" action="UserAction">
<s:textfield name="loginUser.account" key="login.account.lable"/>
<s:password name="loginUser.password" key="login.password.lable"/>
<s:submit name="submit" key="login.submit.button" method="login"/>
</s:form>- 通配符方式
#struts.xml
<action name="*Action" class="cn.edu.zjut.action.UserAction" method="{1}">
<result name="{1}sucess">/{1}Success.jsp</result>
<result name="{1}fail">/{1}Fail.jsp</result>
</action>#login.jsp
<s:form method="post" action="loginAction">
<s:textfield name="loginUser.account" key="login.account.lable"/>
<s:password name="loginUser.password" key="login.password.lable"/>
<s:submit name="submit" key="login.submit.button"/>
</s:form>- 修改UserAction.java,增加UserAction类的构造方法UserAction(),增加count属性,用于测试Action的实例化情况
public class UserAction {
private UserBean loginUser;
private Integer count=0;
public UserAction(){
System.out.println("创建了一个UserAction类对象。");
}
#必须要设置get方法才能被<s:property>标签获取
public Integer getCount() {
return count;
}
public UserBean getLoginUser(){
return loginUser;
}
public void setLoginUser(UserBean loginUser){
this.loginUser = loginUser;
}
public String login(){
count++;
UserService userService = new UserService();
if(userService.login(loginUser)){
return "loginsuccess";
}
return "loginfail";
}
public String register(){
UserService userService = new UserService();
if(userService.register(loginUser)){
return "registersuccess";
}
return "registerfail";
}
}
- 修改struts.xml文件,将UserAction的页面导航设置为redirect结果类型
<action name="login" class="cn.edu.zjut.action.UserAction" method="login">
<result name="loginsuccess" type="redirect">/loginSuccess.jsp</result>
<result name="loginfail">/loginFail.jsp</result>
</action>
(四)实验总结
- Action的四种自定义方式,method方式最好理解,通过method属性表示该请求需要由哪个方法处理,DMI方式和按钮方式则通过在请求时使用!跟上方法标识来进行处理,通配符方式则通过空出的*号来代替请求中相应位置的字符,通过{num}来填充其他地方的内容。
- 通过多次访问结合控制台的信息,我们可以判断每次的请求都重新初始化了一个Action,而Servlet则会在第一次访问时创建,期间多次访问的Servlet为同一个。
- 将type改为redirect之后,发现count值不见了,默认的方式为dispatcher,重定向的方式返回jsp不带有count的值。
dispatcher主要用于返回JSP,HTML等以页面为基础View视图,这个也是Struts2默认的Result类型。
Freemarker或者Velocity是为模板准备数据;
redirect目标地址将无法通过ValueStack等Struts2的特性来获取源Action中的数据;
chain其实只是在一个action执行完毕之后,forward到另外一个action,所以他们之间是共享HttpServletRequest的;
StreamResult等价于在Servlet中直接输出Stream流
二、提高实验——ActionSupport与输入校验
(一)实验目的
- 了解Action 接口的作用,理解ActionSupport 类的作用;
- 掌握在Struts2 中使用校验器或手工编码的方式,对请求参数进行数据校验的方法,掌握在JSP 页面中显示错误信息和提示信息的方法;
- 掌握在Action 中使用国际化资源文件的方法;
- 掌握Struts2 内置类型转换器的作用和使用方法。
(二)基本知识和原理
- 为了让用户开发的Action 类更规范,Struts2 提供了一个Action 接口,该接口定义了Struts2 的Action 处理类应该实现的规范;
- Struts2 还为Action 接口提供了一个实现类:ActionSupport,该类提供了若干默认方法,包括:默认的处理用户请求的方法(excute()方法)、数据校验的方法、添加校验错误信息的方法、获取国际化信息的方法等,部分重要方法列表如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IoQQSwNh-1634041997841)(https:///2021/10/11/dxioaNFUXDKhfgP.png)] - Struts2 框架提供了校验器和手工编码两种方式对请求参数进行数据校验,当Action 类继承了ActionSupport 类,就可以通过定义名为“--validation.xml”的校验规则文件的方法进行校验器校验,也可以通过重写ActionSupport 类的validate()方法或validateXxx()方法进行手动校验;
- 在JSP 页面中使用Struts2 标签生成的表单,能将域级别的错误信息将自动显示到表单元素处;
- 在JSP 页面中使用fielderror 标签,可以集中显示所有的域级错误信息;使用actionerror 标签,可以显示所有的Action 级别错误信息;使用actionmessage标签,可以显示Action 消息;
- Struts2 框架中提供了部分内置的类型转换器,可以将请求参数的String 类型转换成基本数据类型及对应的包装器类型、日期类型、数组类型、集合类型等,当Action 类继承了ActionSupport 类,则内置的类型转换器将默认生效,可以直接使用;
- 如需修改默认的类型转换校验信息,则要在Action 类的包中声明名为“Action类名.properties”的局部属性文件;
- Struts2 框架同时支持自定义类型转换器,将请求参数转换成任意一种类型。
(三)实验内容及步骤
- 修改UserAction类,使其继承ActionSupport类,并在UserAction类中覆盖ActionSupport类的validate()方法,用于对用户登录的请求参数account和password进行校验:若用户名或密码为空,则使用addFieldError(域级)添加错误信息;
public void validate(){
String account = loginUser.getAccount();
String pwd = loginUser.getPassword();
if(account == null || account.equals("")){
this.addFieldError("loginUser.account", "请输入您的用户名!");
}
if(pwd == null || account.equals("")){
this.addFieldError("loginUser.password", "请输入您的密码! ");
}
}- 修改struts.xml文件,在Action的配置中增加validate()方法校验出错时的页面导航()
<action name="login" class="cn.edu.zjut.action.UserAction" method="login">
<result name="loginsuccess">/loginSuccess.jsp</result>
<result name="loginfail">/loginFail.jsp</result>
<result name="input">/login.jsp</result>
</action>
- 修改login.jsp页面,在表单钱增加fielderror标签,再通过浏览器访问
- 修改UserAction.java,再带哦有登录逻辑的login()方法中,对登录情况进行校验:若登录成功,使用addActionMessage()方法添加“登录成功!”的Action提示消息,若登录失败,使用addActionError()方法添加Action级别的错误信息
public String login(){
count++;
UserService userService = new UserService();
if(userService.login(loginUser)){
this.addActionMessage("登录成功!");
return "loginsuccess";
}
else {
this.addActionError("用户名或密码错误,请重新输入!");
return "loginfail";
}
}- 修改login.jsp页面增加actionerror标签;修改loginSuccess.jsp,使用actionmessage标签显示Action提示消息
- 修改sruts.xml文件中用户登录页面导航设置,将登录失败时转向的页面从loginFail.jsp转为login.jsp

- 创建"UserAction-login-validation.xml"校验规则文件,使其与UserAction类位于同一目录下,配置校验信息,使用校验器对请求参数进行校验。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="loginUser.account">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!!!</message>
</field-validator>
</field>
<field name="loginUser.password">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>密码不能为空!!!</message>
</field-validator>
</field>
</validators>
- 将login.jsp、loginSuccess.jsp、loginFail.jsp三个页面进行国际化处理,把需要进行国际化的内容以键值对形式写入资源文件message_zh_CN.properties和message_en_US.properties中
#message_en_US.properties
#field error message
login.account.null=Please input your account!
login.password.null=Please input your password!
#action error message
login.error= Account or password error, please input again!
#action message
login.success=Login successfully!
#message_zh_CN.properties
#field error message
login.account.null=请输入你的用户名
login.password.null=请输入你的密码!
#action error message
login.error=用户名或密码错误,请再次输入!
#action message
login.success=登录成功- 创建struts.properties文件,加载资源文件
struts.custom.i18n.resources=cn.edu.zjut.local.message
struts.i18n.encoding=GBK- 修改UserAction.java,使用ActionSupport()类的getText()方法,获取国际化资源文件信息
public String login(){
count++;
UserService userService = new UserService();
if(userService.login(loginUser)){
this.addActionMessage(this.getText("login,success"));
return "loginsuccess";
}
else {
this.addActionError(this.getText("login.error"));
return "loginfail";
}
}
public void validate(){
String account = loginUser.getAccount();
String pwd = loginUser.getPassword();
if(account == null || account.equals("")){
this.addFieldError("loginUser.account", this.getText("login.account.null"));
}
if(pwd == null || account.equals("")){
this.addFieldError("loginUser.password", this.getText("login.password.null"));
}
}- 修改UserAction-login-validation.xml,获取国际化资源文件中信息
<validators>
<field name="loginUser.account">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message key="login.account.null"></message>
</field-validator>
</field>
<field name="loginUser.password">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message key="login.password.null"></message>
</field-validator>
</field>
</validators>- 运行结果
- 修改UserBean.java,将用于保存注册用户生日的变量类型该类Date类型,使用Struts2内置的类型转换器对请求参数进行校验
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ULsVxrTL-1634041997851)(https:///2021/10/12/VcwTdlPWEpg4sIB.png)]
- 创建局部属性文件“UserAction.properties”,修改类型转换的校验信息,并使用native2ASCII工具将UserAction.properties重新编码
#UserAction.properties
#其中invalid.fieldvalue不能随意修改,
#loginUser.birthday是请求参数域名,应根据实际需要进行修改
invalid.fieldvalue.loginUser.birthday=生日必须是日期,并符合“yyyy-mm-dd”格式<action name="register" class="cn.edu.zjut.action.UserAction" method="register">
<result name="registersuccess">/regSuccess.jsp</result>
<result name="registerfail">/regFail.jsp</result>
<result name="input">/register.jsp</result>
</action>
- 创建UserAction-register-validation.xml文件,增加校验信息的配置,使用校验器对用户注册的请求参数进行校验,要求注册时两次密码输入相同、email地址格式符合要求等
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="loginUser.email">
<field-validator type="email">
<param name="trim">true</param>
<message>你的电子邮件必须时符合规范的</message>
</field-validator>
</field>
<field name="loginUser.password">
<field-validator type="fieldexpression" short-circuit="true">
<param name="expression"><![CDATA[(loginUser.password == loginUser.repassword)]]></param>
<message>两次密码要相同</message>
</field-validator>
</field>
</validators>
- 修改UserAction类,将validate()的方法名改为validateLogin(),并增加validateRegister()方法
public void validateRegister(){
String email = loginUser.getEmail();
String pwd = loginUser.getPassword();
String repwd = loginUser.getRepassword();
if(!email.contains("@")){
this.addFieldError("loginUser.email", this.getText("register.email"));
}
if(!pwd.equals(repwd)){
this.addFieldError("loginUser.repassword", this.getText("register.repassword"));
}
}
(四)实验总结
- validate()是ActionSupport类的默认方法,重写该方法可自定义校验方式,validateXxx()方法则是首字母大写,基于Xxx动态调用来对不同的请求进行数据校验。
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4agpU0Bl-1634041997855)(https:///2021/10/12/z13a9ns6BHyUiw8.png)]
required:必填校验器
requiredstring:必填字符串校验器
int:整数校验器
double:双精度浮点数校验器
date:日期校验器
expression:表达式校验器
fieldexpression:字段表达式校验器
email:电子邮件校验器
url:网址校验器
stringlength:字符串长度校验器
regex:正则表达式校验器 - 国际化资源需要先创建资源键值对,然后struts.properties启动国际化资源,在xml文件和jsp文件中使用key属性使用,java类中使用getText()方法使用
- 内置类型转换器的使用需要创建ClassName-way-validation.xml的格式在所在Action类同目录下创建,配置validators,在配置field-validator时要选择对应的type类
三、拓展实验——Action类与ServletAPI
(一)实验目的
- 掌握在Action 中访问Servlet API 的四种方法,理解四种方法的区别;
- 进一步理解Action 与Servlet 的区别;
- 进一步熟悉Struts2 标签的使用方法;
(二)基本知识与原理
- Struts2 框架中的Action 类没有与任何Servlet API 耦合,因此Action 类可以脱离Servlet 容器环境进行单元测试;
- ActionContext 是com.opensymphony.xwork2 包中的一个类,该类表示一个Action 运行时的上下文;
- 当Action 类需要通过请求、会话或上下文存取属性时,可以通过ActionContext类完成,也可以通过实现Struts 提供的接口:RequestAware、SessionAware和ApplicationAware 完成,而不必调用Servlet API 中的HttpServletRequest、HttpSession 和ServletContext 对象,从而保持Action 与Servlet API 的解耦;
- 在Action 类中直接访问Servlet API,可以通过实现Struts2 提供的接口:ServletContextAware、ServletRequestAware、ServletResponseAware 完成,也可以通过ServletActionContext 工具类实现,但Action 将与Servlet API 直接耦合。
(三)实验内容及步骤
- 修改UserAction类,通过ActionContext获取请求、会话和上下文对象相关联的Map对象来实现存取属性的功能
//ActionContext方式获取请求、会话和上下文对象
private Map request, session, application;
public String login(){
//获取ActionContext对象
ActionContext ctx = ActionContext.getContext();
//获取请求、会话和上下文相关联的Map对象
request = (Map)ctx.get("request");
session = (Map)ctx.getSession();
application = (Map)ctx.getApplication();
//访问applicationn范围的属性值
Integer counter = (Integer) application.get("counter");
if(counter == null){
counter = 1;
}
else{
counter += 1;
}
application.put("counter", counter);
UserService userService = new UserService();
if(userService.login(loginUser)){
//设置session范围属性
session.put("user", loginUser.getAccount());
//设置request范围属性
request.put("tip", "您已登录成功");
return "loginsuccess";
}
else{
return "loginfail";
}
}- 修改loginSuccess.jsp页面,从请求、会话和上下文对象中获取属性值并显示
本站访问次数为:<s:property value="#application.counter"/>
<s:property value="#session.user"/>
<s:property value="#request.tip"/>
- 修改UserAction类,通过实现Struts提供的接口:RequestAware、SessionAware和AppliactionAware,获取请求、会话和上下文对象相关联的Map对象来实现存取属性的功能
public class UserAction extends ActionSupport implements RequestAware, SessionAware, ApplicationAware {
private UserBean loginUser;
private Integer count=0;
public UserAction(){
System.out.println("创建了一个UserAction类对象。");
}
public Integer getCount() {
return count;
}
public UserBean getLoginUser(){
return loginUser;
}
public void setLoginUser(UserBean loginUser){
this.loginUser = loginUser;
}
//接口方式实现
private Map request, session, application;
public void setRequest(Map<String, Object> request){
this.request = request;
}
public void setSession(Map<String, Object> session){
this.session = session;
}
public void setApplication(Map<String, Object> application){
this.application = application;
}
public String login(){
Integer counter = (Integer) application.get("counter");
if(counter == null){
counter = 1;
}
else{
counter += 1;
}
application.put("counter", counter);
UserService userService = new UserService();
if(userService.login(loginUser)){
session.put("user", loginUser.getAccount());
request.put("tip", "您已登录成功");
return "loginsuccess";
}
else{
return "loginfail";
}
}
}
- 修改UseAction,通过接口ServletContextAware、ServletRequestAware、ServletResponseAware直接访问ServletAPI,并实现上述功能
public class UserAction extends ActionSupport implements ServletContextAware, ServletRequestAware, ServletResponseAware {
private UserBean loginUser;
private Integer count=0;
private HttpServletRequest request;
private HttpServletResponse response;
private ServletContext application;
public UserAction(){
System.out.println("创建了一个UserAction类对象。");
}
public Integer getCount() {
return count;
}
public UserBean getLoginUser(){
return loginUser;
}
public void setLoginUser(UserBean loginUser){
this.loginUser = loginUser;
}
//ServletContextAware、ServletRequestAware、ServletResponseAware直接访问ServletAPI
public void setServletRequest(HttpServletRequest request){
this.request = request;
}
public void setServletContext(ServletContext application){
this.application = application;
}
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
public String login(){
Integer counter = (Integer) application.getAttribute("counter");
if(counter == null){
counter = 1;
}
else{
counter += 1;
}
application.setAttribute("counter", counter);
UserService userService = new UserService();
if(userService.login(loginUser)){
HttpSession session = request.getSession();
session.setAttribute("user", loginUser.getAccount());
request.setAttribute("tip", "您已登录成功");
return "loginsuccess";
}
else{
return "loginfail";
}
}
- 修改UserAction类,通过ServletActionContext工具类直接访问Servlet API,实现上述功能
//ServletActionContext工具类直接访问Servlet API
public String login(){
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ServletContext application = ServletActionContext.getServletContext();
HttpSession session = request.getSession();
Integer counter = (Integer) application.getAttribute("counter");
if(counter == null){
counter = 1;
}
else{
counter += 1;
}
application.setAttribute("counter", counter);
UserService userService = new UserService();
if(userService.login(loginUser)){
session.setAttribute("user", loginUser.getAccount());
request.setAttribute("tip", "您已登录成功");
return "loginsuccess";
}
else{
return "loginfail";
}
}
- 利用Servlet API添加购物车功能,在cn.edu.zjut.bean包中创建Item.java用于记录商品信息
package cn.edu.zjut.bean;
public class Item {
private String itemID;
private String name;
private String description;
private double cost;
public Item() {
}
public Item(String itemID, String name, String description, double cost) {
this.itemID = itemID;
= name;
this.description = description;
this.cost = cost;
}
public String getItemID() {
return itemID;
}
public void setItemID(String itemID) {
this.itemID = itemID;
}
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public double getCost() {
return cost;
}
public void setCost(double cost) {
this.cost = cost;
}
}- 在cn.edu.zjut.bean中创建ItemOrder.java用于记录购物车中的一条商品信息和购买数量
package cn.edu.zjut.bean;
public class ItemOrder {
private Item item;
private int numItems;
public ItemOrder() {
}
public ItemOrder(Item item){
setItem(item);
setNumItems(1);
}
public ItemOrder(Item item, int numItems) {
this.item = item;
this.numItems = numItems;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public int getNumItems() {
return numItems;
}
public void setNumItems(int numItems) {
this.numItems = numItems;
}
}- 在cn.edu.zjut.bean中常见ShoppingCart.java用于记录用户的购物车信息,为简化操作,在购物车的构造函数中加入商品信息
package cn.edu.zjut.bean;
import java.util.ArrayList;
import java.util.List;
public class ShoppingCart {
private List itemsOrdered;
public ShoppingCart() {
itemsOrdered = new ArrayList();
Item item = new Item("book001", "JAVAEE 技术实验指导教程",
"WEB 程序设计知识回顾、" + "轻量级JAVAEE 应用框架、"
+ "企业级EJB 组件编程技术、" + "JAVAEE 综合应用开发.", 19.95);
ItemOrder itemorder = new ItemOrder(item);
itemorder.setNumItems(2);
itemsOrdered.add(itemorder);
}
public List getItemsOrdered() {
return (itemsOrdered);
}
public synchronized void addItem(String itemID) {}
public synchronized void setNumOrdered(String itemID, int numOrdered) {}
}- 修改UserAction类的login方法,当登录成功时,创建ShoppingCart对象并存入会话中
if(userService.login(loginUser)){
session.setAttribute("user", loginUser.getAccount());
request.setAttribute("tip", "您已登录成功");
ShoppingCart shoppingCart = new ShoppingCart();
session.setAttribute("ShoppingCart", shoppingCart);
return "loginsuccess";
}- 修改loginSuccess.jsp页面,从会话中获取购物车信息并显示在页面中
<%@ taglib prefix="s" uri="/struts-tags" %>
<%--
Created by IntelliJ IDEA.
User: yiyi
Date: 2021/10/11
Time: 20:05
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功</title>
</head>
<body>
本站访问次数为:<s:property value="#application.counter"/>
<s:property value="#session.user"/>
<s:property value="#request.tip"/>
<br>
<table border="1">
<s:iterator value="#session.shoppingcart.itemsOrdered">
<tr>
<th>编号</th><th>名称</th><th>说明</th><th>单价</th><th>数量</th>
</tr>
<tr>
<td><s:property value="item.itemID"/> </td>
<td><s:property value="item.name"/> </td>
<td><s:property value="item.description"/> </td>
<td><s:property value="item.cost"/> </td>
<td><s:property value="numItems"/> </td>
</tr>
</s:iterator>
</table>
</body>
</html>
(四)实验总结
- ActionContext方式先通过获取的ActionContext对象,再通过get、getSession、getAppliaction方法获取相应的map对象;
- RequestAware, SessionAware, ApplicationAware接口方式通过设置setter方法获取request、session和application;
- ServletContextAware、ServletRequestAware、ServletResponseAware方法同样需要通过setter方法获取request、session和application;
- ServletActionContext工具类方法通过ServletActionContext对象的get方法获取相应对象;
- 1和2是Map类型,3和4是HttpServletRequest、HttpServletResponse和ServletContext类型的;
roperty value="#request.tip"/>
<s:iterator value="#session.shoppingcart.itemsOrdered"> </s:iterator>
编号 | 名称 | 说明 | 单价 | 数量 |
<s:property value=“item.itemID”/> | <s:property value=“item.name”/> | <s:property value=“item.description”/> | <s:property value=“item.cost”/> | <s:property value=“numItems”/> |
(四)实验总结
- ActionContext方式先通过获取的ActionContext对象,再通过get、getSession、getAppliaction方法获取相应的map对象;
- RequestAware, SessionAware, ApplicationAware接口方式通过设置setter方法获取request、session和application;
- ServletContextAware、ServletRequestAware、ServletResponseAware方法同样需要通过setter方法获取request、session和application;
- ServletActionContext工具类方法通过ServletActionContext对象的get方法获取相应对象;
- 1和2是Map类型,3和4是HttpServletRequest、HttpServletResponse和ServletContext类型的;
















