一、搭建一个简单struts2应用
1、引入工程所需运行库文件
目前我用到的Struts版本为2.1.8.1 GA。
把以下几个运行库文件复制到工程的WEB-INF下的lib文件夹中。
2、在web.xml中配置FilterDispatcher
配置WEB-INF下的web.xml文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<?
xml
version="1.0" encoding="UTF-8"?>
<
web-app
version="2.5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
<
filter
>
<
filter-name
>struts2</
filter-name
>
<
filter-class
>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</
filter-class
>
</
filter
>
<
filter-mapping
>
<
filter-name
>struts2</
filter-name
>
<
url-pattern
>/*</
url-pattern
>
</
filter-mapping
>
</
web-app
>
|
- Struts2的核心控制器FilterDispatcher被设计成了过滤器,通过<filter></filter>标签引入。
- <url-pattern>/*</url-pattern>说明所有客户端请求都经由FilterDispatcher处理,并把过滤后的请求交给Struts2进行处理。
3、编写Action
- Struts2直接使用Action来封装HTTP请求参数,因此Action类应该包含与请求相对应的属性,并为该属性提供对应的setter和getter方法。
- 为Action类里增加一个execute方法,因为Struts2框架默认会执行这个方法。这个方法本身并不做业务逻辑处理,而是调用其他业务逻辑组件完成这部分工作。
- Action类返回一个标准的字符串,该字符串是一个逻辑视图名,该视图名对应实际的物理视图。
我们现在要实现的是一个用户登录验证,因此Action中提供用户名和密码两个属性。如果正确返回success否则返回error
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package
wwfy.action.user;
public
class
UserAction {
private
String username;
private
String password;
public
String getUsername() {
return
username;
}
public
void
setUsername(String username) {
this
.username = username;
}
public
String getPassword() {
return
password;
}
public
void
setPassword(String password) {
this
.password = password;
}
public
String execute()
throws
Exception {
// 只有用户名为wwfy,密码为123456方可成功登陆
if
(username.equals(
"wwfy"
) && password.equals(
"123456"
)) {
return
"success"
;
}
else
{
return
"error"
;
}
}
}
|
Action有一下特点:
- Struts2框架中Action是一个POJO,没有被代码污染。
- Struts2中的Action的execute方法不依赖于servlet API,改善了Struts1中耦合过于紧密,极大方便了单元测试。
- Struts2的Action无须用ActionForm封装请求参数。
- 相对Struts1框架而言,Struts2的逻辑视图不再是ActionForward对象,而是一个普通的字符串,利于分离和复用。
4、配置struts.xml
Struts2框架的核心配置文件就是struts.xml,该文件主要负责Struts2应用中各Action的具体实现逻辑。struts.xml会根据不同请求找到具体的Action,然后根据Action返回的逻辑视图名找到具体的物理视图。
在WEB-INF/classes文件夹下创建struts.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<?
xml
version="1.0" encoding="UTF-8"?>
<!
DOCTYPE
struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
<
struts
>
<
package
name="wwfy" extends="struts-default">
<
action
name="loginUser" class="wwfy.action.user.UserAction">
<
result
name="success">/jsp/error.jsp</
result
>
<
result
name="error">/jsp/error.jsp</
result
>
</
action
>
</
package
>
</
struts
>
|
- 该文件发布的时候必须放置在WEB-INF/classes路径下,当程序运行的时候会自动在该目录下搜索struts.xml。
- 在action标签中定义了name和class。name属性对应的是用户URL请求中的action名,比如在本应用中,用户请求为http://localhost:8080/Struts2/loginUser.action,那么name属性就应该为loginUser。class属性是处理请求的实现类(注意:要包含完整路径),本应用的实现类是wwfy.action.user.UserAction。
- result标签定义逻辑视图和物理视图之间的映射,在我们的Action中,如果返回的字符串是"success”则由对应的success.jsp页面进行处理;如果返回的字符串是"error”则由error.jsp页面进行处理。
5编写视图资源
1、登陆页面login.jsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<%@ page language="java" import="java.util.*" pageEncoding="GB2312"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!
DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<
html
>
<
head
>
<
title
>登陆页面</
title
>
</
head
>
<
body
>
<
center
>
<
s:form
action="loginUser">
<
s:textfield
name="username" label="用户名"></
s:textfield
>
<
s:password
name="password" label="密码"></
s:password
>
<
s:submit
value="确定"/>
<
s:reset
value="重置"/>
</
s:form
>
</
center
>
</
body
>
</
html
>
|
2、登陆成功页面success.jsp
1
2
3
4
5
6
7
8
9
10
11
12
|
<%@ page language="java" import="java.util.*" pageEncoding="GB2312"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!
DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<
html
>
<
head
>
<
title
>成功页面</
title
>
</
head
>
<
body
>
<
p
align="center">登陆成功!!!您的用户名是<
s:property
value="username"></
s:property
></
p
>
</
body
>
</
html
>
|
3、登陆失败页面error.jsp
1
2
3
4
5
6
7
8
9
10
11
12
|
<%@ page language="java" import="java.util.*" pageEncoding="GB2312"%>
<!
DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<
html
>
<
head
>
<
title
>失败页面</
title
>
</
head
>
<
body
>
<
p
align="center">登陆失败!!!</
p
>
</
body
>
</
html
>
|
页面中很多以s:开头的标签,这些是Struts2框架独有的标签库.
整个应用的目录结构是
二、Action的传值方式
1、字段驱动方式
所谓字段驱动方式就是通过字段进行数据传递。在Struts2中我们可以直接在Action里定义各种Java基本类型的字段,使这些字段与表单数据相对应,并利用这些字段进行数据传递。
UserAction.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package
wwfy.action.user;
public
class
UserAction {
private
String username;
private
String password;
public
String getUsername() {
return
username;
}
public
void
setUsername(String username) {
this
.username = username;
}
public
String getPassword() {
return
password;
}
public
void
setPassword(String password) {
this
.password = password;
}
public
String execute()
throws
Exception {
System.out.print(username+
"--------"
+password);
// 只有用户名为wwfy,密码为123456方可成功登陆
if
(username.equals(
"wwfy"
) && password.equals(
"123456"
)) {
return
"success"
;
}
else
{
return
"error"
;
}
}
}
|
这个Action中的定义了两个字符串字段"username”和"password”,这两个字段分别对应登陆页面上的“用户名”和“密码”两个表单域。
2、模型驱动方式
所谓模型驱动方式是指通过JavaBean模型进行数据传递。采用这种方式,JavaBean所封装的属性与表单的属性一一对应,JavaBean将成为数据传递的载体。使用模型驱动方式,Action类通过get*()的方法来获取模型,其中“*”代表具体的模型对象。
首先,我们创建一个模型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package
wwfy.javabean.vo;
public
class
User {
private
String username;
private
String password;
public
String getUsername() {
return
username;
}
public
void
setUsername(String username) {
this
.username = username;
}
public
String getPassword() {
return
password;
}
public
void
setPassword(String password) {
this
.password = password;
}
}
|
接下来定义Action类,两个字段已经不再单独定义,而是定义一个User类型的域模型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package
wwfy.action.user;
import
wwfy.javabean.vo.User;
public
class
User2Action {
private
User user;
public
User getUser() {
return
user;
}
public
void
setUser(User user) {
this
.user = user;
}
public
String execute()
throws
Exception{
if
(user.getUsername().equals(
"wwfy"
)&&user.getPassword().equals(
"123456"
)){
return
"success"
;
}
else
{
return
"error"
;
}
}
}
|
在使用模型驱动传值的时候需要注意,如果JSP页面是负责取值的,那么取值的格式必须为“模型对象名.属性名”;如果JSP页面是负责传值的,那么传值的格式可以为“模型对象名.属性名”,也可以直接是“属性名”。
接下来对登陆页和成功页进行改动:
login2.jsp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<%@ page language="java" import="java.util.*" pageEncoding="GB2312"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!
DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<
html
>
<
head
>
<
title
>登陆页面</
title
>
</
head
>
<
body
>
<
center
>
<
s:form
action="loginUser2">
<
s:textfield
name="user.username" label="用户名"></
s:textfield
>
<
s:password
name="user.password" label="密码"></
s:password
>
<
s:submit
value="确定"/>
<
s:reset
value="重置"/>
</
s:form
>
</
center
>
</
body
>
</
html
>
|
success2.jsp:
1
2
3
4
5
6
7
8
9
10
11
12
|
<%@ page language="java" import="java.util.*" pageEncoding="GB2312"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!
DOCTYPE
HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<
html
>
<
head
>
<
title
>成功页面</
title
>
</
head
>
<
body
>
<
p
align="center">登陆成功!!!您的用户名是<
s:property
value="user.username"></
s:property
></
p
>
</
body
>
</
html
>
|
struts.xml里增加配置
1
2
3
4
|
<
action
name="loginUser2" class="wwfy.action.user.User2Action">
<
result
name="success">/jsp/success2.jsp</
result
>
<
result
name="error">/jsp/error.jsp</
result
>
</
action
>
|
这样就完成了模型驱动传值.
三、Action中访问ServletAPI
1、通过ActionContext访问Servlet API
ActionContext类提供了一个静态方法getContext(),该方法返回一个ActionContext的实例。该实例提供了一些访问Servlet API的方法,通常的方法是
返回值 | 方法名 | 功能描述 |
ActionContext | getContext() | 获取系统的ActionContext实例 |
Map | getSession() | 返回一个Map实例,该对象存入HttpSession实例。 |
void | setSession(Map session) | 直接传入一个Map实例,将实例总得key、value对应转换成session的属性名、属性值 |
Map | getApplication() | 返回一个Map对象,该对象存入ServletContext实例 |
void | setApplication() | 直接传入一个Map实例,将实例中的key、value对应转换成application的属性名、属性值 |
Map | getParameters() | 获得所有请求参数。类似于调用HttpServletRequest对象的getParameterMap方法 |
实际上Struts2是把Map对象模拟成ServletContext对象和HttpSession对象,从而将Servlet API从Action中分离出来。
1
2
3
4
5
6
7
|
ActionContext ctx = ActionContext.getContext();
//获得Session
Map session = ctx.getSession();
//获得Application
Map application = ctx.getApplication();
|
在通常的web开发中Request和Response对象比较常见,但在Struts2框架中由于Action能与JSP页面进行数据交互,所以通常都不会用到这两个对象。如果想在Struts2程序中用到这两个对象,也有解决方法。Struts2提供了一个ServletActionContext类,在这个类中包含了一些方法,能够获得和设置request和response对象,并且还能获得ServletContext对象:
返回值 | 方法名 | 功能描述 |
HttpServletRequest | getRequest() | 获得Web应用的HttpServletRequest对象 |
HttpServletResponse | getResponse() | 获得Web应用的HttpservletResponse对象 |
ServletContext | getServletContext() | 获得Web应用的ServletContext对象 |
1
2
3
4
5
6
7
8
9
10
11
12
|
//获得HttpServletRequest
HttpServletRequest request = ServletActionContext.getRequest();
//获得HttpServletResponse
HttpServletResponse response = ServletActionContext.getResponse();
//获得HttpSession
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession();
//获得ServletContext
ServletContet sc = ServletActionContext.getServletContext();
|
2、通过实现*Aware接口获得Servlet API
比如在某个Action中要获得Session对象,就可以让该Action实现SessionAware接口。当然除了获得Session外,我们还可以获得其他对象:
实现接口名称 | 获得Servlet对象的方法 |
ApplicationAWare | void setApplication(Map application) |
CookiesAware | void setApplication(Map cookies) |
RequestAware | void setRequest(Map request) |
ServletRequestAware | void setApplication(HttpServletRequest request) |
ServletResponseAware | void setApplication(HttpServletResponse response) |
SessionAware | void setSession(Map session) |