我对Struts(2.2.3)的问题感到非常不满。这是我对ActionName-validation.xml
的字段验证<field name="txtRequestDateFrom">
<field-validator type="conversion">
<param name="repopulateField">false</param>
<message>${getText("E011", {"Date from"})}</message>
</field-validator>
</field>
我的动作类中没有validate()方法。我在我的动作课中有这个:
private Date txtRequestDateFrom;
{getter, setters}
当我在txtRequestDateFrom字段中输入字母时,我会在
上获得3条验证消息<s:fielderror fieldName="txtRequestDateFrom"/>
看起来像这样
Invalid field value for field "txtRequestDateFrom".
Invalid field value for field "txtRequestDateFrom".
Date from has an invalid value
我有自定义主题,我确信SIMPLE主题没有任何修改。我的拦截器堆栈几乎与默认值堆栈相同。
<interceptor-stack name="defaultStack">
<interceptor-ref name="security"/>
<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="debugging"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUploadStack" />
<interceptor-ref name="fileUpload" >
<param name="maximumSize">4000000</param>
</interceptor-ref>
<interceptor-ref name="checkbox"/>
<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">execute, complete ...</param>
</interceptor-ref>
<interceptor-ref name="workflow"/>
</interceptor-stack>
我发现通过从堆栈中删除conversionError拦截器可以删除一个字段错误。但我认为这不会导致这个问题。 Struts应该能够显示仅由开发人员定义的错误,对吗?
请帮我解决这个问题
答案 0 :(得分:1)
您需要了解how Struts2 handles conversion errors。
在类型转换期间发生的任何错误可能希望报告,也可能不希望报告。例如,报告输入“abc”无法转换为数字可能很重要。另一方面,报告空字符串“”无法转换为数字可能并不重要 - 尤其是在难以区分未输入值的用户与输入空白值的Web环境中。
...
重要的是要知道这些错误都不会直接报告。相反,它们被添加到ActionContext中名为conversionErrors的映射中。有几种方法可以访问此映射,并相应地报告错误。
可以通过两种方式进行错误报告:
- 在全球范围内,使用转换错误拦截器
- 基于每个字段,使用转换验证程序
醇>
您正在使用这两种机制,因此会重复发现的错误。正如文档所述,通常您不希望报告所有转换错误,因此应从堆栈中删除ConversionErrorInterceptor。现在,您可以使用conversion
验证程序选择性地将转换错误提升为字段错误。
答案 1 :(得分:1)
我发现我的自定义DateTimeConverter
导致了异常和额外的错误消息。因为我从Struts2书中找到了以下代码,以便更改我的Date的正常格式。当它抛出异常时,它会在控制台上显示异常并在字段错误上显示错误消息,而不是将异常传递给验证程序。我认为它有点像bug,因为这个类扩展了StrutsTypeConverter
,它应该像普通的转换器一样工作。
public class StringToDateTimeConverter extends StrutsTypeConverter {
private static final DateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd");
public Object convertFromString(Map context, String[] strings, Class toClass) {
if (strings == null || strings.length == 0 || strings[0].trim().length() == 0) {
return null;
}
try {
Calendar calendar = Calendar.getInstance();
calendar.setTime(DATETIME_FORMAT.parse(strings[0]));
calendar.set(Calendar.HOUR, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
return calendar.getTime();
} catch (ParseException e) {
throw new TypeConversionException(e);
}
}
public String convertToString(Map context, Object date) {
if (date != null && date instanceof Date) {
return DATETIME_FORMAT.format(date);
} else {
return null;
}
}
}
无论如何,我将throw new TypeConversionException(e);
更改为return null;
并在验证XML上添加了REQUIRED
验证程序。现在,当我在日期字段上放置无效日期时,它会显示错误。
PS:还有其他方法可以更改Struts全局日期格式吗?感谢
答案 2 :(得分:0)
我昨天遇到了类似的问题,终于找到了一个我喜欢分享的解决方案。我在我的动作中使用注释进行验证,所以我更改了默认的struts拦截器堆栈并将我的SensibleConversionErrorInterceptor放入StrutsConversion错误中。这一个完全相同,但不会产生任何验证错误。相反,它们是通过我的操作中的注释中配置的验证生成的。
这是我的转换器:
public class SensibleConversionErrorInterceptor extends StrutsConversionErrorInterceptor {
private static final long serialVersionUID = 8186282792289268544L;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext invocationContext = invocation.getInvocationContext();
Map<String, Object> conversionErrors = invocationContext.getConversionErrors();
ValueStack stack = invocationContext.getValueStack();
HashMap<Object, Object> fakie = null;
for (Map.Entry<String, Object> entry : conversionErrors.entrySet()) {
String propertyName = entry.getKey();
Object value = entry.getValue();
if (shouldAddError(propertyName, value)) {
// removed cause error messages are generated from annotations in actions
// String message = XWorkConverter.getConversionErrorMessage(propertyName, stack);
// Object action = invocation.getAction();
// if (action instanceof ValidationAware) {
// ValidationAware va = (ValidationAware) action;
// va.addFieldError(propertyName, message);
// }
if (fakie == null) {
fakie = new HashMap<Object, Object>();
}
fakie.put(propertyName, getOverrideExpr(invocation, value));
}
}
if (fakie != null) {
// if there were some errors, put the original (fake) values in place right before the result
stack.getContext().put(ORIGINAL_PROPERTY_OVERRIDE, fakie);
invocation.addPreResultListener(new PreResultListener() {
public void beforeResult(ActionInvocation invocation, String resultCode) {
Map<Object, Object> fakie = (Map<Object, Object>) invocation.getInvocationContext().get(ORIGINAL_PROPERTY_OVERRIDE);
if (fakie != null) {
invocation.getStack().setExprOverrides(fakie);
}
}
});
}
return invocation.invoke();
}
}
一个示例动作:
@Conversion
public class ProductAction extends ActionSupport {
private Product product;
// getter, setter and so on...
@Action(...)
@Validations(
requiredFields = {
@RequiredFieldValidator(
type = ValidatorType.FIELD,
fieldName = "product.validFrom",
message = "required.product.validFrom",
shortCircuit = true
)
},
conversionErrorFields = {
@ConversionErrorFieldValidator(
fieldName = "product.validFrom",
key = "invalid.fieldvalue.product.validFrom'",
shortCircuit = true
)
}
)
public String saveOrUpdate() {
// do something here...
}
}