The thing is, some time ago, when I was doing code review, I found that there was a method in the project with a huge amount of code, and most of it was written as the code of parameter verification. We had to focus on the requirements first.

Product demand

Find the product and get the requirements document. The requirements look like this:

  • Excel data template download
  • Excel data import
  • When importing, according to the template verification rules to filter, import success to return the success list, data problems to return the failure list, failure list support data editing correction

All right. The third column may be a bit difficult to see at first glance, as we know that traditional validation of data is annotated on dtos

As follows:

/ / the first
public Result test(@RequestBody @Validated TestDTO dto) {... }/ / the second
public  Result  test(@RequestBody @ValidTestDTO dto{... } // The third typepublic Result  test(@RequestBody @Validated(value = {SaveGroup.class}) TestDTO dto) {... }Copy the code

TestDTO has some validation annotations like @notnull, @notblank, @size, etc.

This is then encapsulated in the global exception interception to keep the data structure as uniform as possible, so a GlobalExceptionHandle is generally required

When it comes to common data validation, then we painting style, and come back to see demand, visible above requirements are not satisfied, first of all, we are in is a file, which is the user to the excel, we need to parse the file first, then data judgment, legally have to put a collection, illegal to put a collection, moreover, even if the parameter is an array, Once this check is not satisfied, it will immediately enter the exception processing, and cannot be returned to the front end of the correct data structure, so we introduced the solution to solve this kind of requirement today.

Refactoring begins – Opens

We used easyExcel – Demo, a project in the previous article, as the template for code transformation and compilation

Code address: github.com/pengziliu/G…

Download the little demo you made earlier, run it, and create a workbook to import data

Create an Excel data

PostMan simulates call data parsing

Project code and console output

Refactoring begins – Actual combat

Ok, above introduced the basic reading excel function of the previous project, we will implement the requirements mentioned in the beginning based on the above functions.

Let’s customize the rules for phone numbers and names:

  • The mobile number must meet basic mobile number rules
  • The name is not empty and cannot exceed four characters

Returns two sets of success and failure, both of which are satisfied and returned to success, as long as one of which is not satisfied is thrown into the failure list.

Define the data structure returned

Create the return object userExcelvo.java

All right, guys, I’m going to go through some pseudo-code written by a colleague here. Sit back and hold it steady!!

@PostMapping("/importExcel")
    public UserExcelVO importExcel(@RequestParam("file") MultipartFile file){
        List<UserExcelModel> list = null;
        List<UserExcelModel> fail = new ArrayList<>();
        UserExcelVO userExcelVO = new UserExcelVO();
        String mobieReg = "^ [1] [3,4,5,7,8] [0-9] {9} $$";
        try {
            list = EasyExcel.read(file.getInputStream(),UserExcelModel.class,new ModelExcelListener()).sheet().doReadSync();

            list.forEach(data->{
                // Process name validation
                if(StringUtils.isEmpty(data.getName())||data.getName().length()> 4 ){
                    fail.add(data);
                    return;
                }
                // Verify the mobile phone number
                if(StringUtils.isEmpty(data.getMobile())|| ! data.getMobile().matches(mobieReg)) { fail.add(data);return;
                }
                // There may be n ifs depending on the number of fields
            });
            userExcelVO.setFail(fail);
            list.removeAll(fail);
            userExcelVO.setSuccess(list);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return userExcelVO;
    }
Copy the code

Test data:

User name Age Mobile phone Number Gender 1 11 23847235 Male Baodian elder brother 2 12 15813847236 Male Baodian elder brother 3 13 15813847237 male Baodian elder brother 4 14 15813847238 male Baodian elder brother 5 15 15813847239 male 6 16 15813847240 male treasure dian ge 7 17 152247241 male treasure dian ge 8 18 15813847242 male treasure dian ge 9 19 15813847243 male treasure dian ge 10 20 15813847244 male treasure dian ge 11 21 15813847245 Male baodian elder brother 12 22 15813847246 male baodian elder brother 13 23 15813847247 male baodian elder brother 14 24 15813847248 male baodian elder brother 15 25 15813847249 maleCopy the code

Test results:

{
    "success": [{"cellStyleMap": {},
            "name": "Treasure Book 2"."age": 12."mobile": "15813847236"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book Brother 3"."age": 13."mobile": "15813847237"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book 4"."age": 14."mobile": "15813847238"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book Brother 5"."age": 15."mobile": "15813847239"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book Brother 6"."age": 16."mobile": "15813847240"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book Brother 8"."age": 18."mobile": "15813847242"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book Brother 9"."age": 19."mobile": "15813847243"."sex": "Male"}]."fail": [{"cellStyleMap": {},
            "name": "Treasure Book Brother 1"."age": 11."mobile": "23847235"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book brother 7"."age": 17."mobile": "152247241"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book Brother 10"."age": 20."mobile": "15813847244"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book Brother 11"."age": 21."mobile": "15813847245"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book Brother 12"."age": 22."mobile": "15813847246"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book Brother 13"."age": 23."mobile": "15813847247"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book Brother 14"."age": 24."mobile": "15813847248"."sex": "Male"
        },
        {
            "cellStyleMap": {},
            "name": "Treasure Book Brother 15"."age": 25."mobile": "15813847249"."sex": "Male"}}]Copy the code

According to the test results, there should be no problem, and I have simulated it here. But in the actual business scenario, if the order data in an Excel starts with dozens of fields at least, it is obviously unreasonable to write dozens of if and else, so can we use annotations to help us solve the problem? If you use annotations, how do you use them?

Having made!

createValidationUtils.java

public class ValidationUtils {

    public static Validator getValidator(a){
        return validator;
    }

    static Validator validator;
    static{ ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory(); validator=validatorFactory.getValidator(); }}Copy the code

Annotate the Model

Rewrite Controller

 @PostMapping("/v2/importExcel")
    public UserExcelVO importExcelV2(@RequestParam("file") MultipartFile file){
        List<UserExcelModel> list = null;
        List<UserExcelModel> fail = new ArrayList<>();
        UserExcelVO userExcelVO = new UserExcelVO();
        try {
            list = EasyExcel.read(file.getInputStream(),UserExcelModel.class,new ModelExcelListener()).sheet().doReadSync();
            list.forEach(data->{
            	// Here three lines of code solve a hundred if else
                Set<ConstraintViolation<UserExcelModel>> violations  =  ValidationUtils.getValidator().validate(data);
                if(violations.size()>0){ fail.add(data); }}); userExcelVO.setFail(fail); list.removeAll(fail); userExcelVO.setSuccess(list); }catch (IOException e) {
            e.printStackTrace();
        }
        return userExcelVO;
    }
Copy the code

test

Test the same set of data

The test results are as follows. It can be found that the data output of the two implementations is consistent

{" success ": [{" cellStyleMap" : {}, "name" : "the elder brother of the bible 2", "age" : 12, "mobile" : "15813847236", "sex" : "Male"}, {" cellStyleMap ": {}," name ":" the elder brother of the bible 3 ", "age" : 13, "mobile" : "15813847237", "sex", "male"}, {" cellStyleMap ": {}, "name" : "the elder brother of the treasure dian 4", "age" : 14, "mobile" : "15813847238", "sex", "male"}, {" cellStyleMap ": {}," name ":" brother treasure dian 5 ", "age" : 15, "mobile" : "15813847239", "sex", "male"}, {" cellStyleMap ": {}," name ":" the elder brother of the bible 6 ", "age" : 16, "mobile" : "15813847240", "sex", "male"}, {" cellStyleMap ": {}," name ":" the elder brother of the bible 8 ", "age" : 18, "mobile" : "15813847242", "sex" : "Male"}, {" cellStyleMap ": {}," name ":" the elder brother of the bible 9 ", "age" : 19, "mobile" : "15813847243", "sex", "male"}], "fail" : [{" cellStyleMap ": {}," name ":" the elder brother of the treasure dian 1 ", "age" : 11, "mobile" : "23847235", "sex", "male"}, {" cellStyleMap ": {}," name ": Brother treasure dian "7", "age" : 17, "mobile" : "152247241", "sex", "male"}, {" cellStyleMap ": {}," name ":" the elder brother of the bible 10 ", "age" : 20, "mobile" : "15813847244", "sex", "male"}, {" cellStyleMap ": {}," name ":" the elder brother of the bible 11 ", "age" : 21, "mobile" : "15813847245", "sex" : "Male"}, {" cellStyleMap ": {}," name ":" the elder brother of the bible 12 ", "age" : 22, "mobile" : "15813847246", "sex", "male"}, {" cellStyleMap ": {}, "name" : "the elder brother of the bible, 13", "age" : 23, "mobile" : "15813847247", "sex", "male"}, {" cellStyleMap ": {}," name ":" the elder brother of the bible 14 ", "age" : 24, "mobile" : "15813847248", "sex", "male"}, {" cellStyleMap ": {}," name ":" the elder brother of the bible 15 ", "age" : 25, "mobile" : "15813847249", "sex": "male"}]Copy the code

Code warehouse

Github.com/pengziliu/G…

The latest code has been submitted, welcome star, which contains many project tutorials and examples

conclusion

When writing code, in addition to making functions, we should consider the expansibility of the code, otherwise the product said to add a function, we have to talk about writing code, that is also sad.