对于Struts2应用的开发者而言,Action才是应用的核心,开发者需提供大量的Action类,并在struts.xml文件中配置Action;Action类里包含了对用户请求的处理逻辑,Action类也被称为业务控制器
相对Struts1而言,Struts2采用低侵入方式的设计,Struts2不要求Action类继承任何Struts2基类或实现任何Struts2接口;在这种设计方式下,Struts2的Action类是一个普通的POJO(通常应包含一个无参的execute方法),从而有很好的代码复用性
Struts2通常直接使用Action封装HTTP请求参数,因此,Action类还应包含请求参数对应的属性,并提供对应的setter、getter方法
//处理用户请求的Action类,只是一个POJO,无须继承任何基类,无须实现任何接口 public class LoginAction { // 提供两个属性来封装HTTP请求参数 private String user; private String pass; // 省略getter、setter方法 // Action类默认处理用户请求的逻辑控制方法 public String execute() { ...... // 返回处理结果字符串 return resultStr; } }
即使Action需处理的请求包含user和pass两个HTTP请求参数,Action类也可不包含user和pass Field;因为系统是通过对应的getter和setter方法来处理请求参数的
Action类里的属性,不仅可用于封装请求参数,还可用于封装处理结果
(1)、Action接口和ActionSupport基类
为了让用户开发的Action类更规范,Struts2提供了一个Action接口,这个接口定义了Struts2的Action处理类应该实现的规范
public interface Action { // 定义Action接口里包含的一些结果字符串;作用就是统一execute方法的返回值 public static final String ERROR = "error"; public static final String INPUT = "input"; public static final String LOGIN = "login"; public static final String NONE = "none"; public static final String SUCCESS = "success"; // 定义处理用户请求的execute方法S public String execute() throws Exception; }
Struts2为Action接口提供了一个实现类:ActionSupport
public class ActionSupport implements Action,Validatable,ValidationAware,TextProvider,LocaleProvider,Serializable{ // 收集校驗錯誤的方法 public void setActionErrors(Collection errorMessages) { validationAware.setActionErrors(errorMessages); } //返回校验错误的方法 public Collection getActionErrors(){ return validationAware.getActionErrors(); } public void setActionMessages(Collection messages){ validationAware.setActionMessages(messages); } public Collection getActionMessages(){ return validationAware.getActionMessages(); } ...... //设置表单域校验错误信息 public void setFieldErrors(Map errorMap){ validationAware.setFieldErrors(errorMap); } //返回表单域校验错误信息 public Map getFieldErrors(){ return validationAware.getFieldErrors(); } //控制Locale的相关信息 public Locale getLocale(){ return ActionContext.getContext().getLocale(); } public String getText(String aTextName){ return textProvider.getText(aTextName); } //返回国际化信息的方法 public String getText(String aTextName,String defaultValue){ return textProvider.getText(aTextName,defaultValue); } public String getText(String aTextName,String defaultValue,String obj){ return textProvider.getText(aTextName,defaultValue,obj); } ...... //用户访问国际化资源包的方法 public ResourceBundle getTexts(){ return textProvider.getTexts(); } public ResourceBundle getTexts(String aBundleName){ return textProvider.getTexts(aBundleName); } //添加错误信息 public void addActionError(String anErrorMessage){ validationAware.addActionError(anErrorMessage); } public void addActionMesaage(String aMessage){ validationAware.addActionMessage(aMessage); } //添加字段校验失败的错误信息 public void addFieldError(String fieldName,String errorMessage){ vlidationAware.addFieldError(fieldName,errorMessage); } //默认的input方法,直接返回INPUT字符串 public String input() throws Exception{ return INPUT; } public String doDefault() throws Exception{ return SUCCESS; } //默认的处理用户请求的方法,直接返回SUCCESS字符串 public String exceute() throws Exception{ return SUCCESS; } ...... //清除所有错误信息的方法 public void clearErrorsAndMessages(){ validationAware.clearErrorsAndMessages(); } //包含空的输入校验方法 public void validate(){ } public Object clone() throws CloneNotSupportedException{ return super.clone(); } ...... }
(2)、Action访问ServletAPI
1)、通过ActionContext类来访问ServletAPI
ActionContext类中包含的常用方法:
static ActionContext getContext():获取系统的ActionContext实例
Object get(Object key):类似HttpServletRequest的getAttribute(String name)
put(String key,Object value):类似HttpServletRequest的setAttribute(String key,Object value)
Map getSession():返回一个Map对象,模拟了HttpSession实例
Void setSession(Map session):直接传入一个Map实例,将该Map实例里的key-value对转换成session、application的属性名、属性值
void setApplication(Map application):直接传入一个Map实例,将该Map实例里的key-value对转换成session、application的属性名、属性值
Map getApplication():返回一个Map对象,模拟了ServletContext实例
Map getParameters():获取所有的请求参数,类似于HttpServletRequest的getParameterMap()
LoginAction.java: public class LoginAction implements Action { private String username; private String password; // 省略setter、getter方法 public String execute() throws Exception { ActionContext ctx = ActionContext.getContext(); // 通过ActionContext访问application范围的属性值 Integer counter = (Integer) ctx.getApplication().get("counter"); if (counter == null) { counter = 1; } else { counter = counter + 1; } // 通过ActionContext设置application范围的属性 ctx.getApplication().put("counter", counter); // 通过ActionContext设置session范围的属性 ctx.getSession().put("user", getUsername()); if (getUsername().equals("crazyit.org") && getPassword().equals("lbd")) { // 通过ActionContext设置request范围的属性 ctx.put("tip", "服务器提示:您已经成功的登录"); return SUCCESS; } else { // 通过ActionContext设置request范围的属性 ctx.put("tip", "服务器提示:登录失败"); return ERROR; } } }
struts.xml: <constant name=”conststruts.devMode” value=”true”/> <package name=”lee” extends=”struts-default”> <action name=”login” class=”org.crazyit.app.action.LoginAction”> <result name=”error”>/error.jsp</result> <result name=”sucess”>/sucess.jsp</result> </action> </package>
welcome.jsp: ${applicationScope.counter} ${sessionScop.user} ${requestScop.tip}
2)、Action接口直接访问ServletAPI
ServletContextAware:实现该接口的Action可直接访问Web应用的ServletContext实例
ServletRequestAware:实现该接口的Action可直接访问用户请求的HttpServletRequest实例
ServeltResponseAware:实现该接口的Action可直接访问服务器响应的HttpServletResponse实例
SessionAware:
LoginAction.java: package webDemo; public class LoginAction implements Action, ServletResponseAware { private String username; private String password; private HttpServletResponse response; // 省略setter、getter方法 // 重写实现ServletResponseAware接口必须实现的方法 @Override public void setServletResponse(HttpServletResponse response) { this.response = response; } public String execute() throws Exception { ActionContext ctx = ActionContext.getContext(); // 通过ActionContext访问application范围的属性值 Integer counter = (Integer) ctx.getApplication().get("counter"); if (counter == null) { counter = 1; } else { counter = counter + 1; } // 通过ActionContext设置application范围的属性 ctx.getApplication().put("counter", counter); // 通过ActionContext设置session范围的属性 ctx.getSession().put("user", getUsername()); if (getUsername().equals("crazyit.org") && getPassword().equals("lbd")) { // 通过response添加Cookie Cookie c = new Cookie("user", getUseranme()); c.setMaxAge(60 * 60); response.addCookie(c); // 通过ActionContext设置request范围的属性 ctx.put("tip", "服务器提示:您已经成功的登录"); return SUCCESS; } else { // 通过ActionContext设置request范围的属性 ctx.put("tip", "服务器提示:登录失败"); return ERROR; } } }
实现ServletResponseAware接口,必须实现:public void setServletResponse(HttpServletResponse response);
实现ServletRequestAware接口,必须实现:public void setServletRequest(HttpServletRequest request)
实现ServeltContextAware接口,必须实现:public void setServletContext(Servlet context);
实现SessionAware接口,必须实现:public void setSession(Map<String, Object> session);
3)、使用ServletActionContext工具类直接访问Servlet API
ServeletActionContext常用静态方法:
static PageContext getPageContext():取得Web应用的PageContext对象
static HttpServletRequest getRequest():取得Web应用的HttpServletRequest对象
static HttpServletResponse getResponse():取得Web应用的HttpServletResponse对象
static ServletContext getServletContext():取得Web应用的ServletContext对象