GitHub 地址
访问GitHub下载最新源码:https://github.com/JYG0723/Struts2_Action
访问 Servlet Api
Struts2 不再与 Servlet Api 进行耦合,但任提供了三种方式去访问 Servlet Api
- ActionContext :上下文的类,通过它获取相关的对象。Map 方式
- Aware :实现 Aware 接口。
- ServletActionContex:与 ActionContext 类似。
Action 的搜索顺序
- url:
http://127.0.0.1:8080/struts2/path1/path2/student.action
- 首先根据 url 路径判断
namespace
为/path1/path2
的 package 是否存在。- 存在:判断 action 是否存在,如果不存在则去默认
namespace
的 package 里寻找。及namespace
为/
的 package 下。如果还不存在则报错。 - 不存在:检查上一级路径的 package 是否存在(直到默认 namespace),即
namespace
为path1
的 package。如果没有报错。
- 存在:判断 action 是否存在,如果不存在则去默认
动态方法调用
动态方法调用为了解决一个 Action 对应多个请求的处理。以免 Action 太多,Struts2 对其有三种实现方式:
- 指定method属性。容易出现太多 xml文件中出现太多 action,不推荐
- 感叹号方式。官方不推荐,这里不写例子了。(请求写的和屎一样)
- 需要配置常量。并且配置 package 标签的
strict-method-invocation="false"
- 需要配置常量。并且配置 package 标签的
- 通配符方式,相比较而言推荐
- 需要配置 package 标签的
strict-method-invocation="false"
- 需要配置 package 标签的
指定method属性
struts.xml
<package name="default" namespace="/" extends="struts-default">
<action name="helloworld" class="action.HelloWorldAction">
<!-- action 的 method 属性默认 execute -->
<!-- result 的 name 属性默认 success -->
<result>/result.jsp</result>
</action>
<action name="add" class="action.HelloWorldAction" method="add">
<!-- result 的 name 属性默认 success -->
<result>/add.jsp</result>
</action>
</package>
HelloWorldAction
public class HelloWorldAction extends ActionSupport {
public String add() {
return SUCCESS;
}
@Override
public String execute() throws Exception {
System.out.println("执行Action");
return SUCCESS; // = "success"
}
}
url:http://localhost:8080/struts2/add.action
通配符方式
struts.xml
<package name="default" namespace="/" extends="struts-default" strict-method-invocation="false">
<action name="helloworld_*" method="{1}" class="action.HelloWorldAction">
<!-- 默认 success -->
<result>/result.jsp</result>
<result name="add">/{1}.jsp</result>
<result name="update">{1}.jsp</result>
</action>
</package>
HelloWorldAction
public class HelloWorldAction extends ActionSupport {
public String add() {
return "add";
}
public String update() {
return "update";
}
@Override
public String execute() throws Exception {
System.out.println("执行Action");
return SUCCESS; // = "success"
}
}
url:http://localhost:8080/struts2/helloworld_update.action
多配置文件
helloworld.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="default" namespace="/" extends="struts-default" strict-method-invocation="false">
<action name="helloworld_*" method="{1}" class="action.HelloWorldAction">
<!-- 默认 success -->
<result>/result.jsp</result>
<result name="add">/{1}.jsp</result>
<result name="update">/{1}.jsp</result>
</action>
<!--
<action name="add" class="action.HelloWorldAction" method="add">
<result>/add.jsp</result>
</action>
-->
</package>
</struts>
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<include file="helloworld.xml"></include>
</struts>
默认 Action
默认 Action,即如果用户输入的路径有误,找不到对应的 Action,就可以用该 Action 来向用户展示默认页面。防止出现 404 影响用户体验。
<package name="default" namespace="/" extends="struts-default" strict-method-invocation="false">
<default-action-ref name="index"></default-action-ref>
<action name="index">
<!-- 默认 success -->
<result>/error.jsp</result>
</action>
</package>
url:http://localhost:8080/struts2/***.action
Struts2 后缀
struts.xml
<struts>
<include file="helloworld.xml"></include>
<constant name="struts.action.extension" value="html"></constant>
</struts>
url:http://localhost:8080/struts2/helloworld_add.html
<struts>
<include file="helloworld.xml"></include>
</struts>
url:http://localhost:8080/struts2/helloworld_add
注意:
比较有趣的一点是。默认 Struts2 访问 Action 不加.action
后缀也是可以根据名称访问到对应 Action 的。但是如果配置了该struts.action.extension
常量,并且 value 设值了,那么不添加后缀是访问不到的。如果该 value 没有设值,那么任然可以继续不带尾缀访问对应 Action。
struts.propertis
### 指定后缀为 .action 形式的请求可被 Struts2 处理,默认为action。可配置多个请求后缀,用 , 隔开
struts.action.extension=action,do,struts2,
web.xml
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>struts.action.extension</param-name>
<param-value>do</param-value>
</init-param>
</filter>
接受参数
Struts2 的 Action 是如何接收参数的:
- 使用 Action 的属性接收参数
- 使用 DomainModel 接受参数
- 使用 ModelDriven 接受参数
Action 的属性接收
LoginAction
public class LoginAction extends ActionSupport {
private String username;
private String password;
public String login() {
System.out.println(username + ":" + password);
return SUCCESS;
}
// getter/setter
}
struts.xml
<action name="LoginAction" method="login" class="action.LoginAction">
<!-- 默认 success -->
<result>/success.jsp</result>
</action>
login.jsp
<form action="LoginAction.action" method="post">
用户名: <input type="text" name="username">
密码: <input type="password" name="password">
</form>
DomainModel 接受
LoginAction
public class LoginAction extends ActionSupport {
private User user;
public String login() {
System.out.println(user.getUsername()+ ":" + user.getPassword());
return SUCCESS;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
User
public class User {
private String username;
private String password;
getter/setter
}
login.jsp
<form action="LoginAction.action" method="post">
用户名: <input type="text" name="user.username">
密码: <input type="password" name="user.password">
<input type="submit" value="提交">
</form>
ModelDriven 方式接收
LoginAction
public class LoginAction extends ActionSupport implements ModelDriven<User>{
private User user = new User();
public String login() {
System.out.println(user.getUsername()+ ":" + user.getPassword());
return SUCCESS;
}
@Override
public User getModel() {
return user;
}
}
login.jsp
<form action="LoginAction.action" method="post">
用户名: <input type="text" name="username">
密码: <input type="password" name="password">
<input type="submit" value="提交">
</form>
复杂参数请求
User
public class User {
private String username;
private String password;
private List<User> userList;
// getter/setter
}
login.jsp
<form action="LoginAction.action" method="post">
用户名: <input type="text" name="username">
密码: <input type="password" name="password">
用户名1:<input type="text" name="userList[0].username">
用户名2:<input type="text" name="userList[1].username">
用户名3:<input type="text" name="userList[2].username">
<input type="submit" value="提交">
</form>
LoginAction
public class LoginAction extends ActionSupport implements ModelDriven<User> {
private User user = new User();
public String login() {
System.out.println(user.getUsername() + ":" + user.getPassword() + ": 用户名1:"
+ user.getUserList().get(0).getUsername() + ": 用户名2:"
+ user.getUserList().get(1).getUsername());
return SUCCESS;
}
@Override
public User getModel() {
return user;
}
}
处理结果类型
LoginAction
public class LoginAction extends ActionSupport{
···
}
ActionSupport
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
···
}
Action
package com.opensymphony.xwork2;
public interface Action {
String SUCCESS = "success";
String NONE = "none";
String ERROR = "error";
String INPUT = "input";
String LOGIN = "login";
String execute() throws Exception;
}
- SUCCESS:Action 正确的执行完成。返回相应的视图,success 是 name 属性默认值
- NONE:表示 Action 正确的执行完成,但并不返回任何视图
- ERROR:表示 Action 执行失败,返回到错误处理视图
- LOGIN:Action 因为用户没有登录的原因没有正确执行,将返回该登录视图,要求用户进行登录验证
- INPUT :Action 的执行,需要从前段页面获取参数,INPUT 就是代表这个参数输入的界面,一般在应用中,会对这些参数进行验证,如果验证没有通过,将自动返回到该视图。
INPUT 用法示例
struts.xml
<action name="LoginAction" method="login" class="action.LoginAction">
<!-- 默认 success -->
<result>/success.jsp</result>
<result name="input">/login.jsp</result>
</action>
login.jsp
<%@ taglib prefix="s" uri="/struts-tags" %>>
···
<form action="LoginAction.action" method="post">
用户名: <input type="text" name="username"><s:fielderror name="username"></s:fielderror>
密码: <input type="password" name="password">
用户名1:<input type="text" name="userList[0].username">
用户名2:<input type="text" name="userList[1].username">
年龄:<input type="text" name="age">
<input type="submit" value="提交">
</form>
LoginAction
public class LoginAction extends ActionSupport implements ModelDriven<User> {
···
@Override
public void validate() {
if (user.getUsername() == null || "".equals(user.getUsername())) {
this.addFieldError("username", "用户名不能为空");
}
}
}
注意:
这里的addFieldError
方法的username
参数对应 jsp 页面<S:>
标签的 name 属性。
result 标签
<result name = "" type = ""> </result>
这里的 type 属性默认是 dispatcher 即转发。页面是通过请求转发调度过去,支持 jsp 引擎。
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.result.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.result.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.result.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.result.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.result.PlainTextResult" />
<result-type name="postback" class="org.apache.struts2.result.PostbackResult" />
</result-types>