问题
I've created a Struts2 project in which I used XML based validation. Model class RegistrationForm
is shown below
package com.projects;
import com.opensymphony.xwork2.ActionSupport;
public class RegistrationForm implements Serializable{
private static final long serialVersionUID = 1L;
private String fname;
private String lname;
private int numbr;
public int getNumbr() {
return numbr;
}
public void setNumbr(int numbr) {
this.numbr = numbr;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
}
RegistrationFormAction.Java
package com.projects;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class RegistrationFormAction extends ActionSupport implements ModelDriven<RegistrationForm> {
private RegistrationForm registrationForm;
public RegistrationForm getRegistrationForm() {
return registrationForm;
}
public void setRegistrationForm(RegistrationForm registrationForm) {
this.registrationForm = registrationForm;
}
public RegistrationForm getModel(){
registrationForm=new RegistrationForm();
return registrationForm;
}
public String execute(){
return "success";
}
}
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<package name="dd" extends="struts-default">
<interceptors>
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception" />
<interceptor-ref name="alias" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="prepare" />
<interceptor-ref name="i18n" />
<interceptor-ref name="chain" />
<interceptor-ref name="debugging" />
<interceptor-ref name="profiling" />
<interceptor-ref name="scopedModelDriven" />
<interceptor-ref name="modelDriven" />
<interceptor-ref name="params"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="fileUpload" />
<interceptor-ref name="checkbox" />
<interceptor-ref name="staticParams" />
<interceptor-ref name="conversionError" />
<interceptor-ref name="workflow"/>
</interceptor-stack>
</interceptors>
<action name="submitForm" class="com.projects.RegistrationFormAction">
<interceptor-ref name="defaultStack" />
<result name="success">/WelcomePage.jsp</result>
<result name="input">/RegistrationForm.jsp</result>
</action>
</package>
</struts>
RegistrationFormAction-validation.xml
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="registrationform">
<field-validator type="visitor">
<param name="appendPrefix">false</param>
<message/>
</field-validator>
</field>
</validators>
RegistrationForm-validation.xml
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="fname">
<field-validator type="requiredstring">
<message>First Name can't be blank</message>
</field-validator>
</field>
<field name="lname">
<field-validator type="requiredstring">
<message>Last Name can't be blank</message>
</field-validator>
</field>
<field name="numbr">
<field-validator type="int">
<param name="min">1</param>
<param name="max">10</param>
<message>Number between 1 to 10</message>
</field-validator>
</field>
</validators>
but validation is not working.
回答1:
There are a lot of things goin' on here! I'll post them in order of appearance in the question:
Never make a POJO extends ActionSupport:
public class RegistrationForm extends ActionSupport {
must become
public class RegistrationForm implements Serializable {
Better returning
SUCCESS
than"success"
to prevent typos (but ok this is secondary);The intercetpor stack customization has four problems:
you are overriding the existing
basicStack
, this risks to violate the POLA, especially if other people will work on this project; it's better to use a custom name instead, eg.myStack
;you are using only three interceptors, and this is suspicious; while many of the default interceptors can be dropped, many others instead should be always kept, especially with validation involved, eg.
ConversionError
Interceptor, orWorkflow
Interceptor, etc. Read how the whole thing works. As a rule, you should remove an Interceptor only when you know exactly what it does and you are absolutely sure you don't (and won't) need it.When using
ModelDriven
(that is usually not recommended, because basically useless and source of problems when not experts with it), you need to put theModelDriven
Interceptor before theParameters
Interceptor, otherwise when the parameters interceptor runs, the model won't be pushed yet, and the setters will be searched on the action, eg.setFname()
, instead that on the model (resulting in null properties in the model, and in the warningUnexpected Exception caught setting 'fname' on 'class RegistrationFormAction: Error setting expression 'fname' with value ['Sumit', ]
because of the missing setters in the action).
- Finally, if you are really using the code you posted, then you are NOT using the wrong stack you've created, because 1) The default one is the
defaultStack
, not thebasicStack
, so overridingbasicStack
has no effects, and 2) you've not used<default-interceptor-ref>
to change the default stack reference, nor you've used the<interceptor-ref>
inside the<action>
tag to specify a different interceptor stack for that action only.
You are mixing 1.0.2 and 1.0.3 in DOCTYPE of XML validation files, make everything 1.0.3 (and notice that they migrated from OpenSymphony to Apache); then change:
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
to
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
Ensure that the
RegistrationFormAction-validation.xml
file is in the action folder, while theRegistrationForm-validation.xml
is in theRegistrationForm.java
folder.Consider avoiding ModelDriven, because as Stephen Young says,
You Must Tame Complexity to Become a Better Programmer
As pointed out by AleksandrM's comment, there is also a typo in
<field name="registrationform">
that should be
<field name="registrationForm">
来源:https://stackoverflow.com/questions/30746955/how-to-perform-xml-validation-when-using-modeldriven