基于范型的java验证框架

来源:互联网 发布:mac默认dock排列 编辑:程序博客网 时间:2024/06/06 23:51

        经历了很多项目的人,就会发现编写验证代码的过程是多么极其乏味痛苦的历程,而太多的验证代码都极其相似,想尝试用个框架来解决。但在网上搜索一番,发现要么极其复杂不够灵活,要么庞大不适合我的项目。于是发挥劳动人民自力更生的精神,居然被我研究成功了。

      二话不说,先上代码。

1.Validate<T1>,这个是主要的框架引擎。

     package com.zjg;

import java.io.IOException;
import java.util.ArrayList;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;

public class Validate<T1> {
    interface IValidateRule<T2> {
        public boolean validate(T2 data);

        public String getComment();

        public String getFailedHint();

        public String toJson() throws JsonGenerationException,
                JsonMappingException, IOException;
    }

    public static abstract class BaseValidateRule<T3> implements
            Validate.IValidateRule<T3> {
        String comment = "";
        String failedHint = "";

        @Override
        public String toJson() throws JsonGenerationException,
                JsonMappingException, IOException {
            // TODO 自动生成的方法存根
            return new UnicodeJsonObjectMapper().writeValueAsString(this);
        }

        public String getComment() {
            return comment;
        }

        public void setComment(String comment) {
            this.comment = comment;
        }

        @Override
        public String getFailedHint() {
            return failedHint;
        }

        public void setFailedHint(String failedHint) {
            this.failedHint = failedHint;
        }
    }

    ArrayList<IValidateRule<T1>> validateRules = new ArrayList<IValidateRule<T1>>();
    ArrayList<Boolean> preDependences = new ArrayList<Boolean>();
    StringBuffer lastFailedHint = new StringBuffer();

    String separator = ",";
    String comment = "";

    public String toJson() throws JsonGenerationException,
            JsonMappingException, JSONException, IOException {
        int i = 0;
        int size = 0;
        JSONStringer stringer = new JSONStringer();
        stringer.object();
        {
            stringer.key("comment").value(comment);
            stringer.key("separator").value(separator);

            stringer.key("validateRules").array();
            {
                size = validateRules.size();
                for (i = 0; i < size; i++) {
                    stringer.value(validateRules.get(i).toJson());
                }
            }
            stringer.endArray();

            stringer.key("preDependences").array();
            {
                size = preDependences.size();
                for (i = 0; i < size; i++) {
                    stringer.value(preDependences.get(i));
                }
            }
            stringer.endArray();

            stringer.key("validateRuleClassNames").array();
            {
                size = validateRules.size();
                for (i = 0; i < size; i++) {
                    stringer.value(validateRules.get(i).getClass().getName());
                }
            }
            stringer.endArray();
        }
        stringer.endObject();
        return stringer.toString();
    }

    public void parseFormJson(String json) throws JsonParseException,
            JsonMappingException, IOException, JSONException,
            ClassNotFoundException {
        JSONObject jsonObject = new JSONObject(json);
        comment = jsonObject.getString("comment");
        separator = jsonObject.getString("separator");

        UnicodeJsonObjectMapper objectMapper = new UnicodeJsonObjectMapper();
        ArrayList<IValidateRule<T1>> tmpValidateRules = new ArrayList<IValidateRule<T1>>();
        JSONArray validateRulesJsonArray = null;
        JSONArray validateRuleClassNamesJsonArray = null;
        int i = 0;
        int size = 0;
        validateRulesJsonArray = jsonObject.getJSONArray("validateRules");
        validateRuleClassNamesJsonArray = jsonObject
                .getJSONArray("validateRuleClassNames");
        size = validateRulesJsonArray.length();
        for (i = 0; i < size; i++) {
            tmpValidateRules
                    .add((IValidateRule<T1>) objectMapper.readValue(
                            validateRulesJsonArray.getString(i), Class
                                    .forName(validateRuleClassNamesJsonArray
                                            .getString(i))));
        }

        ArrayList<Boolean> tmpPreDependences = new ArrayList<Boolean>();
        JSONArray preDependencesJsonArray = jsonObject
                .getJSONArray("preDependences");
        size = preDependencesJsonArray.length();
        for (i = 0; i < size; i++) {
            tmpPreDependences.add(preDependencesJsonArray.getBoolean(i));
        }
        validateRules = tmpValidateRules;
        preDependences = tmpPreDependences;
    }

