Java后端开发数据校验工作

1.数据校验该谁做?

当我们随便打开一个网站注册页面的时候,用户名和密码等等属性往往会伴随着数据校验的工作,

身为后端开学学习的小白,我们应该知道数据校验这个工作该谁做?

1.前端工程师需要在页面通过JavaScript代码等等来设置数据校验

2.后端开发也需要通过Java代码等等来设置数据校验

2.数据校验小案例

打开百度的注册页面,当我们输入用户名过长的时候,页面上会提示我们"用户名不能超过7个汉字或者14个字符"

设想一下,如果这个数据校验工作由后端开发来实现流程大概是这样的:

1.前端界面输入框由用户输入信息

2.通过点击别的区域由JavaScript代码来接受这个事件

3.JavaScript将接收到的事件信息通过ajax,axios等等发给后端

4.后端接受数据,进行校验,然后传递给前端

仅仅是这么一个小功能,就耗费大量的流程时间显然是不合理的。

不妨再设想一下,如果这个数据校验仅仅由前端开发来实现流程大概是这样的:

1.前端页面输入框由用户输入信息

2.通过点击事件或者别的事件获取到信息

3.前端进行数据校验并显示

听起来好像没有什么问题,而且流程也简化了很多

但是作为开发无论是前端还有后端,我们都不能简单的将用户想象成好人,更多的应该是想象为居心叵测的坏人,如果他们使用python爬虫,postman工具这么一些程序或者软件来绕过前端js代码数据验证,那前端没有一点办法。

所以呢数据校验这个工作应该由前后端协同来开发,从而应对不同的业务场景。

3.validation验证框架

1 关于Spring Validation

一种方式是如果我们仅仅凭人力来实现数据的校验,不合法可以抛出异常,但是工作量和代码复杂度会比较高 ,而且很有可能会因为疏忽遗漏等等造成一些本不该出现的bug或者缺失的

第二种方式就是采用市场上主流的 Spring Validation 框架去实现校验,所以 Spring Validation 框架的主要作用是 检查参数的基本有效性。

2 使用流程

在Spring Boot工程中,使用此框架需要添加依赖,并刷新maven

<!-- Spring Boot支持Spring Validation的依赖项,用于检查参数的基本有效性 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

springboot内置了validation框架的,可以通过IDEA在项目初始化的时候直接勾选

3 快速入门

1.在处理请求的方法的参数列表中,在POJO类型的参数上添加@Validated注解,表示需要通过Spring Validation框架检查此参数,例如UserController中注册功能:

2.在此POJO类中的属性上,添加对应的检查注解,以配置检查规则,

例如,添加@NotNull注解,就表示“不允许为null”的规则!

UserDTO类  

此时应该加的注解都加了,该做的事情也都做完,但是仔细想一想其实疏忽了一个大问题,

如果数据校验框架validation校验完毕了,该怎么办?是直接报错?还是抛出异常?还是返回一些什么东西?

3.重启工程,在Knife4j中测试,当提交请求时,如果username参数为 null,服务器端将响应400错误。

 同时终端也出现了异常, MethodArgumentNotValidException:方法参数无效的异常

如果业务逻辑简单一些,验证的流程到这里其实就已经结束了,只需要处理一下异常然后由前端加一些页面来为用户显示

具体的流程请点击下面的链接,里面有详细的教程

Spring MVC中异常处理_springmvc全局异常处理-优快云博客

但是平常的数据校验不会这么简单,所以我们仍然需要掌握更多的数据校验注解

4.明确提示消息

当提交的username的值为 null 时,可以发现异常已被处理!

但是,处理结果并不合适,因为,客户端得到此结果后,仍无法明确出现了什么错误!

所有的检查注解都可以配置message参数,用于对错误进行描述。

  • 第1步:@NotNull 注解中添加 message 参数

    @NotNull(message = "必须提交用户名")
    private String username;
  • 第2步:自定义枚举状态码 StatusCode

    VALIDATE_ERROR(3002, "参数校验失败")
  • 第3步:异常方法中获取提示信息 message

    在处理异常时,需要调用MethodArgumentNotValidException对象的getFieldError().getDefaultMessage()获取以上配置的描述文本

    @ExceptionHandler
    public JsonResult handleBindException(MethodArgumentNotValidException ex){
        /*
        	ex.getFieldError().getDefaultMessage():获取 @NotNull(message="xxx") 中message的消息
        */
        String message = ex.getFieldError().getDefaultMessage();
        return new JsonResult(StatusCode.VALIDATE_ERROR, message);
    }
  • 第4步:重启工程,在Knife4j中测试

5 常用注解

5.1 @NotNull注解

  • 作用:用于验证对象是否为 null

  • 用法:@NotNull 注解用于对象类型上

  • 示例

    @NotNull(message = "用户名不能为null")
    private String username;

