处理Spring @RequestParam的重复值

时间:2014-04-02 16:21:41

标签: spring-mvc

我有一个带有基本请求映射的Spring 3.2控制器,如

@RequestMapping("/action")
public String action(@RequestParam("param") String param) {
    //do stuff...
    return "view";
}

此控制器处理由非技术业务用户创建的链接。有时用户会搞砸它并创建具有重复参数的链接,例如

www.example.com/action?param=value&param=value

参数完全相同,可能是复制/粘贴错误。

我的问题是Spring将这些欺骗连接在一起,所以当我只需要"value,value"时,上面的url会为param提供"value"

检测和处理这些重复项的好方法是什么?我知道我可以将@RequestParam的所有内容更改为List<String>并从那里开始,但是&# 39;在几十个请求映射上有很多样板。

理想情况下,有一种方法可以在Spring尝试绑定它们之前拦截和修改url参数 - 但仅限于此控制器。

3 个答案:

答案 0 :(得分:1)

一个好主意是用您自己的策略扩展AbstractNamedValueMethodArgumentResolver。然后可以在您认为必要的地方使用该策略。

此策略仅适用于Spring 3.1+,因为您使用的是Spring 3.2

,这对您来说不是问题

答案 1 :(得分:1)

我发现我可以注册一个自定义字符串属性编辑器来执行此操作。

class DuplicateParameterReducingPropertyEditor extends PropertyEditorSupport {

    Object value;

    @Override
    public void setValue(Object value) {
        if (value instanceof String[]) {
            String[] strings = (String[])value;
            Set<String> unique = Sets.newHashSet(strings);
            this.value = unique.toArray();
        } else {
            this.value = value;
        }
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        this.value = text;
    }

    @Override
    public String getAsText() {
        return value.toString();
    }

    @Override
    public Object getValue() {
        return value;
    }

};

我把它添加到我的控制器:

@InitBinder
public void initBinder(WebDataBinder binder) {

    PropertyEditor stringEditor = new DuplicateParameterReducingPropertyEditor();
    binder.registerCustomEditor(String.class, stringEditor);
}

因此,只要Spring遇到@RequestParam - 带注释的String方法参数,就会调用PropertyEditor来转换传入的数据(如果需要)。在重复参数的情况下,Spring将String[]值传递给属性编辑器setValue,然后我可以对其进行操作。

这确实有我想要的结果。不过,我不确定这一点的影响,所以我不能认为它是一个很好的解决方案。不必更改任何处理程序方法签名是一个很大的优点。

答案 2 :(得分:0)

我在Spring Boot中遇到了同样的问题。最终,我想出了使用转换器的这种解决方案,以防它对任何人都有帮助。

此方法应作为WebMvcConfigurer类的一部分添加。

@Override
public void addFormatters(FormatterRegistry registry) {
    // Duplicate query parameters converter
    registry.addConverter(new Converter<String[], String>() {
        public String convert(String[] arr) {
            return arr[arr.length - 1];             // Return the last value
        }
    });
}