    public String getLastFailedHint() {
        return lastFailedHint.toString();
    }

    public Validate<T1> addValidateRule(IValidateRule<T1> validateRule,
            boolean preDependence) {
        if (validateRule == null) {
            throw new NullPointerException();
        }
        validateRules.add(validateRule);
        preDependences.add(Boolean.valueOf(preDependence));
        String tmpComment = validateRule.getComment();
        if (tmpComment.length() > 0) {
            if (validateRules.size() > 1) {
                comment += ",";
            }
            comment += tmpComment;
        }
        return this;
    }

    public boolean validate(T1 data) {
        if (data == null) {
            throw new NullPointerException();
        }
        boolean result = true;
        lastFailedHint.setLength(0);

        int faliedCount = 0;
        String failedHint;

        int size = validateRules.size();
        for (int i = 0; i < size; i++) {
            if (preDependences.get(i) && !result) {
                break;
            }
            if (!validateRules.get(i).validate(data)) {
                result = false;
                failedHint = validateRules.get(i).getFailedHint();
                if (failedHint.length() != 0) {
                    if (faliedCount > 0) {
                        lastFailedHint.append(separator);
                    }
                    lastFailedHint.append(failedHint);
                    faliedCount++;
                }
            }
        }
        return result;
    }

    public String getSeparator() {
        return separator;
    }

    public void setSeparator(String separator) {
        this.separator = separator;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }
}


2.这是可以无限扩展的规则库

