【问题标题】:Spring internationalization: locale change problemSpring 国际化:语言环境更改问题
【发布时间】:2011-06-22 01:07:27
【问题描述】:

我有一个国际化的网络项目。它与http://www.springbyexample.org/examples/basic-webapp-internationalization-jsp-example.html 非常相似。 装饰器中有用于切换语言环境的链接。他们将 lang 参数添加到当前 url:

<a href="?lang=en">En</a> | <a href="?lang=ru">Ru</a> </span></td>

第一次国际化运行良好。但是后来我们发现了一些表格的问题。 表格:

<form:form action="${pageContext.request.contextPath}/branch/${branchId}/topic.html" modelAttribute="topicDto" method="POST" 
onsubmit="this.getAttribute('submitted')"> <!--Block multiple form submissions-->
<table border="2" width="100%">
    <tr>
        <td width="30%">
            <form:label path="topicName"><spring:message code="label.topic"/></form:label>
            <form:input path="topicName"/>
            <form:errors path="topicName"/>
        </td>
    </tr>
    <tr>
        <td height="200">
            <form:label path="bodyText"><spring:message code="label.text"/></form:label>
            <form:textarea path="bodyText"/>
            <form:errors path="bodyText"/>
        </td>
    </tr>
</table>
<input type="submit" value="<spring:message code="label.addtopic"/>"/>

控制器:

/**
 * @see Topic
 */
@Controller
public final class TopicController {
/**
 * Method handles newTopic.html GET request and display page for creation new topic
 *
 * @param branchId {@link org.jtalks.jcommune.model.entity.Branch} id
 * @return {@code ModelAndView} object with "newTopic" view, new {@link TopicDto} and branch id
 */
@RequestMapping(value = "/branch/{branchId}/topic/create", method = RequestMethod.GET)
public ModelAndView createPage(@PathVariable("branchId") Long branchId) {
    return new ModelAndView("newTopic")
            .addObject("topicDto", new TopicDto())
            .addObject("branchId", branchId);
}

/**
 * This method handles POST requests, it will be always activated when the user pressing "Submit topic"
 *
 * @param topicDto the object that provides communication between spring form and controller
 * @param result   {@link BindingResult} object for spring validation
 * @param branchId hold the current branchId
 * @return {@code ModelAndView} object which will be redirect to forum.html
 * @throws org.jtalks.jcommune.service.exceptions.NotFoundException
 *          when branch not found
 */
@RequestMapping(value = "/branch/{branchId}/topic", method = RequestMethod.POST)
public ModelAndView create(@Valid @ModelAttribute TopicDto topicDto,
                           BindingResult result,
                           @PathVariable("branchId") Long branchId) throws NotFoundException {
    if (result.hasErrors()) {
        return new ModelAndView("newTopic").addObject("branchId", branchId);
    } else {
        Topic createdTopic = topicService.createTopic(topicDto.getTopicName(), topicDto.getBodyText(),
                branchId);
        return new ModelAndView("redirect:/branch/" + branchId + "/topic/"
                + createdTopic.getId() + ".html");
    }
}

}

如果用户发布带有无效字段的表单,它将在字段之前看到验证消息。如果他此时切换页面语言,他将看到错误:

HTTP Status 405 - Request method 'GET' not supported
type Status report
message Request method 'GET' not supported
description The specified HTTP method is not allowed for the requested resource (Request method     'GET' not supported).
Apache Tomcat/7.0.11

您可以在我们的开发服务器上自己检查问题 http://deploy.jtalks.org/jcommune/index.html 例如在注册页面 http://deploy.jtalks.org/jcommune/registration.html 将表格留空并提交。您将看到验证消息。而不是更改语言并再次提交表单以查看指定的错误。

你可以在这里找到我们所有的资源http://fisheye.jtalks.org/

