• 作者:老汪软件技巧
  • 发表时间:2024-12-04 07:03
  • 浏览量:

大家好,我是苏三,又跟大家见面了。前言

对于开发人员来说,对用户输入的参数或者系统参数做校验,是日常工作之一。

很多小伙伴在写接口的时候,可能都会碰到一个问题:参数校验应该怎么写?

比如,开发一个用户注册接口,需要校验以下条件:

乍一看,这种校验逻辑看起来很简单嘛,直接写几个if就完事了。

但真的这么简单吗?

接下来我们就从传统的参数校验入手,看看问题出在哪,然后再聊聊Spring Boot 中如何优雅地实现参数校验,希望对你会有所帮助。

苏三的免费刷题网站:里面:面试八股文、BAT面试真题、工作内推、工作经验分享、技术专栏等等什么都有,欢迎收藏和转发。

一、传统参数校验的问题

很多人可能会直接在 Controller 里手写校验逻辑,比如下面这个代码:

@RestController
@RequestMapping("/api/users")
public class UserController {
    @PostMapping("/register")
    public ResponseEntity register(@RequestBody Map request) {
        String username = (String) request.get("username");
        if (username == null || username.length() < 3 || username.length() > 20) {
            return ResponseEntity.badRequest().body("用户名不能为空,且长度必须在3到20之间");
        }
        String password = (String) request.get("password");
        if (password == null || password.length() < 8) {
            return ResponseEntity.badRequest().body("密码不能为空,且长度至少为8个字符");
        }
        Integer age = (Integer) request.get("age");
        if (age == null || age <= 0 || age > 120) {
            return ResponseEntity.badRequest().body("年龄必须是正整数,且不能超过120");
        }
        return ResponseEntity.ok("注册成功!");
    }
}

这段代码乍一看没什么问题,但如果仔细分析,会发现一堆隐患:

代码冗余:校验逻辑散落在 Controller 里,写起来麻烦,后期维护更是灾难。重复劳动:类似的校验逻辑可能会出现在多个接口里,导致代码重复度极高。用户体验差:返回的错误信息不统一、不规范,前端开发还得猜用户输入到底哪儿错了。扩展性差:万一某天需要加新的校验规则,你可能要到处改代码。

所以,这种手写参数校验的方式,在简单场景下勉强能用,但如果业务变复杂,问题会越来越多。

那么问题来了,那有没有更优雅的方式来处理这些问题呢?

答:当然是有的。

二、Spring Boot 的参数校验机制

在 Spring Boot 中,我们可以使用Hibernate Validator(Bean Validation 的参考实现)来实现参数校验。

它的核心思路是:把校验逻辑从业务代码里抽离出来,用注解的方式声明校验规则。

接下来我们一步步来看怎么实现。

1. 使用注解进行参数校验

首先,定义一个用于接收用户注册参数的 DTO 对象:

@Data
public class UserRegistrationRequest {
    @NotNull(message = "用户名不能为空")
    @Size(min = 3, max = 20, message = "用户名长度必须在3到20之间")
    private String username;
    @NotNull(message = "密码不能为空")
    @Size(min = 8, message = "密码长度至少为8个字符")

_瞧瞧别人家的参数校验,那叫一个优雅!_瞧瞧别人家的参数校验,那叫一个优雅!

    private String password;     @NotNull(message = "年龄不能为空")     @Min(value = 1, message = "年龄必须是正整数")     @Max(value = 120, message = "年龄不能超过120")     private Integer age;     @Email(message = "邮箱格式不正确")     private String email; }

这里我们用了几个常见的校验注解:

这些注解由 Hibernate Validator 提供,基本涵盖了日常开发中的大部分校验需求。

然后,在 Controller 中这样写:

@RestController
@RequestMapping("/api/users")
public class UserController {
    @PostMapping("/register")
    public ResponseEntity register(@Valid @RequestBody UserRegistrationRequest request) {
        return ResponseEntity.ok("注册成功!");
    }
}

注意这里的@Valid注解,它的作用是告诉 Spring:对请求参数进行校验。

2. 统一处理校验错误

如果前端传的参数不合法,Spring 会抛出一个MethodArgumentNotValidException异常。默认情况下,这个异常返回的信息不太友好,可能是这样的:

{
  "timestamp": "2024-01-01T12:00:00.000+00:00",
  "status": 400,
  "error": "Bad Request",
  "message": "Validation failed for object='userRegistrationRequest'. Error count: 2",
  "path": "/api/users/register"
}

为了提升用户体验,我们可以用全局异常处理器来统一格式化错误信息:

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<StringString>> handleValidationException(MethodArgumentNotValidException ex) {
        Map<StringString> errors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error -> {
            errors.put(error.getField(), error.getDefaultMessage());
        });
        return ResponseEntity.badRequest().body(errors);
    }
}

现在,当参数校验失败时,返回的错误信息会变成这样:

{
  "username": "用户名长度必须在3到20之间",
  "password": "密码不能为空"
}

清晰又直观,用户一看就明白自己错在哪儿了。

最近就业形势比较困难,为了感谢各位小伙伴对苏三一直以来的支持,我特地创建了一些工作内推群, 看看能不能帮助到大家。

你可以在群里发布招聘信息,也可以内推工作,也可以在群里投递简历找工作,也可以在群里交流面试或者工作的话题。


上一条查看详情 +常用文件处理以及数据转化
下一条 查看详情 +没有了