为了让用户开发的Action类更规范,Struts2提供了一个Action接口,这个接口定义了Struts2的Action处理类应该实现的规范。下面是Action接口的源码:
public interface Action {
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";
public String execute( ) throws Exception;
}
上面的Action接口里只定义了一个execute方法,该接口的规范规定了Action类应该包含一个execute方法,该方法返回一个字符串。除此之外,该接口还定义了5个字符串常量,它们的作用是统一execute方法的返回值。例如当Action类处理用户请求成功后,有人喜欢返回welcome字符串,有人喜欢返回success字符串......这样不利于项目的统一管理。Action接口定义了如上5个字符串常量,分别代表了特定的含义。当然如果开发者依然希望使用特定的字符串作为逻辑视图名,依然可以返回自己的视图名。
另外,Struts2为Action接口提供了一个实现类:ActionSupport:
public class ActionSupport implements Action, Validateable, ValidationAware,
TextProvider, LocaleProvider, Serializable {
protected static Logger LOG = LoggerFactory.getLogger(ActionSupport.class);
private final transient TextProvider textProvider =
new TextProviderFactory().createInstance(getClass(), this);
private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
public void setActionErrors(Collection<String> errorMessages) {
validationAware.setActionErrors(errorMessages);
}
public Collection<String> getActionErrors() {
return validationAware.getActionErrors();
}
public void setActionMessages(Collection<String> messages) {
validationAware.setActionMessages(messages);
}
public Collection<String> getActionMessages() {
return validationAware.getActionMessages();
}
/**
* @deprecated Use {@link #getActionErrors()}.
*/
@Deprecated public Collection<String> getErrorMessages() {
return getActionErrors();
}
/**
* @deprecated Use {@link #getFieldErrors()}.
*/
@Deprecated public Map<String, List<String>> getErrors() {
return getFieldErrors();
}
public void setFieldErrors(Map<String, List<String>> errorMap) {
validationAware.setFieldErrors(errorMap);
}
public Map<String, List<String>> getFieldErrors() {
return validationAware.getFieldErrors();
}
public Locale getLocale() {
ActionContext ctx = ActionContext.getContext();
if (ctx != null) {
return ctx.getLocale();
} else {
LOG.debug("Action context not initialized");
return null;
}
}
public boolean hasKey(String key) {
return textProvider.hasKey(key);
}
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 String getText(String aTextName, List<Object> args) {
return textProvider.getText(aTextName, args);
}
public String getText(String key, String[] args) {
return textProvider.getText(key, args);
}
public String getText(String aTextName, String defaultValue, List<Object> args) {
return textProvider.getText(aTextName, defaultValue, args);
}
public String getText(String key, String defaultValue, String[] args) {
return textProvider.getText(key, defaultValue, args);
}
public String getText(String key, String defaultValue, List<Object> args,
ValueStack stack) {
return textProvider.getText(key, defaultValue, args, stack);
}
public String getText(String key, String defaultValue, String[] args,
ValueStack stack) {
return textProvider.getText(key, defaultValue, args, stack);
}
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 addActionMessage(String aMessage) {
validationAware.addActionMessage(aMessage);
}
public void addFieldError(String fieldName, String errorMessage) {
validationAware.addFieldError(fieldName, errorMessage);
}
public String input() throws Exception {
return INPUT;
}
public String doDefault() throws Exception {
return SUCCESS;
}
/**
* A default implementation that does nothing an returns "success".
* <p/>
* Subclasses should override this method to provide their business logic.
* <p/>
* See also {@link com.opensymphony.xwork2.Action#execute()}.
*
* @return returns {@link #SUCCESS}
* @throws Exception can be thrown by subclasses.
*/
public String execute() throws Exception {
return SUCCESS;
}
public boolean hasActionErrors() {
return validationAware.hasActionErrors();
}
public boolean hasActionMessages() {
return validationAware.hasActionMessages();
}
public boolean hasErrors() {
return validationAware.hasErrors();
}
public boolean hasFieldErrors() {
return validationAware.hasFieldErrors();
}
/**
* Clears field errors. Useful for Continuations and other situations
* where you might want to clear parts of the state on the same action.
*/
public void clearFieldErrors() {
validationAware.clearFieldErrors();
}
/**
* Clears action errors. Useful for Continuations and other situations
* where you might want to clear parts of the state on the same action.
*/
public void clearActionErrors() {
validationAware.clearActionErrors();
}
/**
* Clears messages. Useful for Continuations and other situations
* where you might want to clear parts of the state on the same action.
*/
public void clearMessages() {
validationAware.clearMessages();
}
/**
* Clears all errors. Useful for Continuations and other situations
* where you might want to clear parts of the state on the same action.
*/
public void clearErrors() {
validationAware.clearErrors();
}
/**
* Clears all errors and messages. Useful for Continuations and other situations
* where you might want to clear parts of the state on the same action.
*/
public void clearErrorsAndMessages() {
validationAware.clearErrorsAndMessages();
}
/**
* A default implementation that validates nothing.
* Subclasses should override this method to provide validations.
*/
public void validate() {
}
@Override public Object clone() throws CloneNotSupportedException {
return super.clone();
}
/**
* <!-- START SNIPPET: pause-method -->
* Stops the action invocation immediately (by throwing a PauseException)
* and causes the action invocation to return
* the specified result, such as {@link #SUCCESS}, {@link #INPUT}, etc.
* <p/>
* <p/>
* The next time this action is invoked (and using the same continuation ID),
* the method will resume immediately
* after where this method was called, with the entire call stack
* in the execute method restored.
* <p/>
* <p/>
* Note: this method can <b>only</b> be called
* within the {@link #execute()} method.
* <!-- END SNIPPET: pause-method -->
*
* @param result the result to return - the same type of
* return value in the {@link #execute()} method.
*/
public void pause(String result) {
}
}
ActionSupport是一个默认的Action实现类,该类里已经提供了许多默认方法,这些默认方法包括获取国际化信息的方法,数据校验的方法,默认的处理用户请求的方法等。实际上,ActionSupport类是Struts2默认的Action处理类,如果让开发者的Action类继承ActionSupport,会大大简化Action的开发。所以实际开发中Action一般都选择继承ActionSupport基类。