package com.zjg;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ValidateRules {

    /**
     * Email格式验证
     *
     * @author 周继光
     *
     */
    public static class EmailValidateRule extends
            Validate.BaseValidateRule<String> {
        String regex = "\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
        {
            setComment("合法的电子邮件格式");
            setFailedHint("非法的电子邮件格式");
        }

        @Override
        public boolean validate(String data) {
            // TODO 自动生成的方法存根
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(data);
            return matcher.matches();
        }

        /**
         * regex getter
         *
         * @return regex
         */
        public String getRegex() {
            return regex;
        }

        /**
         * regex setter
         *
         * @param regex
         *            要设置的 regex
         */
        public void setRegex(String regex) {
            this.regex = regex;
        }
    }

    public static class MinLengthValidateRule extends
            Validate.BaseValidateRule<String> {
        int length = 6;
        {
            setComment("不少于" + length + "(含" + length + ")个字符");
            setFailedHint("少于" + length + "个字符");
        }

        @Override
        public boolean validate(String data) {
            // TODO 自动生成的方法存根
            return data.length() >= length;
        }

        public int getLength() {
            return length;
        }

        public void setLength(int length) {
            this.length = length;
        }
    }

    public static class MaxLengthValidateRule extends
            Validate.BaseValidateRule<String> {
        int length = 40;
        {
            setComment("不多于" + length + "(含" + length + ")个字符");
            setFailedHint("多于" + length + "个字符");
        }

        @Override
        public boolean validate(String data) {
            // TODO 自动生成的方法存根
            return data.length() <= length;
        }

        public int getLength() {
            return length;
        }

        public void setLength(int length) {
            this.length = length;
        }
    }

    public static class UsernameIllegalCharacterValidateRule extends
            Validate.BaseValidateRule<String> {
        String regex = "^[\\w\\d\\_\\-\\@\\.]*$";
        {
            setComment("只能包含\"a-z\",\"A-Z\",\"0–9\",\"_\",\"-\",\"@\",\".\"等字符");
            setFailedHint("含有\"a-z\",\"A-Z\",\"0–9\",\"_\",\"-\",\"@\",\".\"之外的字符");
        }

        @Override
        public boolean validate(String data) {
            // TODO 自动生成的方法存根
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(data);
            return matcher.matches();
        }

        /**
         * regex getter
         *
         * @return regex
         */
        public String getRegex() {
            return regex;
        }

        /**
         * regex setter
         *
         * @param regex
         *            要设置的 regex
         */
        public void setRegex(String regex) {
            this.regex = regex;
        }
    }

    public static class PasswordIllegalCharacterValidateRule extends
            Validate.BaseValidateRule<String> {
        String regex = "^[\\x21-\\x7e]*$";
        {
            setComment("只能包含ASCII码表中\"!\"-\"~\"等字符");
            setFailedHint("含有ASCII码表中\"!\"-\"~\"之外的字符");
        }

        @Override
        public boolean validate(String data) {
            // TODO 自动生成的方法存根
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(data);
            return matcher.matches();
        }

        /**
         * regex getter
         *
         * @return regex
         */
        public String getRegex() {
            return regex;
        }

        /**
         * regex setter
         *
         * @param regex
         *            要设置的 regex
         */
        public void setRegex(String regex) {
            this.regex = regex;
        }
    }

    public static class IllegalCharacterValidateRule extends
            Validate.BaseValidateRule<String> {
        String[] illegalCharacter = { " ", " " };
        {
            setComment("不能含有\"" + illegalCharacter + "\"等非法字符");
            setFailedHint("含有\"" + illegalCharacter + "\"等非法字符");
        }

        @Override
        public boolean validate(String data) {
            // TODO 自动生成的方法存根
            boolean result = true;
            int i = 0;
            int size = illegalCharacter.length;
            for (i = 0; i < size; i++) {
                if (data.indexOf(illegalCharacter[i]) != -1) {
                    return false;
                }
            }
            return true;
        }

        /**
         * illegalCharacter getter
         *
         * @return illegalCharacter
         */
        public String[] getIllegalCharacter() {
            return illegalCharacter;
        }

        /**
         * illegalCharacter setter
         *
         * @param illegalCharacter
         *            要设置的 illegalCharacter
         */
        public void setIllegalCharacter(String[] illegalCharacter) {
            this.illegalCharacter = illegalCharacter;
        }
    }
}

3.示例

package com.test;

import java.io.IOException;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.json.JSONException;

import com.zjg.Validate;
import com.zjg.ValidateRules;

public class Test {

