一尘不染

How to prevent parameter binding from interpreting commas in Spring 3.0.5?

spring

考虑以下控制器方法:

@RequestMapping(value = "/test", method = RequestMethod.GET)
public void test(@RequestParam(value = "fq", required = false) String[] filterQuery) {
    logger.debug(fq = " + StringUtils.join(filterQuery, "|"));
}

这是不同fq组合的输出:

  1. /test?fq=foo 结果是 fq = foo
  2. /test?fq=foo&fq=bar 结果是 fq = foo|bar
  3. /test?fq=foo,bar 结果是 fq = foo|bar
  4. /test?fq=foo,bar&fq=bash 结果是 fq = foo,bar|bash
  5. /test?fq=foo,bar&fq=结果是 fq = foo,bar|

示例3是问题所在。我期望(想要/需要)它输出fq = foo,bar

我已经尝试过使用\和转义逗号,%3C但是工作很少。

如果我查看HttpServletRequest对象的版本:

String[] fqs = request.getParameterValues("fq");
logger.debug(fqs = " + StringUtils.join(fqs, "|"));

它输出预期的输出:fqs = foo,bar。因此,“问题”在于Spring数据绑定。

我可以绕过Spring的绑定和使用,HttpServletRequest但是我真的不想要,因为我在真实代码中使用了支持bean(正在发生相同的事情),并且不想重新实现绑定功能。我希望有人可以提供一种通过转义或其他机制防止这种行为的简单方法。

TIA

更新:我在Twitter上发布了此问,并得到了答复,说预期的输出随Spring 3.0.4.RELEASE一起出现。我现在已经确认是这种情况,因此是一个临时解决方案。我将继续并将其记录为Spring JIRA系统上的错误。如果任何人都可以提供解决方法或使用3.0.5进行修复,我将接受他们的回答。


阅读 432

收藏
2020-04-13

共1个答案

一尘不染

我已经测试了你的代码:令人难以置信,但是我无法重现你的问题。我已经下载了最新版本的spring(3.0.5),这是我的控制器:

package test;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/test/**")
public class MyController {

    private static final Logger logger = Logger.getLogger(MyController.class);

    @RequestMapping(value = "/test/params", method = RequestMethod.GET)
    public void test(SearchRequestParams requestParams, BindingResult result) {
    logger.debug("fq = " + StringUtils.join(requestParams.getFq(), "|"));
    }
}

这是我的SearchRequestParams类:

package test;

public class SearchRequestParams {
    private String[] fq;

    public String[] getFq() {
    return fq;
    }

    public void setFq(String[] fq) {
    this.fq = fq;
    }
}

这是我简单的spring配置:

<bean id="urlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />

<bean class="test.MyController" />

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix">
        <value>/WEB-INF/jsp/</value>
    </property>
    <property name="suffix">
        <value>.jsp</value>
    </property>
</bean>

我已经在tomcat 7.0.8中测试了我的代码;输入时,我http://localhost:8080/testweb/test/params.htm?fq=foo,bar可以在以下行中读取日志文件:DEBUG fq = foo,bar。我的代码与你的代码有什么区别?难道我做错了什么?我想为你提供帮助,因此,如果你有任何疑问或可以为你做其他测试,那将是一种荣幸。

更新/解决方案
通过你的代码,我重现了该问题;你<mvc:annotation-driven />在分派器Servlet配置中具有标记,因此你默默使用默认的转换服务,实例FormattingConversionService,其中包含从String到的默认转换器String[],使用逗号作为分隔符。你必须使用另一个转换服务Bean,其中包含你自己的从String到的转换器String[]。你应该使用其他分隔符,我选择使用“;” 因为它是查询字符串中常用的分隔符(“?first = 1; second = 2; third = 3”):

import org.springframework.core.convert.converter.Converter;
import org.springframework.util.StringUtils;

public class CustomStringToArrayConverter implements Converter<String, String[]>{
   @Override
    public String[] convert(String source) {
        return StringUtils.delimitedListToStringArray(source, ";");
    }
}

然后,你必须在配置中指定此转换服务bean:

<mvc:annotation-driven conversion-service="conversionService" />

<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="au.org.ala.testspringbinding.CustomStringToArrayConverter" />
        </list>
    </property>
</bean>

该问题已解决,现在你应该检查是否有副作用。我希望你在应用程序中不需要原始的从String到的转换String[](以逗号作为分隔符)。

2020-04-13