You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何限制Spring Boot API禁止传入重复查询参数?

处理Spring Boot中重复查询参数的400错误返回

方案一:自定义校验注解(推荐,符合注解实现需求)

这种方式可以精准控制哪些参数需要校验重复,步骤如下:

  1. 定义自定义校验注解@NoDuplicateParam
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = NoDuplicateParamValidator.class)
public @interface NoDuplicateParam {
    String message() default "重复的查询参数不被允许";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
  1. 实现对应的校验器NoDuplicateParamValidator
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

public class NoDuplicateParamValidator implements ConstraintValidator<NoDuplicateParam, String> {

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) return true;
        
        HttpServletRequest request = attributes.getRequest();
        String paramName = context.getPropertyName();
        String[] paramValues = request.getParameterValues(paramName);
        
        return paramValues == null || paramValues.length <= 1;
    }
}
  1. 在控制器中使用注解,记得开启方法级校验
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Validated // 必须添加此注解启用参数校验
public class MyApiController {

    @GetMapping("/my-api")
    public String myApi(@NoDuplicateParam @RequestParam String foo) {
        return foo;
    }
}
  1. 配置全局异常处理器,捕获校验异常返回400
import jakarta.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<String> handleValidationExceptions(MethodArgumentNotValidException ex) {
        FieldError error = ex.getBindingResult().getFieldError();
        String message = error != null ? error.getDefaultMessage() : "参数校验失败";
        return new ResponseEntity<>(message, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<String> handleConstraintViolationException(ConstraintViolationException ex) {
        String message = ex.getConstraintViolations().stream()
                .map(violation -> violation.getMessage())
                .findFirst()
                .orElse("参数校验失败");
        return new ResponseEntity<>(message, HttpStatus.BAD_REQUEST);
    }
}

方案二:全局过滤器拦截所有重复参数

如果需要所有接口都禁止重复查询参数,可以写一个过滤器在请求到达控制器前拦截:

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Enumeration;

@Component
public class DuplicateParamFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        Enumeration<String> paramNames = httpRequest.getParameterNames();
        boolean hasDuplicate = false;
        String duplicateParam = "";

        while (paramNames.hasMoreElements()) {
            String paramName = paramNames.nextElement();
            String[] values = httpRequest.getParameterValues(paramName);
            if (values != null && values.length > 1) {
                hasDuplicate = true;
                duplicateParam = paramName;
                break;
            }
        }

        if (hasDuplicate) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            httpResponse.getWriter().write("参数 " + duplicateParam + " 不允许重复");
            return;
        }

        chain.doFilter(request, response);
    }
}

方案三:修改Spring参数解析逻辑

通过自定义参数解析器,替换默认的RequestParamMethodArgumentResolver,当发现参数有多个值时直接抛出异常:

  1. 自定义参数解析器
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestParamMethodArgumentResolver;

public class NoDuplicateRequestParamResolver extends RequestParamMethodArgumentResolver {

    public NoDuplicateRequestParamResolver(boolean useDefaultResolution) {
        super(useDefaultResolution);
    }

    @Override
    protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
        HttpServletRequest httpRequest = request.getNativeRequest(HttpServletRequest.class);
        if (httpRequest != null) {
            String[] values = httpRequest.getParameterValues(name);
            if (values != null && values.length > 1) {
                throw new IllegalArgumentException("参数 " + name + " 不允许重复");
            }
        }
        return super.resolveName(name, parameter, request);
    }
}
  1. 注册解析器到Spring容器
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new NoDuplicateRequestParamResolver(true));
    }
}
  1. 全局异常处理器添加IllegalArgumentException捕获
    在之前的GlobalExceptionHandler中新增:
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException ex) {
    return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
}

内容的提问来源于stack exchange,提问作者Brunke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 16:22:08