    public static void main(String[] args) {
        String username = "BLUE-_baby9811@.163.com";
        String password = "BLUE-_baby9811@.163.com!@#$%^&*()_+=-~`:;\"'{[}]|\\<,>.?/";

        Validate<String> usernameValidate = new Validate<String>() {
            {
                setComment("用户名");
            }
        }.addValidateRule(new ValidateRules.MinLengthValidateRule(), false)
                .addValidateRule(new ValidateRules.MaxLengthValidateRule(),
                        true)
                .addValidateRule(
                        new ValidateRules.UsernameIllegalCharacterValidateRule(),
                        true);
        System.out
                .println("validate comment>>" + usernameValidate.getComment());
        if (usernameValidate.validate(username)) {
            System.out.println("validate hint>>" + "验证成功!");
        } else {
            System.out.println("validate hint>>"
                    + usernameValidate.getLastFailedHint());
        }

        Validate<String> passwordValidate = new Validate<String>() {
            {
                setComment("密码");
            }
        }.addValidateRule(new ValidateRules.MinLengthValidateRule(), false)
                .addValidateRule(new ValidateRules.MaxLengthValidateRule(), true)
                .addValidateRule(
                        new ValidateRules.PasswordIllegalCharacterValidateRule(),
                        true);
        System.out
        .println("validate comment>>" + passwordValidate.getComment());
        if (passwordValidate.validate(password)) {
            System.out.println("validate hint>>" + "验证成功!");
        } else {
            System.out.println("validate hint>>"
                    + passwordValidate.getLastFailedHint());
        }

        //以下代码测试json功能,可以通过json持久化
        String tmp = null;
        try {
            tmp = usernameValidate.toJson();
        } catch (JsonGenerationException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        } catch (JSONException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        } catch (IOException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        System.out.println("usernameValidate.toJson()>>" + tmp);
        Validate<String> usernameValidate1 = new Validate<String>();
        try {
            usernameValidate1.parseFormJson(tmp);
        } catch (JsonParseException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        } catch (JSONException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        } catch (IOException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        System.out
        .println("validate comment>>" + usernameValidate1.getComment());
        if (usernameValidate1.validate(username)) {
            System.out.println("validate hint>>" + "验证成功!");
        } else {
            System.out.println("validate hint>>"
                    + usernameValidate1.getLastFailedHint());
        }

    }
}

4.结果

validate comment>>用户名不少于6(含6)个字符,不多于40(含40)个字符,只能包含"a-z","A-Z","0–9","_","-","@","."等字符
validate hint>>验证成功!
validate comment>>密码不少于6(含6)个字符,不多于40(含40)个字符,只能包含ASCII码表中"!"-"~"等字符
validate hint>>多于40个字符
usernameValidate.toJson()>>{"comment":"用户名不少于6(含6)个字符,不多于40(含40)个字符,只能包含\"a-z\",\"A-Z\",\"0\u20139\",\"_\",\"-\",\"@\",\".\"等字符","separator":",","validateRules":["{\"length\":6,\"failedHint\":\"\\u5C11\\u4E8E6\\u4E2A\\u5B57\\u7B26\",\"comment\":\"\\u4E0D\\u5C11\\u4E8E6\\uFF08\\u542B6\\uFF09\\u4E2A\\u5B57\\u7B26\"}","{\"length\":40,\"failedHint\":\"\\u591A\\u4E8E40\\u4E2A\\u5B57\\u7B26\",\"comment\":\"\\u4E0D\\u591A\\u4E8E40\\uFF08\\u542B40\\uFF09\\u4E2A\\u5B57\\u7B26\"}","{\"regex\":\"^[\\\\w\\\\d\\\\_\\\\-\\\\@\\\\.]*$\",\"failedHint\":\"\\u542B\\u6709\\\"a-z\\\",\\\"A-Z\\\",\\\"0\\u20139\\\",\\\"_\\\",\\\"-\\\",\\\"@\\\",\\\".\\\"\\u4E4B\\u5916\\u7684\\u5B57\\u7B26\",\"comment\":\"\\u53EA\\u80FD\\u5305\\u542B\\\"a-z\\\",\\\"A-Z\\\",\\\"0\\u20139\\\",\\\"_\\\",\\\"-\\\",\\\"@\\\",\\\".\\\"\\u7B49\\u5B57\\u7B26\"}"],"preDependences":[false,true,true],"validateRuleClassNames":["com.zjg.ValidateRules$MinLengthValidateRule","com.zjg.ValidateRules$MaxLengthValidateRule","com.zjg.ValidateRules$UsernameIllegalCharacterValidateRule"]}
validate comment>>用户名不少于6(含6)个字符,不多于40(含40)个字符,只能包含"a-z","A-Z","0–9","_","-","@","."等字符
validate hint>>验证成功!

5.主要思路

定义一个rule接口,引擎只与接口交互,引擎保存一个rule列表,通过扩展rule接口可以定义很多很多不同的规则,并根据需要添加到引擎的rule列表中对数据一一验证,改变或扩展规则基本不影响用户代码。有一个前置依赖性标志,如果这个标志为true,那么必须通过前面的规则验证,才进行本项规则验证。通过json对持久化支持。

6.后语

还有待完善,希望大家帮忙测试,并多多担宝贵意见,谢谢!

0 0
原创粉丝点击