【问题标题】:How to customize split-pattern for request parameter如何为请求参数自定义拆分模式
【发布时间】:2011-05-03 10:51:04
【问题描述】:

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

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 在 '&'-tokens 上拆分,而不是在 ','-tokens 上。例如。

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" />

【问题讨论】:

  • 你能告诉我们你的控制器代码吗?

标签: spring-mvc parameters split request


【解决方案1】:

我在尝试将 @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")

【讨论】:

    【解决方案2】:

    按照 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();
        }
    
    }
    

    【讨论】:

    • 您提到的ConversionServiceFactoryBean 配置对我不起作用,因为MyCustomCollectionToStringConverter 具有参数化而不是默认构造函数。我刚刚在afterPropertiesSet() 方法中添加了registry.addConverter(new MyCustomCollectionToStringConverter(this.getObject()));
    【解决方案3】:

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

    public class SearchParams {
    
        private String q = "";
        private String fq;
    
        public String[] getSplitFq() {
           // split and return the array
        }
    }
    

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

    【讨论】:

      【解决方案4】:

      您可以使用@InitBinder 注解来配置数组绑定。像这样的东西应该可以工作:

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

      你可以在Spring MVC documentation阅读更详细的解释

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-19
        • 2017-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多