路径参数@PathVariable,参数校验:@Validated(Controller上)+@Pattern

2023-12-21 10:04

本文主要是介绍路径参数@PathVariable,参数校验:@Validated(Controller上)+@Pattern,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

说明

路径参数 进行合法性校验。

在这里插入图片描述

主要使用场景为:校验 id 的长度,是否符合要求。

如果id长度不对,说明一定找不到此id对应的数据,也就不需要去操作数据库了,直接在接口层就拦截掉无效请求。

比如:通过ID查询一条记录、通过ID删除一条记录、通过ID修改一条记录,都是通过id来找到这条记录的,都应该对id进行合法性校验。

校验逻辑

有效格式

本文中的例子,是对删除用户接口的用户ID参数进行校验,此参数是路径参数,其正确格式应该为19位数字(雪花算法生成的ID)。

核心代码

开启校验,主要包含两个注解:

  1. 开启校验的注解:@Validated
  2. 校验格式的注解:@Pattern

异常统一处理:

  • ConstraintViolationException

校验不通过会抛出异常 ConstraintViolationException,需要在异常统一处理中,加入对应的处理逻辑,向前端返回适当的响应。

开启校验的注解:@Validated

@Slf4j
@RestController
@RequestMapping("response")
@Tag(name = "响应统一封装")
@Validated
public class ResponseController {// 接口代码,省略。。。
}

@Validated,是 @Valid 的变体,本例需要对接口方法的参数直接进行校验,所以使用 @Validated(经过测试,使用@Valid无效,不能开启校验)。

@Validated 官方解释如下:

JSR-303的javax.validation.Validity的变体,支持验证组的规范。
可以与Spring MVC处理程序方法参数一起使用。

在这里插入图片描述

校验格式的注解:@Pattern

使用位置为:需要校验的路径参数前;

包含的内容有:参数的校验格式 和 校验不通过时的提示语。

    @ApiLog@DeleteMapping("users/{id}")@Operation(summary = "删除用户")@Parameter(name = "id", description = "用户ID", example = "1234567890123456789")public void deleteUser(@PathVariable @Pattern(regexp = "^\\d{19}$", message = "id应为19位数字") String id) {log.info("测试,删除用户,DELETE请求。id=" + id);}

异常统一处理:ConstraintViolationException

    @ExceptionHandler@ResponseStatus(HttpStatus.BAD_REQUEST)public Result<String> handleException(ConstraintViolationException e, HandlerMethod handlerMethod) {logInfo(e, handlerMethod);String userMessage = UserTipGenerator.getUserMessage(e);HttpStatus httpStatus = HttpStatus.BAD_REQUEST;String errorMessage = String.format("【参数校验异常】(错误数量:%s):%s", e.getConstraintViolations().size(), e.getMessage());return Result.fail(userMessage, String.valueOf(httpStatus.value()), errorMessage);}

不进行异常处理的接口响应

在这里插入图片描述

异常统一处理后的接口响应

在这里插入图片描述

异常统一处理代码

在这里插入图片描述

完整示例代码

接口校验

package com.example.web.response.controller;import com.example.core.log.annotation.ApiLog;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.validation.constraints.Pattern;@Slf4j
@RestController
@RequestMapping("response")
@Tag(name = "响应统一封装")
@Validated
public class ResponseController {@ApiLog@DeleteMapping("users/{id}")@Operation(summary = "删除用户")@Parameter(name = "id", description = "用户ID", example = "1234567890123456789")public void deleteUser(@PathVariable @Pattern(regexp = "^\\d{19}$", message = "id应为19位数字") String id) {log.info("测试,删除用户,DELETE请求。id=" + id);}// 其他接口省略 ...}

异常统一处理

package com.example.core.advice;import com.example.core.advice.util.ErrorMessageGenerator;
import com.example.core.advice.util.UserTipGenerator;
import com.example.core.model.BusinessException;
import com.example.core.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.HandlerMethod;import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.List;@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {private final HttpServletRequest request;public GlobalExceptionHandler(HttpServletRequest request) {this.request = request;}/*** Get请求,参数校验异常:对象参数校验。*/@ExceptionHandler@ResponseStatus(HttpStatus.BAD_REQUEST)public Result<Void> handleException(BindException e, HandlerMethod handlerMethod) {logInfo(e, handlerMethod);List<FieldError> fieldErrors = e.getFieldErrors();String userMessage = UserTipGenerator.getUserMessage(fieldErrors);String errorMessageCore = ErrorMessageGenerator.getErrorMessage(fieldErrors);HttpStatus httpStatus = HttpStatus.BAD_REQUEST;String errorMessage = String.format("【参数校验异常】(错误数量:%s):%s", e.getErrorCount(), errorMessageCore);return Result.fail(userMessage, String.valueOf(httpStatus.value()), errorMessage);}@ExceptionHandler@ResponseStatus(HttpStatus.BAD_REQUEST)public Result<String> handleException(ConstraintViolationException e, HandlerMethod handlerMethod) {logInfo(e, handlerMethod);String userMessage = UserTipGenerator.getUserMessage(e);HttpStatus httpStatus = HttpStatus.BAD_REQUEST;String errorMessage = String.format("【参数校验异常】(错误数量:%s):%s", e.getConstraintViolations().size(), e.getMessage());return Result.fail(userMessage, String.valueOf(httpStatus.value()), errorMessage);}/*** 业务异常处理*/@ExceptionHandler@ResponseStatus(HttpStatus.BAD_REQUEST)public Result<Void> handleException(BusinessException e, HandlerMethod handlerMethod) {logInfo(e, handlerMethod);return Result.fail(e.getUserMessage(), e.getErrorCode(), e.getErrorMessage());}private void logInfo(Exception e, HandlerMethod handlerMethod) {String message = getLogMessage(e, handlerMethod);log.info(message, e);}private String getLogMessage(Exception e, HandlerMethod handlerMethod) {String exceptionName = e.getClass().getName();String requestMethod = request.getMethod();String url = request.getRequestURI();String className = handlerMethod.getBean().getClass().getName();String methodName = handlerMethod.getMethod().getName();return String.format("\n接口:[%s:%s]\n异常名称:[%s]\n出现异常的方法:[%s.%s]\n异常信息:\n%s", requestMethod, url, exceptionName, className, methodName, e.getMessage());}}
package com.example.core.advice.util;import org.springframework.util.CollectionUtils;
import org.springframework.validation.FieldError;import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;/*** 用户提示生成器。** @author songguanxun* @date 2023-8-24*/
public class UserTipGenerator {/*** 获取用户提示(参数校验异常时)*/public static String getUserMessage(List<FieldError> errors) {StringBuilder stringBuilder = new StringBuilder();errors.forEach(error -> {String defaultMessage = error.getDefaultMessage();String numberFormatExceptionName = NumberFormatException.class.getName();if (defaultMessage != null && defaultMessage.contains(numberFormatExceptionName)) {String message = String.format("数字格式异常,当前输入为:[%s]", error.getRejectedValue());stringBuilder.append(message).append(";");} else {stringBuilder.append(defaultMessage).append(";");}});return stringBuilder.toString();}public static String getUserMessage(ConstraintViolationException e) {Set<ConstraintViolation<?>> sets = e.getConstraintViolations();if (CollectionUtils.isEmpty(sets)) {return "";}StringBuilder sb = new StringBuilder();sets.forEach(error -> sb.append(error.getMessage()).append(";"));return sb.toString();}}

校验效果

成功

在这里插入图片描述

失败

在这里插入图片描述

这篇关于路径参数@PathVariable,参数校验:@Validated(Controller上)+@Pattern的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/519557

相关文章

如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)

