在 com.opensymphony.xwork2.Action
接口中提供了 5 个如下静态字段:
public static final String SUCCESS = "success"; // 操作成功
public static final String NONE = "none"; // 操作成功不跳转
public static final String ERROR = "error"; // 操作失败
public static final String INPUT = "input"; // 通常在表单提交请求参数验证失败时返回,标识需重新输入提交
public static final String LOGIN = "login"; // 返回到登录页
其中除 input
之外的四个结果我们经常用到,也很容易理解。那 input
结果到底是什么时候用呢?
先看如下示例:
// com.zze.action.Test11Action
package com.zze.action;
import com.opensymphony.xwork2.ActionSupport;
public class Test11Action extends ActionSupport {
private Integer age;
public void setAge(Integer age) {
this.age = age;
}
@Override
public String execute() throws Exception {
System.out.println(age);
return NONE;
}
}
在上述 action 中使用属性驱动的方式接受一个 Integer
类型的年龄字段,而参数提交时提交的是 "aa",
"aa"明显是不可以转成
Integer` 类型的,此时 Struts2 就会返回错误如下:
No result defined for action com.zze.action.Test11Action and result input - action - file:/WEB-INF/classes/struts.xml:13:51
即:没有为 action 定义一个 name="input"
的 result
。为什么 Struts2 会返回这个结果呢?
首先我们要知道 Struts2 内部默认是有一个拦截器栈的,在 struts2-core-2.3.37.jar!/struts-default.xml
中可以看到它们的定义,如下:
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="datetime"/>
<interceptor-ref name="multiselect"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<!--接收参数-->
<interceptor-ref name="params"/>
<!--类型转换-->
<interceptor-ref name="conversionError"/>
<!--数据校验-->
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="debugging"/>
<interceptor-ref name="deprecation"/>
</interceptor-stack>
在请求 action 时该栈下的拦截器会依次执行,而每个拦截器都有它自身的功能。如 params
拦截器用来接收参数、conversionError
拦截器用来类型转换、validation
拦截器用来数据校验。
而 Struts2 有一个专门存放错误的区域,当这几个操作出错时,Struts2 就会将对应错误信息存到该错误区域。接着在 workflow
拦截器中就会检查错误区域是否有错误,如果有,则返回 "input"
逻辑视图,如果没有则继续执行后续拦截器及 action。workflow
对应拦截器部分源码如下:
// com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor#doIntercept
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();
if (action instanceof ValidationAware) {
ValidationAware validationAwareAction = (ValidationAware) action;
// 如果错误区有错误
if (validationAwareAction.hasErrors()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Errors on action [#0], returning result name [#1]", validationAwareAction, inputResultName);
}
String resultName = inputResultName; // "input"
resultName = processValidationWorkflowAware(action, resultName);
resultName = processInputConfig(action, invocation.getProxy().getMethod(), resultName);
resultName = processValidationErrorAware(action, resultName);
return resultName;
}
}
return invocation.invoke();
}
了解了拦截器返回 "input"
逻辑视图的原因,我们就可以对症下药了,在 struts.xml
中 action
标签下添加一个 "input"
的结果:
<result name="input">/input.jsp</result>
而在该 JSP 页中我们可以通过 Struts2 提供的标签输出错误信息:
// input.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<s:fielderror/>
</body>
</html>
请求及响应如下:
回到文章开头的那个问题,input
逻辑视图到底是什么时候用呢?
input
逻辑视图使我们对验证错误信息的传输及获取更加方便快捷,因为 input
逻辑视图就是 Struts2 在处理验证等相关逻辑出现错误时给我们返回的一个结果,我们可以在这个逻辑视图中拿到相关的错误信息以我们自己的方式友好的回显给客户端。
评论区