1. Password This article introduces one of the child projects of Jakarta Open Source Project, and the version is 1.0.2. It uses an XML file to define the data verification function entered for the user, and the entire verification system provides strong scalability so that developers can develop their own verification functions to join this verification system. It provides two options for web applications with client JavaScript verification and server validation, but it is just a verification system, and some things need to develop, especially ValidatorAction, but have project source code and their examples, There is a demonstration of Struts this excellent open source project, using a good COMMONS-Validator verification system should be very easy. This article has made some discussions on this verification system, I hope to use it!
2. User Issues When we develop a information system, the user interface is often a very important place that is easy to ignore but is indeed important. We have a lot of design patterns to write backend code, and now we also have an excellent verification system such as Commons-Validator to deal with users of users of users. Enter the verification is about the strongness of the entire information system, because malicious input data may cause the information system to crash; input verification is also related to the friendliness of the information system, because it cannot provide the user to provide the correct input guidance. Regardless of the user's hand, Finally, only the grief is going.
3. Simple analysis Through the description of the above user issues, we can simply analyze the basic characteristics of the verification system:
The verification system should have good scalability, allowing information system developers to develop their own verification capabilities to meet the verification requirements of special systems. The verification system should display accurate verification error information to help the user correct the error, and the error message should be external configurable, change the corresponding error message does not need to modify the source code. For Web information systems, both client authentication and server verification should be supported.
4. Using the interface
4.1. Profile
Below is an elemental relationship diagram of the verification rule XML file, I will choose some important and relatively complicated elements to explain.
Element Constant
The "constant" element defines the static value of the replacement parameters used by the "field" element. "constant-name" and "constant-value" elements indicate the reference identity and value of this static value, respectively.
2. Element Validator
This "validator" element defines the ValidatorAction object that the FormSet element field can use.
Child Elements JavaScript attribute
Property Name Optional Note With the Default NameRequired Verification Objects ClassNameRequired Verification Objects Full Class Method Required Use this Validation Method Name MethodParams Required Verification Method's comma-separated parameter Type list MSG Required verification fails Message Key Depends comma Separated this verification depends on other verification list JSFunctionName
3. Element Formset
"Formset" defines a Form set for Locale. "Form" element defines the "field" set to be verified, the name attribute is a reference identifier assigned to this "form".
Child Element Constant Form Property
Attribute Name Option Note With the Language of the Language Locale Objects of the Language Locale Object Partial Variant Locale Object
4. Elements Field
"Field" element defines the properties that requires authentication, in the web application, a "field" corresponds to an HTML form control. Verify the system to verify this "field" element by verifying a JavaBean, this element can accept 4 properties: child element MSG arg0 arg1 arg2 arg3 var attribute
Attribute Name Optional Note With the JavaBeaN property corresponding to the default value preactyRequired this "field" element. Depends commaly separated ValidatorAction object list, all ValidatorAction object verification passes, this "Field" is valid. Page JavaBean may have a page property that only the "field" element that is less than or equal to the JavaBean page property will be processed. This mechanism is very useful for the "wizard". Default [0] indexedlistproperty "indexedlistproperty" is a way to return an array or a collection.
5. Element MSG
The "MSG" element defines a custom message key to provide message text for the "Field" of the validation. When "Field" does not have a child element "MSG" element, each ValidatorAction object uses its own message properties.
Attributes
Attribute Name Optional Note With the ValidatorAction object corresponding to this message, the default value Name. The message key in the Key message resource file. Resource If this value is "false", the "Key" property will be a direct message text. Default [TRUE]
6. Element Arg0 | Arg1 | Arg2 | ARG3
This is four parameter elements that define four replacements in the Validator or Field message template. For example, the message resources corresponding to the Validator's MSG are "must provide the {0} field, and the length of the field cannot be less than {1} characters!", When the error is displayed, {0} will be replaced by the message text of Arg0, and { 1} will be replaced by the message text of Arg1.
Attributes
Attribute Name Optional Note With the ValidatorAction object corresponding to this message, the default value Name. The message key in the Key message resource file. Resource If this value is "false", the "Key" property will be a direct message text. Default [TRUE]
7. Element VAR
"Field" can pass this element to a ValidatorAction object, which can also be referenced by the arg? element via the grammar $ {var: var-name}. Its child elements var-name and var-value are values for variable identification and variables, respectively.
4.2. Application Programming Interface As shown in the "Commons-Validator API", the COMMONS-Validator class is clearly divided into three, the first kind of class of each element represents the validation rule file, this paper called element class, second It is a class that proceeds to verify data and verification. This paper says the fa. ADE class, the third is a class that implements universal functions, this documentation tool class. Elements represent each element in the verification rule file. For programmers, the main role is to use them to get the message text; FA? ADE class is used to integrate the Commons-Validator verification system into the application system; and tools help The programmer writes a class of ValidatorAction. Specific use See the code below.
4.3. Code Sample Although Common-Validation is a verification system written for the web application, it can also be used in the Java application, in order to put the attention on the verification system, the following verification sample uses Java applications Come. 4.3.1. Defining the verification rule verification rule is an XML file that defines a form that needs to be verified, and the verification requirements of each field of its form, and the Validator element is used to complete the verification requirements of each field. This example defines a input form nameform and its two fields, and the two fields must be provided, and the AGE field must also be an integer; two verification action INT and REQUIRED are also defined, which meet the integer requirements and the required requirements, respectively:
ClassName = "Org.i505.validator.mytypevalidator" Method = "ValidateInt" Methodparams = "java.lang.object, org.apache.commons.validator.field" Msg = "errors.int" /> ClassName = "org.i505.validator.myvalidator" Method = "ValidateRequired" Methodparams = "java.lang.object, org.apache.commons.validator.field" Msg = "ErrorS.Required" /> global> field> field> form> formset> form-validation> 4.3.2. Write a message resource file The message resources of Commons-Validator include two major parts, the first part is a message including the ValidatorAction object of the parameter placeholder. The second part is the display information of each input form input data, which is used as the information display when the verification fails. In this case, the value includes a display information of an input form: # ValidatorAction object message ErrorS.Required = must provide {0} fields! ERRORS.INT = {0} field must be an integer! # Nameform Enter the display information of each input data of the form Nameform.username.displayName = Name Nameform.DisplayName = age 4.3.3. Write ValidatorAction We can see the INT and Required ValidatorAction defined by the validator elements in the verification definition rule file, using org.i505.validator.mytypeValidator and org.i505.validator.myvalidator, two classes, which also define the verification method they use. ValidateInt and ValidateRequired and parameter type list of methods. Below is the code of these two classes: package org.i505.validator; import Org.apache.commons.validator.field; Import org.apache.commons.validator.GenericTypeValidator; Import org.apache.commons.validator.validatorutil; Public class mytypevalidator { Public Static Integer ValidateInt (Object Bean, Field Field) { String value = value = validatorutil.getValueAsstring (bean, field.getproperty ()); Integer x = generictypevalidator.formatint (value); Return X; } } Package Org.i505.validator; Import org.apache.commons.validator.field; Import org.apache.commons.validator.GenericvaliDator; Import org.apache.commons.validator.validatorutil; Public class myvalidator { Public Static Boolean ValidateRequired (Object Bean, Field Field) { String value = value = validatorutil.getValueAsstring (bean, field.getproperty ()); Return! GenericValidator.isblankornull (Value); } } 4.3.4. Write Javabean Commons-Validator is a input verification system for web applications. The FORM definition in the verification rule is for HTML Form forms, but the Common-Validator requires JavaBean when verify internal. The various properties of this JavaBean represent the input control of the HTML Form form. So for the previous verification rules, the JavaBean we implemented needs to define two properties: AGE and Username, the code is as follows: Public class validatebean extends Object { String username; string agec; Public void setusername (String username) { This. Username = Username; } Public string getUsername () { Return this.username; } Public void setage (String age) { THIS.AGE = AGE; } Public string getage () { Return this.Age; } Public string toString () { Return "{username =" this.username ", agn =" this.age "}" } Note that the type of this verification bean is a string type because it only represents the value of the input control of the HTML Form form, and the original user input data can basically expressed by String, if we declare the agge property The type of type is integrated, then we pass a type conversion at the value of the HTML Form form to the BEAN, this earlier than our integer verification, so there may be a risk of generating type conversion errors. 4.3.5. Writing verification main program Writing verification main programs have the following five steps: Create and process the ValidatorResources object, which is to initialize this object with the ValidatorResourcesInitializer class using the verification rule definition file. Creating a bean object to be verified To create a Validator object with a FORM defined in the verification rule definition file and telling this object to verify the Bean object. Validate () method running the validator object actually verifies the result of the Bean object print verification The following is a three-time verification in accordance with the instance code written in the steps described above. The first time the two properties are empty bean objects. The second time is a bean object that is not legal. The third time is BEAN objects with two attributes: Public static void main (String [] args) throws oews oException, validatorException { InputStream in = NULL; Try { ValidatorResources Resources = New ValidatorResources (); IN = validateexample.class.getResourceceAsStream ("MyValidator-Example.xml); ValidatorResourcesInitializer.Initialize (resources, in); ValidateBean bean = new validatebean (); Validator Validator = New Validator (Resources, "Nameform"); Validator.AddResource (Validator.Bean_Key, Bean); ValidatorResults Results = NULL; Results = validator.validate (); PrintResults (bean, results, resources); Bean.setUsername ("Gong Yongsheng"); Bean.setage ("very young"); Results = validator.validate (); PrintResults (bean, results, resources); Bean.setage ("28"); Results = validator.validate (); PrintResults (bean, results, resources); } Finally { IF (in! = NULL) { In.Close (); } } } 4.3.6. Print verification results Print verification results may be the most complex part of the verification system, as it involves verifying files and message resource files, involving a lot of objects and their complex relationships. Especially need to be pointed out is the display of the error message text. The following code includes three parts: The first part is to generate a resourcebundle object using the resource file, note that your resource file must be found in ClassLoader; the second part is the actual print verification result; the third part is a function of displaying Chinese messages. The validate () method of the Validator object saves the verification result into the ValidatorResults object returned to it, and it saves the validation result object ValidatorResult, which saves the ValidatorResult of each attribute of the Bean object, first we can get the bean object. Verify the FORM defined by the file to get the corresponding message keys and other information, and through this information from the ValidatorResults object, the ValidatorResult object isvalid function can determine the success of the validation, if the verification is not passed, you can use FORM information Displays the error message text. Private static resourcebundle apps = ResourceBundle.getBundle ( "Org.i505.validator.myApplicationResources"); Public Static Void PrintResults ValidateBean Bean, ValidatorResults RESULTS, ValidatorResources Resources) { Boolean Success = True; Form form = resources.get (locale.getdefault (), "nameform"); System.out.println ("/ N / N Verification:"); System.out.println (bean); Iterator propertyNames = results.get (); While (propertyNames.hasnext ()) { String PropertyName = (String) PropertyNames.next (); Field Field = (Field) Form.GetfieldMap (). Get (PropertyName); String prettyfieldname = getGBKMSG (apps.getstring (file.getarg0 (). GetKey ())); ValidatorResult Result = results.getvalidatorResult (propertyName); Map actionMap = result.getActionMap (); Iterator Keys = ActionMap.keyset (). Iterator (); While (keys.hasnext ()) { String actname = (string) keys.next (); ValidatorAction action = Resources.getValidatorAction (actname); System.out.println ( PropertyName "[[" ACTNAME "] (" (Result.issalid (ACTNAME)? "Verification": "Verification Fail") ")"); IF (! Result.issalid (actname) { Success = false; string message = getGBKMSG (apps.getstring (action.getmsg ())); Object [] args = {prettyfieldname}; System.out.println ( "The error message is:" MessageFormat.Format (Message, Args); } } } IF (Success) { System.out.println ("Form Verification"); } Else { System.out.println ("Failed Failed"; } } Public Static String getGBKMSG (String MSG) { String GBKSTR = "" Try { GBKSTR = New String (Msg.getbytes ("ISO-8859-1"), "GBK"); } Catch (unsupportedencodingexception e) { // Todo Auto-Generated Catch Block E.PrintStackTrace (); } Return GBKSTR; } The verification results are as follows: Verification: {username = null, agn = null} AGE [Required] error message is: Must provide age field! Username [Required] error message is: Must provide a name field! Form verification failed Verification: {username = Gong Yongsheng, AGE = very young} AGE [Required] (Verification Pass) AGE [INT] (Verification Failed) The error message is: the age field must be an integer! UserName [Required] Factifies Failed Verification: {username = Gong Yongsheng, AGE = 28} AGE [Required] (Verification Pass) AGE [INT] (Verification Pass) Username [Required] (Verification Pass) Form verification 5. Internal analysis 5.1. The ValidatorResults object has a map, with Field's getKey (), this Field's verification result ValidatorResult object is a value. The ValidatorResult object also has a map, with the name of each validator element of Field (a list of Field Validator Elements in the Depends of the field element), with a value that indicates the success of the verification success or not. The ValidatorResources object contains a map, represented by a string of local, formset is the value (so formset has a variety of versions), which also contains a map, saving global constants, with a constant name, constant value; Also included with a MAP, with the value of the Validator element, the ValidatorAction object is the value. The FormSet object contains a map, with the Form's Name property, the Form object is a value; also contains a map, with the Name of the child element constant of the Formset element, the value of the child elements constant value. The Form object contains a map, which is a value of the Field object corresponding to the field element, and the Field object is a value; there is also an array of Field objects that save the order. The Field object has a MAP, with the name of var, the VAR object is the value. The Validator object contains a map, with the names in the MethodParams parameter list of each validator element, the corresponding object is the value, the key and value of this MAP will be used as the parameter of the Methods attribute in the corresponding validator element. Through these MAP, Commons-Validator has paved a class relational table between the various types of the system, see the figure below: 5.2. How to call the validator element of the ValidatorAction verification rule define the ValidatorAction, and the field element references these validatorAction through the Depends property. From the verification main program from the above code sample, you can know that the validator.validate () method is for a FORM element, which will verify the various field of this FORM element, and verify the field is the Depends property that calls the field element. The verification method defined by each validator element. Validator elements define a verification method using ClassName, Method, and MethodParams, such as the XML fragment below defines a verification method of validation of an integer ValidateIntInt, with two parameters. The type is java.lang.object, Org.apache.commons.validator.field. The verification method ValidateInt will be implemented in the org.i505.validator code. ClassName = "Org.i505.validator.mytypevalidator" Method = "ValidateInt" Methodparams = "java.lang.object, org.apache.commons.validator.field" Msg = "errors.int" /> So much, now the problem is how the validator.validate () method calls each verification method (such as validateInt)? We analyze this problem with a sequential diagram and a piece of code. The above figure is a brief sequential diagram, and the interpretation of this sequence diagram: 1. Add resources to Validator objects (add items to resource MAP) 2. Actual verification For each field defined by the Form, call the following steps: #begin 3. Verify a field Perform the following steps to each ValidatorAction for Field: #begin 4. Verify a ValidatorAction 5. Merge verification results #end #end The following code explains the fourth step in the above: Verify a validatorAction. // add these two objects to the resources Since the Reference // The current validator action and field HRESOURCES.PUT (Validator_Action_Key, VA); HRESOURCES.PUT (Field_Key, Field); Class C = getClassLoader (). LoadingClass (Va.getClassName ()); List lparams = va.getMethodparamslist (); INT size = lparams.size (); INT beanindexpos = -1; INT FieldIndexpos = -1; class [] paramclass = new class [size]; Object [] Paramvalue = New Object [Size]; For (int x = 0; x String paramkey = (string) lparams.get (x); IF (bean_key.equals (paramkey)) { Beanindexpos = x; } IF (Field_Key.Equals (paramkey)) { FieldIndExpos = x; } // there were problems calling getclass on paramvalue [] Paramclass [x] = getClassLoader (). loadingClass (paramkey); Paramvalue [x] = hResources.get (paramkey); } Method M = C.getMethod (Va.getMethod (), paramclass; // if the method is static we don't need an instance of the class // to call the method. if it isn't, we do. IF (! Modifier.ISstatic (M.GETMODIFIERS ()))) Try { IF (Va.getClassNameInstance () == null) { Va.setClassNameInstance (C.NewInstance ()); } } Catch (Exception EX) { Log. Error "COULDN'T LOAD Instance" "of class" va.getclassname () "." ex.getMessage ()); } } Object result = null; IF (Field.isIndexed ()) { Object oindexed = PropertyUtils.getProperty HRESOURCES.GET (Bean_Key), Field.GetIndexedListProperty ()); Object indexedlist [] = new object [0]; OINDEXED InstanceOf Collection { IndexedList = ((collect) .toarray (); } Else IF (OINDEXED.GETCLASS (). isarray ()) { IndexedList = (Object []) OINDEXED; } // set current orthoped object to the parameter arch Paramvalue [beanindexpos] = indexedlist [POS]; // set Field Clone with the key modified to represent // the current field Field Indexedfield = (Field) Field.clone (); Indexedfield.SetKey ValidatorUtil.replace Indexedfield.getKey (), Field.Token_indexed, "[" POS "]"); paramvalue [FieldIndexpos] = Indexedfield; Result = m.invoke (Va.getClassNameInstance (), paramvalue; Results.add (Field, Va.getName (), IsValid (Result), Result IF (! isvalid (result)) { Return False; } } Else { Result = m.invoke (Va.getClassNameInstance (), paramvalue; Results.add (Field, Va.getName (), IsValid (Result), Result IF (! isvalid (result)) { Return False; } } This code first adds two resources: Field and ValidatorAction, which are currently being verified, then instantiate an object in which the authentication method is located, followed by constructing the parameter list of the verification method according to the key / value of the resource Map and the parameter class list of the verification method. , The authentication method of an object of the verification method is called. 6. Legacy issues We say that Commons-Validator is a universal verification system, it is really a good thing, but if you want to use it in the actual system, you need a certain job, especially when you use its client authentication. Fortunately, the Struts project made a very classic demonstration for us to use these validation systems. I think it is necessary to move these efforts of the Struts project to the Commons-Validator project so that its usability will be greatly improved. 7. Summary as a verified universal framework, some features are not available immediately, it requires developers to package again. Struts reorganizes the client verification mechanism for Commons-Validator, so that this mechanism is immediately available for development Struts programs. With these packaging, the rest of the task is to develop ValidatorAction to meet different verification requirements. In addition, Struts also provides inputs that are verified and a regular expression match, which uses the PERL5 regular expression matching mechanism for Commons-Validator. When developing a web information system, in addition to verify input, we also need to pay attention to the output of the data. The web interface is HTML code, and this code is interpreted by the browser. If our internal data includes the reserved word of HTML code, a little harm is destroying the browser's explanation of HTML, and it is broken our last interface. It is important to introduce safety hazards, paralyzed information systems. The following code can be used to filter HTML reserves, learn urlencoding, called HTMLENCoding: Public static string htmlencoding (String value) { IF (value == null) Return (NULL); Char content [] = new char [value.Length ()]; Value.getchars (0, value.Length (), Content, 0); StringBuffer Result = New StringBuffer (Content.length 50); For (int i = 0; i Switch (Content [I]) { Case '<': Result.Append ("<"); Break; Case '>': Result.Append (">"); Case '&': Result.Append ("&"); Break; Case '"": Result.Append ("" "); Break; Case '/' ': Result.Append ("'"); Break; Note and default: Result.Append (Content [i]); } } Return (result.toString ()); }