Как предотвратить привязку параметров от интерпретации запятых в Spring 3.0.5? - программирование
Подтвердить что ты не робот

Как предотвратить привязку параметров от интерпретации запятых в Spring 3.0.5?

Рассмотрим следующий метод контроллера:

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

Вот результат для разных комбинаций fq:

  • /test?fq=foo приводит к fq = foo
  • /test?fq=foo&fq=bar приводит к fq = foo|bar
  • /test?fq=foo,bar приводит к fq = foo|bar
  • /test?fq=foo,bar&fq=bash приводит к fq = foo,bar|bash
  • /test?fq=foo,bar&fq= результат fq = foo,bar|

Пример 3 - проблема. Я ожидаю (хочу/нужно) его вывод fq = foo,bar.

Я попытался выйти из запятой с помощью \ и использовать %3C, но niether работать.

Если я посмотрю на версию объекта HttpServletRequest:

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

Он печатает ожидаемый результат: fqs = foo,bar. Таким образом, "проблема" связана с привязкой данных Spring.

Я мог бы обходить привязку Spring и использовать HttpServletRequest, но я действительно не хочу, поскольку я использую поддержку bean в моем реальном коде (то же самое происходит) и не хотят повторно реализовывать функциональные возможности привязки. Я надеюсь, что кто-то может обеспечить простой способ предотвратить это поведение посредством экранирования или какого-либо другого механизма.

ТИА

ОБНОВЛЕНИЕ:. Я разместил этот Q на Twitter и получил ответ, в котором говорилось ожидаемый вывод с Spring 3.0.4.RELEASE. Я подтвердил, что это так, и, следовательно, это временное решение. Я расскажу об этом как об ошибке в системе Spring JIRA. Если кто-то может обеспечить работу или исправить с помощью 3.0.5, я приму их ответ.

4b9b3361

Ответ 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 /> в конфигурации сервлета диспетчера, поэтому вы тихо используете службу преобразования по умолчанию, экземпляр 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[] (с запятой в качестве разделителя).;-)

Ответ 2

Я нашел самый элегантный и самый короткий путь для меня - добавьте @InitBinder в @Controller:

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(String[].class, new StringArrayPropertyEditor(null));
}

Он преобразует String в String [] без использования разделителя (null param), с Spring классом org.springframework.beans.propertyeditors.StringArrayPropertyEditor. Если кто-то из того же проекта будет использовать новый способ преобразования по умолчанию, это будет нормально.

Ответ 3

Как предложил Филипп Поттер, я отправляю "обновление" на мой вопрос в качестве ответа, поскольку его, возможно, было легко пропустить...

Отклонение вниз от Spring 3.0.5.RELEASE до 3.0.4.RELEASE исправлено при использовании аннотации @RequestParam, предполагая, что это ошибка с 3.0.5.

Однако он не исправляет связанную проблему при привязке к форме-поддержке bean - это то, что у меня есть в моем webapp. Я протестировал всю версию до 3.0.0.RELEASE и получил тот же результат (/test?fq=foo,bar производит fq = foo|bar).

например.

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

где SearchRequestParams содержит поле String[] fq.

Если у кого есть исправление, я с радостью приму их ответ.

Ответ 4

javanna уже указала правильную причину. Я просто хотел бы указать, что вы также можете полностью удалить StringToArrayConverter как показано здесь, и .

Ответ 5

Его взломать, но вы считали, что передаете свои параметры, ограниченные '-'

/test?fq=foo-bar results in fq = foo-bar
/test?fq=foo-bar&fq=bash results in fq = foo-bar|bash 

Или любой другой разделитель, возможно, ~, или!, или ^, или