2011-06-22 57 views
1

我有一个国际化的网络项目。这与http://www.springbyexample.org/examples/basic-webapp-internationalization-jsp-example.html非常相似。 在装饰器中有切换区域设置的链接。他们将lang param添加到当前网址中:春季国际化:语言环境变化问题

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

回答

0

我固定porblem通过改变映射从

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

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

和误差消失。

1

要附加到任何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将您带到页面中生成。)机会是用户不会在中间切换语言。但是,如果您必须保留表单数据,则需要采用不同的方法。

+0

感谢您的解释。但我能做些什么来避免这个错误?我可以将用户重定向到交换语言的主页面。但它不是用户友好的。可能我可以坚持得到控制器之前的某个地方的参数吗? – NullPointer

+0

我也可以设置spirng特定的cookie形式而不是传递GET-param。它很好用,但我认为这不是最好的解决方案。 – NullPointer

0

我想知道你必须使用POST/REDIRECT/GET patter。

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方法的那些属性。