Java 如何检查SpringRestController的未知查询参数?

Java 如何检查SpringRestController的未知查询参数?,java,spring,web-services,rest,spring-mvc,Java,Spring,Web Services,Rest,Spring Mvc,我有一个基本的rest控制器获取参数 如果查询字符串包含未定义的参数,如何拒绝连接 @RestController @RequestMapping("/") public class MyRest { @RequestMapping(value = "/{id}", method = RequestMethod.GET) @ResponseBody public String content(@PathVariable id, @RequestParam(value = "pag

我有一个基本的rest控制器获取参数

如果查询字符串包含未定义的参数,如何拒绝连接

@RestController
@RequestMapping("/")
public class MyRest {
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
    @ResponseBody
    public String content(@PathVariable id, @RequestParam(value = "page", required = false) int page) {
        return id;
    }
}
localhost:8080/myapp/123?paggge=1


当前调用此url时,只使用id执行该方法,忽略未知的
pagge
参数。一般来说,这很好,但如何验证它们并在返回HTTP状态代码的情况下进行验证?

在方法参数中添加
HttpServletRequest请求
,请执行以下操作:

String query = request.getQueryString()

在方法体中输入并验证。

您可以获得所有传入参数,并以您想要的方式进行处理。 引用spring文档:

在映射或多值映射参数上使用@RequestParam注释时,映射将填充所有请求参数


在控制器方法中,可以包含
@RequestParam Map
类型的参数,以访问传入的所有查询参数。可以使用泛型ArgsChecker服务类检查用户是否传入了无效参数。如果是这样,您可以抛出一个异常,该异常可以由@ControllerAdvice类处理

@RestController
@ExposesResourceFor(Widget.class)
@RequestMapping("/widgets")
public class WidgetController {


@Autowired
ArgsChecker<Widget> widgetArgsChecker;

    @RequestMapping(value = "", method = RequestMethod.GET, produces = {"application/hal+json"})
    public HttpEntity<PagedResources<WidgetResource>> findAll(@RequestParam @ApiIgnore Map<String, String> allRequestParams, Pageable pageable, PagedResourcesAssembler pageAssembler) {
        Set<String> invalidArgs = widgetArgsChecker.getInvalidArgs(allRequestParams.keySet());
        if (invalidArgs.size() > 0) {
            throw new QueryParameterNotSupportedException("The user supplied query parameter(s) that are not supported: " + invalidArgs + " . See below for a list of query paramters that are supported by the widget endpoint.", invalidArgs, widgetArgsChecker.getValidArgs());

        }
现在标记您想要查询的域类的字段 注释:

package com.widgetstore.api.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Queryable {
} 
@Getter
@Setter
public class Widget {
    @Queryable 
    private String productGuid;
    @Queryable 
    private String serialNumber;

    private String manufacturer;
现在确保在应用程序启动时创建ArgsChecker bean:

@SpringBootApplication
public class StartWidgetApi{

public static void main(String[] args){
    SpringApplication.run(StartWidgetApi.class);
}


@Bean(name="widgetArgsChecker")
public ArgsChecker<Widget> widgetArgsChecker(){
    return new ArgsChecker<Widget>(Widget.class);
}

//Other ArgsCheckers of different types may be used by other controllers.
@Bean(name="fooArgsChecker")
public ArgsChecker<Foo> fooArgsChecker(){
    return new ArgsChecker<Foo>(Foo.class);
 }
}

我想分享一种不同的方式,因为我发现ametiste的答案过于手工,mancini0的答案过于冗长

假设您使用Spring框架验证API将请求参数绑定到对象
APIRESQUEST

@InitBinder
public void initBinder(WebDataBinder binder, WebRequest request) {
    binder.setAllowedFields(ApiRequest.getAllowedRequestParameters());
}

@RequestMapping("/api")
public String content(@Valid ApiRequest request, BindingResult bindingResult) {
    return request.getId();
}
使用以下API请求定义

public class ApiRequest {
    private String id;

    public static String[] getAllowedRequestParameters() {
        return new String[]{
            "id"
        };
    }
}

然后可以使用
BindingResult
执行检查是否存在任何意外的请求参数,如下所示:

    String[] suppressedFields = bindingResult.getSuppressedFields();
    if (suppressedFields.length > 0) {
        // your code here
    }

不幸的是,这不起作用,因为只有当查询路径包含
..?query=testvalue
@membersound hm时才会设置查询,我可能误解了。在params中使用
HttpServletRequest
,在方法中使用
String query=request.getQueryString()
怎么样?太好了。相应地更新了答案。:)不是通过编写代码进行实际验证,而是可以使用一些JSR303验证吗?或者其他验证?@Rajas不太可能,因为你通常只需要忽略任何未知参数,只验证你实际使用的参数。对于你使用的参数,当然有。我想知道…为什么这很重要?如果您不接受该参数,让它掉在地板上也无妨。是否有一种方法可以返回“400错误请求”,而不必每次都检查
bindingResult
 {"timestamp": 2017-01-10'T'blahblah, "errorMessage": "The user supplied query parameter(s) that are not supported: ["someUnknownField","someOtherField"]. See below for a list of allowed query parameters." ,
"allowableParameters": ["productGuid","serialNumber"]
}
@InitBinder
public void initBinder(WebDataBinder binder, WebRequest request) {
    binder.setAllowedFields(ApiRequest.getAllowedRequestParameters());
}

@RequestMapping("/api")
public String content(@Valid ApiRequest request, BindingResult bindingResult) {
    return request.getId();
}
public class ApiRequest {
    private String id;

    public static String[] getAllowedRequestParameters() {
        return new String[]{
            "id"
        };
    }
    String[] suppressedFields = bindingResult.getSuppressedFields();
    if (suppressedFields.length > 0) {
        // your code here
    }