验证可选字段的请求参数名称-spring引导
如果您有这样描述的端点:验证可选字段的请求参数名称-spring引导,spring,spring-boot,spring-mvc,Spring,Spring Boot,Spring Mvc,如果您有这样描述的端点: @GetMapping("/hello") public String sayHello(@RequestParam(name= "my_id", required=false) myId, @RequestParam(name= "my_name") myName){ // return something } 问题: 此端点的使用者可能会在请求中发送无效的参数名称 /hello?我的名字=adam&a=1&b=2,它会正常工作 目标: 能够使用正确的方法验
@GetMapping("/hello")
public String sayHello(@RequestParam(name= "my_id", required=false) myId, @RequestParam(name= "my_name") myName){
// return something
}
问题:
此端点的使用者可能会在请求中发送无效的参数名称
/hello?我的名字=adam&a=1&b=2
,它会正常工作
目标:
能够使用正确的方法验证可选的请求参数名称
实际解决方案:
我已经实现了一个解决方案(对我来说,它不是正确的解决方案),我扩展了一个HandlerInterceptorAdapter
,并将其注册到WebMVCConfigure
:
/**
*
* Interceptor for unknown request parameters
*
*/
public class MethodParamNamesHandler extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
ArrayList<String> queryParams = Collections.list(request.getParameterNames());
MethodParameter[] methodParameters = ((HandlerMethod) handler).getMethodParameters();
Map<String, String> methodParametersMap = new HashMap<>();
if(Objects.nonNull(methodParameters)){
methodParametersMap = Arrays.stream(methodParameters)
.map(m -> m.getParameter().getName())
.collect(Collectors.toMap(Function.identity(),Function.identity()));
}
Set<String> unknownParameters = collectUnknownParameters(methodParametersMap, queryParams);
if(!CollectionUtils.isEmpty(unknownParameters)){
throw new InvalidParameterNameException("Invalid parameters names", unknownParameters);
}
return super.preHandle(request,response,handler);
}
/**
* Extract unknown properties from a list of parameters
* @param allParams
* @param queryParam
* @return
*/
private Set<String> collectUnknownParameters(Map<String, String> allParams, List<String> queryParam){
return queryParam.stream()
.filter(param -> !allParams.containsKey(param))
.collect(Collectors.toSet());
}
}
/**
*
*未知请求参数的拦截器
*
*/
公共类MethodParamNameHandler扩展HandlerInterceptorAdapter{
@凌驾
公共布尔预处理(HttpServletRequest请求、HttpServletResponse响应、对象处理程序)引发异常{
ArrayList queryParams=Collections.list(request.getParameterNames());
MethodParameter[]methodParameters=((HandlerMethod)处理程序).getMethodParameters();
Map methodParametersMap=新HashMap();
if(Objects.nonNull(methodParameters)){
methodParametersMap=Arrays.stream(methodParameters)
.map(m->m.getParameter().getName())
.collect(Collectors.toMap(Function.identity(),Function.identity());
}
Set unknownParameters=collectUnknownParameters(methodParametersMap,queryParams);
如果(!CollectionUtils.isEmpty(未知参数)){
抛出新的InvalidParameterNameException(“无效参数名称”,未知参数);
}
返回super.preHandle(请求、响应、处理程序);
}
/**
*从参数列表中提取未知属性
*@param-allParams
*@param queryParam
*@返回
*/
私有集合collectUnknownParameters(映射所有参数、列表查询参数){
返回queryParam.stream()
.filter(参数->!allParams.containsKey(参数))
.collect(收集器.toSet());
}
}
缺点:
这种解决方案的缺点是它基于方法参数,
它将使用名称myId
而不是myu id
,这可以通过将大写单词转换为snake-case来解决问题;但这并不是一个好的解决方案,因为您可以这样做:sayHello(@RequestParam(name=“my_id”,required=false)anotherName)
问题:
有没有合适的方法来实现这一点?从参数中获取可选注释并检查其名称参数。您可以尝试
@RequestParam Map reqParam
捕获所有请求参数,否则可以使用SpringValidator@ZigmaEmpire这将为我带来请求中发送的参数,在我的实际解决方案中,它相当于arraylistqueryparams=Collections.list(request.getParameterNames())你就不能这么做吗?公共字符串sayHello(@RequestParam(name=“my_id”,required=false)Long myId,@RequestParam(name=“my_name”)String myName)@RobScully对不起,我不明白你的建议!从参数中获取可选注释并检查其名称参数。您可以尝试@RequestParam Map reqParam
捕获所有请求参数,否则可以使用SpringValidator@ZigmaEmpire这将为我带来请求中发送的参数,在我的实际解决方案中,它相当于arraylistqueryparams=Collections.list(request.getParameterNames())你就不能这么做吗?公共字符串sayHello(@RequestParam(name=“my_id”,required=false)Long myId,@RequestParam(name=“my_name”)String myName)@RobScully对不起,我不明白你的建议!