《如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)》:本文主要介绍如何更改pycharm缓存路径和虚拟内存分页文件位置(c盘爆红)问题,具有很好的参考价值,希望对大家有所帮助,如有... 目录先在你打算存放的地方建四个文件夹更改这四个路径就可以修改默认虚拟内存分页js文件的位置接下来从高级-

Python FastAPI实现JWT校验的完整指南

《PythonFastAPI实现JWT校验的完整指南》在现代Web开发中,构建安全的API接口是开发者必须面对的核心挑战之一,本文将深入探讨如何基于FastAPI实现JWT(JSONWebToken... 目录一、JWT认证的核心原理二、项目初始化与环境配置三、安全密码处理机制四、JWT令牌的生成与验证五、

一文详解PostgreSQL复制参数

《一文详解PostgreSQL复制参数》PostgreSQL作为一款功能强大的开源关系型数据库,其复制功能对于构建高可用性系统至关重要,本文给大家详细介绍了PostgreSQL的复制参数,需要的朋友可... 目录一、复制参数基础概念二、核心复制参数深度解析1. max_wal_seChina编程nders:WAL

一文详解如何查看本地MySQL的安装路径

《一文详解如何查看本地MySQL的安装路径》本地安装MySQL对于初学者或者开发人员来说是一项基础技能,但在安装过程中可能会遇到各种问题,:本文主要介绍如何查看本地MySQL安装路径的相关资料,需... 目录1. 如何查看本地mysql的安装路径1.1. 方法1:通过查询本地服务1.2. 方法2:通过MyS

Linux高并发场景下的网络参数调优实战指南

《Linux高并发场景下的网络参数调优实战指南》在高并发网络服务场景中,Linux内核的默认网络参数往往无法满足需求,导致性能瓶颈、连接超时甚至服务崩溃,本文基于真实案例分析,从参数解读、问题诊断到优... 目录一、问题背景:当并发连接遇上性能瓶颈1.1 案例环境1.2 初始参数分析二、深度诊断:连接状态与

Spring Validation中9个数据校验工具使用指南

《SpringValidation中9个数据校验工具使用指南》SpringValidation作为Spring生态系统的重要组成部分,提供了一套强大而灵活的数据校验机制,本文给大家介绍了Spring... 目录1. Bean Validation基础注解常用注解示例在控制器中应用2. 自定义约束验证器定义自

Spring Boot Controller处理HTTP请求体的方法

《SpringBootController处理HTTP请求体的方法》SpringBoot提供了强大的机制来处理不同Content-Type​的HTTP请求体,这主要依赖于HttpMessageCo... 目录一、核心机制:HttpMessageConverter​二、按Content-Type​处理详解1.

史上最全nginx详细参数配置

《史上最全nginx详细参数配置》Nginx是一个轻量级高性能的HTTP和反向代理服务器,同时也是一个通用代理服务器(TCP/UDP/IMAP/POP3/SMTP),最初由俄罗斯人IgorSyso... 目录基本命令默认配置搭建站点根据文件类型设置过期时间禁止文件缓存防盗链静态文件压缩指定定错误页面跨域问题

Python如何调用指定路径的模块

《Python如何调用指定路径的模块》要在Python中调用指定路径的模块,可以使用sys.path.append,importlib.util.spec_from_file_location和exe... 目录一、sys.path.append() 方法1. 方法简介2. 使用示例3. 注意事项二、imp

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及