Action作为Structs2的核心,主要包含对用户处理的逻辑,即是控制器。
struts2在对请求参数还是输出参数都在Action类中提供属性,当然属性包含对应的setter与getter方法。不仅能得到请求的参数,如果设置属性,还能再JSP页面通过<s:property value="tip" />得到tip属性的值。
实现Action接口
接口中包括五个常量值,与一个execute方法,五个常量为ERROR、INPUT、LOGIN、NONE、SUCCESS。
ActionSupport基类
基类继承Action接口与Validateable,封装一些默认方法,简化Action的开发。
Action访问ServletAPI
关于用法,无非是ActionContext ctx=ActionContext.getContext();得到ActionContext基类,通过getApplication()、getParameters()、getSession()等得到对象,或者通过set方法设置内容,不过,对象都是为Map类型。
package app.action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport{
private String username;
private String password;
private String mark;
public String getMark() {
return mark;
}
public void setMark(String mark) {
this.mark = mark;
}
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(){
if(getUsername().endsWith("admin")&&getPassword().endsWith("admin")){
//ActionContext.getContext().getSession().put("user", getUsername());
ActionContext ctx=ActionContext.getContext();
Integer counter=(Integer) ctx.getApplication().get("struts.i18n.encoding");
System.out.println(counter);
if(counter==null){
counter=1;
}else{
counter+=1;
}
mark="我是标签";
ctx.getApplication().put("counter", counter);
ctx.getSession().put("user", username);
ctx.put("tip", "登录成功了哦");
return "success";
}else{
return "error";
}
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
登录成功!<br/>
我是标签,存储在内存中:<s:property value="mark"/> <br/>
访问次数,我存在Application中:${applicationScope.counter} <br/>
访问用户,我存在Session中: ${sessionScope.user} <br/>
返回消息,我存在response中:${requestScope.tip}
</body>
</html>
这项来设置Servlet中的内容和通过JSP页面的标签访问Servlet中的内容。
Action直接访问ServletAPI
通过实现接口, ServletContextAware 、ServletRequestAware 、ServletResponseAware , 同时申明对象,及实现set方法,得到servlet对象。
使用ServletActionContext访问
通过工具类ServletActionContext的静态方法getPageContext()、getRequest()、getResponse()、getServletContext()访问PageContext、HttpServletRequest、HttpServletResponse、ServletContext对象。
有关于Action的配置
包和命名空间
在Struts的配置文件中定义Action都是通过package下的action的子元素完成。package主要包括四个属性:
name:必须属性,指定该包名字,以便被其他包引用。
extends:可选属性,可以继承其他包。
namespace :可选属性,定义该包的命名空间。
abstract :可选属性,指定该包是否为抽象包,如果为抽象包,不能包含Action的定义。
由于Struts配置文件从上到下处理,所以父包放在子包前面。
当一个包,初始继承struts-default,struts-default这个包在Struts内部已经定义,并且是个抽象包,包含大量的的类型定义,拦截器定义等,是配置Action的基础。
命名空间来管理访问地址,即当指定包的命名空间后,访问该包下的Action是命名空间+Action名
/book/test.action首先会去到/book这个命名空间寻找名为test 的actio,如果不存在,再去默认的命名空间寻找,如果都未找到,就报错错误。
如果存在这种情况/book/search/test.action,系统会首先去/book/search/命名空间去寻找,如果未找到,不会进入/book命名空间,会直接进入默认命名空间寻找。
Action的基本配置
Action就是一个逻辑控制器,只是在处理完请求后,发送指定的视图给用户。name为必须属性,指定名称,如果需要在name属性中使用/,则需要设置常量stuts.enable.SlashesInActionNames为true,如果使用.或者-,会引发一些未知异常,最好不使用。class不是必须属性,不指定,则会指向系统默认的ActionSupport。
Action的动态方法调用
Action的动态方法调用就是在Action的地址后面加上!再加上访问名,如果是login!regist则会指向注册了login这个action类里,去找这个regist方法,执行这个方法的内容,按照regist方法的逻辑进行,达到使用同一个Action的不同方法处理用户的请求。 相应的默认的login 会访问execute方法。
这个动态方法的开关也是通过常量设置。struts.enable.DynamicMethodInvocation 。
指定method属性及使用通配符
通过指定method属性,让action调用指定的方法,而不是通过execute方法。
<action name="regist" class="app.action.LoginRegistAction" method="regist">
。。。
</action>
这样指定regist ,则调用类中的regist方法。
通配符:
<action name="*Action" class="app.action.LoginRegistAction" method="{1}">
。。。。
</action>
假若loginAction访问,则用LoginRegistAction类中的login方法。
name属性中*代表一个或多个任意字符,在class、method属性{N},代表前面第N个*号所匹配的字符串。
<action name="*Action" class="app.action.{1}Action">
。。。。
</action>
假若loginAction访问,则用loginAction类中的execute方法。
再复杂点例子
<action name="*_*" class="app.action.{1}Action" method="{2}">
...
</action>
假若Test_abc访问,则会使用TestAction类来处理,并调用abc方法
同样的,对result 也会起作用,终极测试
<action name="*_*_*" class="app.action.{1}Action" method="{2}">
<result name="success">/{3}.jsp</result>
</action>
倘若Test_abc_welcome访问,则会使用TestAction类来处理,并调用abc方法,如果返回success,则跳转到welcome.jsp页面。
Action里面配置了*,明显就会出现符合多个请求的Action,假若有三个Action,abcAction、*Action、*,如果访问名为abcAction,毫无疑问,肯定是进入到abcAction,假若是aAction,这里的先后顺序,则是在配置文件中,谁先搜寻到,就访问谁,不存在谁更优先匹配到。除非请求属性相同,不然的话则按照在配置文件中的先后顺序决定有谁处理请求。
配置默认Action
<default-action-ref name="defaultView" />
<action name="defaultView" class="app.action.TestAction">
<result name="success">/welcome.jsp</result>
</action>
当用户找不到对应的action时,就用设置的defaultView请求,则会执行defaultView。action请求,使用TestAction类的execute方法。
配置Action的默认处理类
<default-class-ref class="app.action.TestAction" />
假若Action不指定class属性,则使用系统默认的ActionSupport 作为Action类(条件是继承了struts-default包),应为在struts-default.xml文件中有如下配置。
<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
假若指定,在不指定Action的class属性,则会使用TestAction类。