【问题讨论】:

    标签: java spring-mvc internationalization


    【解决方案1】:

    您将 lang 参数附加到将您带到页面的任何 URL。因此,如果您通过 /registration.html 访问表单,那么 En 和 Ru 链接也会指向 /registration.html。推测该控制器支持 GET,因此当您单击链接并生成 GET 请求时,一切正常。

    一旦您发布了表单,En 和 Ru 链接就会指向 /user.html,因为这就是您对页面进行编程的方式。单击这些链接,您将生成对 /user.html 的 GET 请求。这可能会失败,因为 /user.html 的控制器支持 POST 但不支持 GET。

    仅供参考,您可以准确地看到客户端和服务器端发生了什么。无论哪种情况,都可以使用任意数量的工具来观察来回的 HTTP 流量。

    您使用 Spring 的方式可能是切换语言发生在服务器端,因此您需要再次获取实际页面。特别是要修复您的注册表单,最简单的方法是扔掉用户已经输入的数据,即使在表单验证失败后,也只需将链接切换为指向 /registration.html。 (换句话说,不应该根据将您带到页面的任何 URL 生成链接。)用户可能不会在中间切换语言。但是,如果您必须保留表单数据,则需要采用不同的方法。

    【讨论】:

    • 感谢您的解释。但是我能做些什么来避免这个错误呢?我可以将用户重定向到切换语言的主页。但它对用户不友好。可能我可以在控制器之前的某个地方使用 GET 参数吗?
    • 我也可以设置 spirng-specific cookie form javascript 而不是传递 GET-param。效果很好,但我认为这不是最好的解决方案。
    【解决方案2】:

    我通过更改映射来解决问题

    @RequestMapping(value = "/branch/{branchId}/topic", method = RequestMethod.POST)
    

    @RequestMapping(value = "/branch/{branchId}/topic", method = {RequestMethod.POST, RequestMethod.GET})
    

    错误消失了。

    【讨论】:

      【解决方案3】:

      我认为您必须使用 POST/REDIRECT/GET 模式。

      http://en.wikipedia.org/wiki/Post/Redirect/Get

      例如:

      @Controller
      public final class TopicController {
      
      @RequestMapping(value = "/branch/{branchId}/topic/create", method = RequestMethod.GET)
      public ModelAndView createPage(@PathVariable("branchId") Long branchId) {
          return new ModelAndView("newTopic")
                  .addObject("topicDto", new TopicDto())
                  .addObject("branchId", branchId);
      }
      
      @RequestMapping(value = "/branch/{branchId}/topic", method = RequestMethod.POST)
      public ModelAndView create(@Valid @ModelAttribute TopicDto topicDto,
                                 BindingResult result,
                                 @PathVariable("branchId") Long branchId) throws NotFoundException {
          if (result.hasErrors()) {
              return new ModelAndView("newTopic").addObject("branchId", branchId);
          } else {
      
             /*Here you must create your topic, and add to DB, then redirect..*/
      
              return new ModelAndView("redirect:/TO_THE_VIEW_PAGE");
          }
      }
      
      @RequestMapping(value = "/TO_THE_VIEW_PAGE", method = RequestMethod.GET)
       public ModelAndView view(/*need parameters*/) {
      
          /*...There you must get your topic from DB, and go to view page..*/
      
          return new ModelAndView("/PATH_TO_THE_VIEW_PAGE");
      }
      

      如果您需要将数据(对象)传递给重定向后调用的 (view) 方法,您可以使用 RedirectAttributes 类。 http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/web/servlet/mvc/support/RedirectAttributes.html

      例如:

      @RequestMapping(value = "/branch/{branchId}/topic", method = RequestMethod.POST)
      public ModelAndView create(@Valid @ModelAttribute TopicDto topicDto,
                                 BindingResult result,
                                 @PathVariable("branchId") Long branchId, 
                                 RedirectAttributes redirectAttributes) throws NotFoundException {
      
              redirectAttributes.addFlashAttribute("topic", topicDto);
              redirectAttributes.addFlashAttribute("branchId", branchId);
      
              return new ModelAndView("redirect:/TO_THE_VIEW_PAGE");
          }
      }
      

      然后在view 方法中获取这些属性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多