如何在 Play Framework v1.2.7 中配置带有动态 id 属性的 POST 路由,该属性将加载 JPA 实体

Posted

技术标签:

【中文标题】如何在 Play Framework v1.2.7 中配置带有动态 id 属性的 POST 路由,该属性将加载 JPA 实体【英文标题】:How do I configure a POST route in Play Framework v1.2.7 with a dynamic id attribute that will load a JPA entity 【发布时间】:2013-09-14 09:42:07 【问题描述】:

我想要一个 http 路由“POST /users/2”,它可以将表单提交给带有动作签名 Application.saveUser(User user) 的控制器,该控制器将根据指定的实体 id 更新现有用户的详细信息URL 中的动态参数。 User 类型是一个 JPA 实体,如果在请求/表单中指定了参数“user.id”,则 Play 对 JPA 的支持将自动加载该实体。到目前为止,我一直将“user.id”指定为隐藏输入,但我真的希望 id 成为 URL 的一部分。

我在 URL 中包含用户 ID 的第一个想法是定义这样的路由:

POST /users/user.id   Application.saveUser()

不幸的是,这给出了以下异常:

Oops: PatternSyntaxException
An unexpected error occured caused by exception PatternSyntaxException: unknow class: user.id

play.exceptions.UnexpectedException: Unexpected Error
    at play.Invoker$Invocation.onException(Invoker.java:244)
    at play.Invoker$Invocation.run(Invoker.java:286)
    at Invocation.HTTP Request(Play!)
Caused by: jregex.PatternSyntaxException: unknow class: member.id
    at jregex.CharacterClass.parseName(jregex/CharacterClass.java:361)
    at jregex.Term.append(jregex/Term.java:482)
    at jregex.Term.makeTree(jregex/Term.java:259)
    at jregex.Term.makeTree(jregex/Term.java:219)
    at jregex.Term.makeTree(jregex/Term.java:206)
    at jregex.Pattern.compile(jregex/Pattern.java:164)
    at jregex.Pattern.<init>(jregex/Pattern.java:150)
    at jregex.Pattern.<init>(jregex/Pattern.java:108)
    at play.mvc.Router$Route.compute(Router.java:755)

我尝试的另一个选项是只使用“id”参数名称,希望 Play 能够将其与用户 id 属性匹配:

POST /users/id   Application.saveUser()

但这给出了预期的 NoRouteFoundException,因为“id”与操作方法参数名称“用户”不匹配。最后一个明显的选择是使用参数名称“用户”,并再次希望 Play 可以使用一些智能来计算出这是 id:

POST /users/user   Application.saveUser()

这确实使页面能够使用表单中指定的正确路由呈现,但在提交时未加载正确的 JPA 实体:

<form action="/users/3" method="post" accept-charset="utf-8" enctype="application/x-www-form-urlencoded">

我尝试的最后一种方法是进行映射,但不确定是否支持:

POST /users/user   Application.saveUser(user.id: user)

再次没有加载正确的 JPA 实体。我搜索了高低,但没有找到如何正确完成此操作的示例。

【问题讨论】:

【参考方案1】:

播放文档中有一个示例,它显示了解决您问题的方法: http://www.playframework.com/documentation/1.2.7/jpa#save (本章第二个代码sn-p)

您需要一条路线(就像您在第二种方法中建议的那样),您只需传递要编辑的模型的 id:

POST /users/id   Application.saveUser()

相应的操作方法可能如下所示:

public static void save(Long id) 
    User user = User.findById(id);  // here you load the entity you want to edit by it's id
    user.edit("user", params.all());  // here the entity will be edited
    validation.valid(user);
    if(validation.hasErrors()) 
        edit(id);
     else
        user.save(); // explicit save here
        show(id);
    

【讨论】:

好的,所以这种方法更明确,需要更多样板文件 - 准确地说是前三行 - 如果实体 id 以以下格式提供,则匹配 Play JPA 插件完成的自动加载插件理解的。我希望有一个稍微更优雅的解决方案,看起来应该是可能的,但这绝对是有效的,而不是一个巨大的负担。谢谢【参考方案2】:

[Hi tazmaniax],尝试同时包含 id 和 model,但只在您的路线中包含 id。

POST /users/id   Application.saveUser()

Application.saveUser(Long id, User user)

<form action="@Application.saveUser(user.id)" method="post".....

【讨论】:

感谢您的提示,看起来很有趣,很快就会尝试

以上是关于如何在 Play Framework v1.2.7 中配置带有动态 id 属性的 POST 路由,该属性将加载 JPA 实体的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Play Framework 2.0 中使用相对路径访问资源文件?

如何在 Play Framework 1.2 中实现 HTTP Basic Auth?

如何使用 Play Framework 显示 SQL?

如何在 Play Framework JSON Rest 上使用 java.time.LocalDate?

如何在 Play!Framework WebSockets ("wss://") 中使用 TLS

如何构建版本独立的 Play!Framework 2 模块?