• 从零开始实现放置游戏(七)——实现后台管理系统(5)参数校验


      前面几章实现了在RMS系统中进行数据的增删查改以及通过Excel批量导入。但仍有遗留的问题,比如在新增或编辑时,怪物的生命值、护甲等数据我们可以输入负值,这种数据是不合理且没有意义的。本章我们就实现服务端对参数的校验。

    一、添加依赖项

      在rms模块的pom.xml中,添加校验组件的依赖项(注意:之前的组件我们都引用了最新版本。但因hibernate-validator的最新版本6.xx+中引用的el-api.jar有冲突,无法用maven插件启动,所以这里使用5.1.1版本):

    <!-- 参数校验 -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.1.1.Final</version>
    </dependency>

      这个组件本身提供了一些注解,@NotNull, @NotBlank, @Min等等,来对模型进行校验,但错误提示不够好,默认通用的错误提示无法明确知道是哪个字段报错。如果为每个字段添加一个提示语,又非常繁琐,所以我们这里稍加改动,在util模块做一个通用的校验工具包。

      在util模块的pom.xml中添加依赖:

    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
        <scope>provided</scope>
    </dependency>

    二、添加自定义注解及提示信息

      以非空校验为例,在util模块中新建包com.idlewow.util.validation.annotaion,在此包下新建一个注解类NotBlank.java如下:

    package com.idlewow.util.validation.annotation;
    
    
    import com.idlewow.util.validation.validator.NotBlankValidator;
    
    import javax.validation.Constraint;
    import javax.validation.Payload;
    import javax.validation.ReportAsSingleViolation;
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Documented
    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    @ReportAsSingleViolation
    @Constraint(validatedBy = NotBlankValidator.class)
    @NotNull
    public @interface NotBlank {
        String field() default "";
    
        String message() default "{field.not.blank.message}";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    
        @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
        @Retention(RetentionPolicy.RUNTIME)
        @Documented
        @interface List {
            NotBlank[] value();
        }
    }

      注解有了,还需要一个对应的检验器,新建包com.idlewow.util.validation.validator,并在此包下新建类NotBlankValidator如下:

    package com.idlewow.util.validation.validator;
    
    import com.idlewow.util.validation.annotation.NotBlank;
    
    import javax.validation.ConstraintValidator;
    import javax.validation.ConstraintValidatorContext;
    
    public class NotBlankValidator implements ConstraintValidator<NotBlank, CharSequence> {
        public NotBlankValidator() {
        }
    
        public void initialize(NotBlank annotation) {
        }
    
        @Override
        public boolean isValid(CharSequence charSequence, ConstraintValidatorContext constraintValidatorContext) {
            if (charSequence == null) {
                return false;
            } else {
                return charSequence.toString().trim().length() > 0;
            }
        }
    }

      另外,在对模型进行校验时,不同场景下的需求不同。比如,在新增时,因为主键由数据库自增,无需添加主键;编辑时,则必须指定主键ID,对其进行非空校验。因此,我们在com.idlewow.util.validation包下在新建一个对校验分组的类ValidateGroup:

    package com.idlewow.util.validation;
    
    import javax.validation.groups.Default;
    import java.io.Serializable;
    
    public class ValidateGroup implements Serializable {
        public interface Create extends Default {
        }
    
        public interface Update extends Default {
    
        }
    }

      最后,我们在util模块的resource资源目录下添加提示信息的资源文件ValidationMessages.properties,

    #common invalid message
    field.not.blank.message={field}不能为空
    field.not.null.message={field}不能为NULL
    field.size.message={field}的长度应为{min}至{max}之间
    field.min.message={field}不能小于{value}
    field.max.message={field}不能大于{value}
    field.range.message={field}的大小应为{min}至{max}之间
    field.positive.message={field}必须是正数
    field.negative.message={field}必须是负数

    三、参数校验注解的使用

      首先,我们需要在需要校验的模型上加上注解,此处以怪物模型为例:

    package com.idlewow.mob.model;
    
    import com.idlewow.common.model.BaseModel;
    import com.idlewow.util.validation.annotation.NotBlank;
    import com.idlewow.util.validation.annotation.NotNull;
    import com.idlewow.util.validation.annotation.Positive;
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    
    import java.io.Serializable;
    
    @Data
    @EqualsAndHashCode(callSuper = true)
    public class MapMob extends BaseModel implements Serializable {
        @NotBlank(field = "主键id", groups = ValidateGroup.Update.class)
        private String id;
        @NotBlank(field = "怪物名称")
        private String name;
        @NotBlank(field = "地图id")
        private String mapId;
        @NotBlank(field = "地图名称")
        private String mapName;
        @NotNull(field = "阵营")
        private Integer faction;
        @NotNull(field = "怪物种类")
        private Integer mobClass;
        @NotNull(field = "怪物类型")
        private Integer mobType;
        @Positive(field = "等级")
        private Integer level;
        @Positive(field = "生命值")
        private Integer hp;
        @Positive(field = "伤害")
        private Integer damage;
        @Positive(field = "护甲")
        private Integer amour;
    }

      模型注解添加完毕,我们在BaseController中添加一个通用的校验方法,方便在各个Controller中调用:

    public abstract class BaseController {
        ......
        ......
        @Autowired
        protected Validator validator;
        
        ......
        ......
    
        protected CommonResult validate(Object object, Class... classes) {
            Set<ConstraintViolation<Object>> set = validator.validate(object, classes);
            if (set != null && set.size() > 0) {
                ConstraintViolation constraintViolation = set.iterator().next();
                return CommonResult.fail(constraintViolation.getMessage());
            }
    
            return CommonResult.success();
        }
    }

      在MapMobController的新增和编辑方法中,添加校验逻辑,

    @Controller
    @RequestMapping("/manage/map_mob")
    public class MapMobController extends BaseController {
        ……
        ……
    
        @ResponseBody
        @RequestMapping(value = "/add", method = RequestMethod.POST)
        public Object add(@RequestBody MapMob mapMob) {
            try {
                CommonResult commonResult = this.validate(mapMob, ValidateGroup.Create.class);
                if (!commonResult.isSuccess())
                    return commonResult;
    
                mapMob.setCreateUser(this.currentUserName());
                mapMobManager.insert(mapMob);
                return CommonResult.success();
            } catch (Exception ex) {
                logger.error(ex.getMessage(), ex);
                return CommonResult.fail();
            }
        }
        
        ……
        ……
    
        @ResponseBody
        @RequestMapping(value = "/edit/{id}", method = RequestMethod.POST)
        public Object edit(@PathVariable String id, @RequestBody MapMob mapMob) {
            try {
                if (!id.equals(mapMob.getId())) {
                    return CommonResult.fail("id不一致");
                }
    
                CommonResult commonResult = this.validate(mapMob, ValidateGroup.Update.class);
                if (!commonResult.isSuccess())
                    return commonResult;
    
                mapMob.setUpdateUser(this.currentUserName());
                mapMobManager.update(mapMob);
                return CommonResult.success();
            } catch (Exception ex) {
                logger.error(ex.getMessage(), ex);
                return CommonResult.fail();
            }
        }
    }

    四、运行效果

      

    小结

      本章实现了对请求参数的后台校验,当然也可以在前端提前进行校验,但后端的校验一般必不可少。

      源码下载地址:https://idlestudio.ctfile.com/fs/14960372-384755438

      本文原文地址:https://www.cnblogs.com/lyosaki88/p/idlewow_7.html

      项目交流群:329989095

  • 相关阅读:
    html5 video标签如何禁止视频下载
    Redis源代码-数据结构Adlist双端列表
    HTML5分析实战WebSockets基本介绍
    Chromium on Android: Android在系统Chromium为了实现主消息循环分析
    Android AIDL使用特定的解释
    [LeetCode]Maximum Product Subarray
    OC省字典的数组摘要集
    CocoaChina 第四个测试
    Java在的时候,类定义HashSet初始化方法
    WSHPSRS-匹克选择列表生成器-SRS(R12.2.3)
  • 原文地址:https://www.cnblogs.com/lyosaki88/p/idlewow_7.html
Copyright © 2020-2023  润新知