如何自定义请求参数的拆分模式

时间:2011-05-03 10:51:04

标签: spring-mvc parameters split request

我的问题是我有以下网址:

http://localhost:8080/shiSolrClient/app/shi/search?q=xyz&fq=author:"Max, Muster"

我有一个映射这些requestParameters的bean:

public class SearchParams {

    private String q = "";
    private String[] fq;

    // getters goes here...
}

我的问题是Spring会自动在逗号上拆分fq参数。所以在我的bean中,fq中有两个字符串:

String[0]: author:"Max
String[1]: Muster"

我不想要这种行为。我想要的是告诉Spring拆分'&' - 令牌不是',' - 令牌。例如。

http://localhost:8080/shiSolrClient/app/shi/search?q=xyz&fq=author:"Max, Muster"&content:"someContent"

fq=     
String[0]: author:"Max, Muster"

String[1]: content:"someContent"

任何人都可以告诉我如何在Spring MVC 3中存档它

我的控制器如下:

@RequestMapping(value = "search", method = RequestMethod.GET)
public String search(SearchParams searchParams, BindingResult bindResult, Model  
   model)  {

    SolrQuery solrQ = getBasicQuery(searchParams).setQuery(searchParams.getQ());
    for(String fq : searchParams.getFq()) {
        solrQ.setParam("fq", fq);
    }
    try {
        QueryResponse rsp = getSolrServer().query(solrQ);
        model.addAttribute("solrResults", transformResults(rsp.getResults(),
           rsp.getHighlighting(), searchParams, rsp));
        model.addAttribute("facetFields", transformFacets(rsp.getFacetFields(),
           rsp.getFacetDates(), searchParams));
        model.addAttribute("pagination", calcPagination(searchParams, 
           rsp.getResults()));
   ...
}

我的Spring-Config看起来像这样:

<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />

<!-- Handles HTTP GET requests for /resources/** -->
<resources mapping="/resources/**" location="/resources/" />

<!-- Configure Apache Tiles for the view -->
<beans:bean id="tilesConfigurer" 
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
   <beans:property name="definitions">
          <beans:list>
      <beans:value>/WEB-INF/views/layout/layouts.xml</beans:value>
      <beans:value>/WEB-INF/views/hitlist/views.xml</beans:value>
      </beans:list>
   </beans:property>
</beans:bean>

<beans:bean id="viewResolver"
          class="org.springframework.web.servlet.view.UrlBasedViewResolver">
   <beans:property name="requestContextAttribute" value="requestContext"/>
   <beans:property name="viewClass" 
           value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</beans:bean>

<beans:bean id="messageSource"
      class="org.springframework.context.support.ResourceBundleMessageSource">
   <beans:property name="basenames">
      <beans:list>
      <beans:value>global</beans:value>
      <beans:value>hitlist</beans:value>
      <beans:value>local/messages</beans:value>
      </beans:list>
   </beans:property>
</beans:bean>

    <!-- Scans within the base package of the application for @Components to configure 
          as beans -->
<context:component-scan base-package="com.shi.solrclient.web" />

4 个答案:

答案 0 :(得分:3)

我遇到了一个类似的问题,试图将@RequestParameter与List一起使用(它一直被逗号删掉。

我提出的解决方案是在我的控制器方法中使用WebRequest参数,这允许我使用request.getParameterValues(“blar”)

@RequestMapping(value = "search", method = RequestMethod.GET)
public String search(WebRequest req, BindingResult bindResult, Model  model)  {
    String[] searchParams = req.getParameterValues("fq")

答案 1 :(得分:1)

为Eugene提议的String []注册自定义编辑器不起作用,因为在任何自定义编辑器使用之前,String []由CollectionToStringConverter转换为String。

为了使用除逗号之外的其他分隔符(这是CollectionToStringConverter的默认行为),您需要按照Spring MVC reference documentation中的说明添加自己的自定义转换器。

<bean id="conversionService"
        class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="example.MyCustomCollectionToStringConverter"/>
        </set>
    </property>
</bean>

为了实现MyCustomCollectionToStringConverter,您不能扩展CollectionToStringConverter,因为它是最终的,但您可以查看its source code来创建自己的。

final class MyCustomCollectionToStringConverter implements ConditionalGenericConverter {

    private static final String DELIMITER = "&";

    private final ConversionService conversionService;

    public MyCustomCollectionToStringConverter(ConversionService conversionService) {
        this.conversionService = conversionService;
    }

    @Override
    public Set<ConvertiblePair> getConvertibleTypes() {
        return Collections.singleton(new ConvertiblePair(Collection.class, String.class));
    }

    @Override
    public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
        return ConversionUtils.canConvertElements(sourceType.getElementTypeDescriptor(), targetType, this.conversionService);
    }

    @Override
    public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
        if (source == null) {
            return null;
        }
        Collection<?> sourceCollection = (Collection<?>) source;
        if (sourceCollection.size() == 0) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        int i = 0;
        for (Object sourceElement : sourceCollection) {
            if (i > 0) {
                sb.append(DELIMITER);
            }
            Object targetElement = this.conversionService.convert(sourceElement, sourceType.elementTypeDescriptor(sourceElement), targetType);
            sb.append(targetElement);
            i++;
        }
        return sb.toString();
    }

}

答案 2 :(得分:0)

由于没有人对此提出“正确”答案,因此最简单的选择可能是不让Spring根本拆分参数,而是在getter方法中添加拆分逻辑:

public class SearchParams {

    private String q = "";
    private String fq;

    public String[] getSplitFq() {
       // split and return the array
    }
}

这可能比试图说服Spring按照你自己的规范去做更容易。

答案 3 :(得分:0)

您可以使用@InitBinder批注配置数组绑定。这样的事情应该有效:

@InitBinder("fq")
public void fqBinderInit(WebDataBinder binder) {
  binder.registerCustomEditor(String[].class, new StringArrayPropertyEditor("&"));
}  

您可以在Spring MVC documentation

中阅读更详细的说明