5.2 @NotEmpty 注解

  • 作用:用于验证字符串是否为空,并且会检查是否为 null 值(为null值时报错)

  • 用法:用于字符串类型上

  • 示例

    @NotEmpty(message = "用户名不能为空")
    private String username;

5.3 @NotBlank 注解

  • 作用:不允许为空白,即不允许是“仅由空格、TAB等空白值组成的字符串”,也不允许为空字符串,也不允许为空值null

  • 用法:用于字符串类型上

  • 示例

    @NotBlank(message = "用户名不能为空白串")
    private String username;

5.4 @Size 注解

  • 作用:可以指定最小值和最大值限制字符串的长度

  • 用法:用于字符串类型参数

  • 示例

    @Size(min = 6, max = 20, message = "用户名长度必须在6到20之间")
    private String username;

5.5 @Range 注解

  • 作用:用于验证数字类型字段的取值范围,通过配置min和max属性来限制数值类型参数的值区间包括最小值和最大值

  • 用法:用于数值类型参数

  • 示例

    @Range(min = 1, max = 10, message = "年龄必须在1-10岁之间")
    private int age;
    
    @Range(min = 0.1, max = 1.0, message = "成绩必须在0.1到1.0之间")
    private double score;

6 非POJO参数校验

在 Spring Validation 中,除了对 POJO(Plain Old Java Object)进行校验的功能外,还支持对非 POJO 进行校验,比如 String、Integer、Double 等类型的参数。

6.1 使用流程

  • 在当前方法所在的类上添加 @Validated 注解

  • 在参数上添加对应的检查注解

6.2 使用示例

对于微博详情页的 id 参数进行范围校验,范围只能在1-10之间

  • 第1步:在类 WeiboController 中添加 @Validated 注解

    @Validated
    public class WeiboController {}
  • 第2步:在控制器方法参数 id 上添加对应的检查注解

  • public JsonResult selectById(
    (@Range(min = 1 , max = 500 , message = "查找微博id必须在1-500之间")
    @RequestParam("id") Long id )
  • 第3步:重启工程,在Knife4j或者浏览器中测试

1.@RequestParam注解

在这里的@RequestParam注解,

官方给出的解释:

给出的解释很抽象,我们可以这样通俗的解释:

后端开发的时候我们会根据url来进行请求访问后端服务器,比如

http://localhost:8080/v1/users/weibo?id=1

这里的@RequestParam就是用来接收请求的参数id的,可以在@RequestParam("id")注解上加上参数("id")这就代表了前端输入的地址,?后面必须是id=1的格式,如果参@RequestParam("abc")那就说明,地址?后面的格式必须是abc=1等等才能正确接收

那我之前也没有加过这个注解呀?不是照样可以正确接收吗?

它还是能正常拿到 ?id=1 的参数。

这是因为:

Spring Boot 会根据参数名自动去请求参数中匹配同名的字段,也就是 "id"。

但这种用法有几个问题:

  1. 不明确,不够语义化(看代码不知道参数从哪来的)

  2. 一旦参数名和多个来源都能匹配,就会出现歧义,比如路径参数、表单参数等

  3. Swagger、Knife4j 等工具无法解析这个参数来自哪儿,所以文档不会显示参数定义

我在这里把该注解去掉后,打开knife4j文档,发现没有Lond id这个请求参数了

 所以我们使用@RequestParam注解,功能之一便是搭配第三方的一些工具比如knife4j,来解决spring boot和别的工具框架的冲突。

更准确的说法是:

@RequestParam 是让 Spring 明确知道你这个参数来自 URL 的查询参数,同时也能让文档生成工具正确识别参数来源、类型、描述

2.@Parm注解

@ParamMyBatis 框架 提供的,用于:

在 Mapper 接口中为多个参数命名,方便在 SQL 映射文件中引用,MyBatis 在 Mapper 接口中,如果你没有使用 @Param 显式命名参数,它会自动使用 param1param2param3……这样的名字来表示位置参数。。

public interface UserMapper { 
    UserVO selectUser(
         @Param("username") String username,
         @Param("password") String password); 
}

你在对应的 UserMapper.xml 中这样写 SQL:

<select id="selectUser" resultType="com.xxx.UserVO">
 SELECT * FROM users 
 WHERE username = #{username} AND password = #{password} 
</select>

因为你用了 @Param("username"),所以在 XML 中你就可以直接用 #{username},否则 MyBatis 不知道你传入的参数叫什么。


 如果不写 @Param 会怎么样?

  • 如果方法里 只有一个参数,可以不写,MyBatis 会自动用 param1 来识别。

  • 如果方法有 多个参数而你不写 @Param,那你在 XML 中只能用 param1param2 来引用:

WHERE username = #{param1} AND password = #{param2}

可读性很差,而且代码体验也很差。 

 

在下面我将@Param去掉了,在UserMapper.xml中将#{}中内容换为 默认的param1, param2,通过knife4j测试,仍然可以登录成功 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值