【问题标题】:Spring MVC redirect with variablesSpring MVC 使用变量重定向
【发布时间】:2013-10-09 19:18:23
【问题描述】:

我有以下 Spring MVC 3.2.4 方法:

@RequestMapping(value = "/products/{product}", method = RequestMethod.POST)
public String update(Product product, @Valid @ModelAttribute("productForm") ProductForm productForm, BindingResult bindingResult, Model model) {
    if (bindingResult.hasErrors()) {
        return "products/view";
    }
    mapper.map(productForm, product);
    productService.saveProduct(product);
    return "redirect:/products/{product}";
}

成功后,它应该将用户重定向回产品的详细信息。问题是我没有重定向到页面“/products/1”,而是重定向到页面“/products/Product [code=1234567890, name=Nejaky]”。看起来占位符 {product} 已替换为 product.toString() 而不是 URL 中的原始 ID。 我正在使用内置的 Spring Data 转换器:

<mvc:annotation-driven conversion-service="conversionService">
    <mvc:argument-resolvers>
        <bean class="org.springframework.data.web.PageableHandlerMethodArgumentResolver" />
    </mvc:argument-resolvers>
</mvc:annotation-driven>

<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />

<bean class="org.springframework.data.repository.support.DomainClassConverter">
    <constructor-arg ref="conversionService" />
</bean>

我应该怎么做才能使其正常工作并将我重定向回“/products/1”而不执行“redirect:/product”+product.getId()之类的操作?

【问题讨论】:

  • 您的模型中是否有一个名为“product”的属性,可能是通过 ModelAttribute 注释方法?

标签: spring spring-mvc redirect spring-data


【解决方案1】:

我们的故事始于RedirectView源代码,方法replaceUriTemplateVariables

protected StringBuilder replaceUriTemplateVariables(
        String targetUrl, Map<String, Object> model, Map<String, String> currentUriVariables, String encodingScheme)
        throws UnsupportedEncodingException {

    StringBuilder result = new StringBuilder();
    Matcher m = URI_TEMPLATE_VARIABLE_PATTERN.matcher(targetUrl);
    int endLastMatch = 0;
    while (m.find()) {
        String name = m.group(1);
        Object value = model.containsKey(name) ? model.remove(name) : currentUriVariables.get(name);
        Assert.notNull(value, "Model has no value for '" + name + "'");
        result.append(targetUrl.substring(endLastMatch, m.start()));
        result.append(UriUtils.encodePathSegment(value.toString(), encodingScheme));
        endLastMatch = m.end();
    }
    result.append(targetUrl.substring(endLastMatch, targetUrl.length()));
    return result;
}

如您所料,该方法使用value.toString(),其中value 是您在Model 中的product 对象。这里不涉及转换系统等其他组件。您的选择如下:

使用

"redirect:/product" + product.getId()

添加一个名为 "productId" 的模型属性并在视图名称中使用它

model.addAttribute("productId", product.getId());
"redirect:/product/{productId}"

或者使用 uri 变量。我还没有关于这些的信息。

【讨论】:

    【解决方案2】:

    好的,终于找到原因了。我不得不用@PathVariable 注释产品参数。想知道没有它也能正常工作。

    【讨论】:

    • 在这种特殊情况下,可能是因为 product 对象最终出现在模型中,然后在替换字符串时使用了该对象,但通常您甚至不必将 product 作为参数用于替换 {product} 以在重定向字符串中工作的处理程序方法。
    【解决方案3】:

    我知道这是一个老问题,但对于任何面临同样问题的人来说,这里就是答案

    只需将 RedirectAttributes 注入您的控制器并使用 redirectAtrr.addAttribute([attrbuteName],[attributeValue])

    @RequestMapping(value = "/products/{product}", method = RequestMethod.POST)
    public String update(Product product,@Valid,@ModelAttribute("productForm") ProductForm productForm,BindingResult bindingResult,Model model,RedirectAttributes redirectAttr) {
        if (bindingResult.hasErrors()) {
            return "products/view";
        }
        mapper.map(productForm, product);
        productService.saveProduct(product);
        redirectAttr.addAttributte("productId",product.getId());
        return "redirect:/products/{productId}";
    }
    

    阅读documentation了解更多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-23
      • 2014-06-20
      • 2015-06-05
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 2011-07-15
      • 2015-05-19
      相关资源
      最近更新 更多