【问题标题】:Can I mark a controller method as POST in Play using annotations?我可以使用注释在 Play 中将控制器方法标记为 POST 吗?
【发布时间】:2011-11-17 13:22:02
【问题描述】:

我在任何地方都没有找到这个 - 我可以告诉 Play!应该(仅)通过 HTTP POST 访问特定的控制器方法吗?

类似于 C# 的 Asp.Net MVC 中的HttpPost attribute

public class MyController extends Controller {

  @Post
  public void addPerson(String name, String address) {
  }
}

更新 - 我不明白添加 POST 路由的作用:

  1. POST 请求无需添加此类路由即可工作。
  2. 由于该方法仍被“Catch all”GET 规则捕获,即使添加 POST 路由也不会阻止对该方法的 GET 请求。

【问题讨论】:

  • 如果您希望仅通过 POST 访问您的方法,则需要删除 * catch all。无论如何,这一切都应该只用于开发。它还可以帮助您准确了解您所暴露的内容!
  • @mericano1 - 一切都非常适合遵循约定优于配置的习惯用法,我不认为这对生产不利(否则我将在那里复制控制器/操作列表......更多的维护)。我想我会提交一个功能请求。

标签: java playframework http-post


【解决方案1】:

您在路由文件中执行此操作:

POST /person/add   MyController.addPerson

关于此here 的更多文档。

【讨论】:

  • 我看到了这个选项,但是感觉有点别扭。另外,即使我添加了这个路由,这个方法也会响应 GET 请求,因为它会匹配默认的“Catch all”路由。是否有计划允许通过注释进行设置?我应该提交功能请求吗?
【解决方案2】:

我参加聚会有点晚了。 afaik没有内置注释, 但是你可以很容易地自己写一个:

注解/HttpMethod.java

/**
 * Add this annotation to your controller actions to force a get/post request. 
 * This is checked in globals.java, so ensure you also have @With(Global.class) 
 * in your controller
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface HttpMethod{
    String method() default "POST";
}

控制器/Global.java

/**
 * All the funky global stuff ... 
 */
public class Global extends Controller{

    @Before
    public static void before(){
        if( getActionAnnotation( HttpMethod.class ) != null ){
            HttpMethod method = getActionAnnotation( HttpMethod.class ); 
            if( !method.method().equals( request.method ) ){
                error( "Don't be evil! " ); 
            }
        }
    }
}

用法: 控制器/Admin.java

@With({Global.class, Secure.class})
public class Admin extends Controller {
    @HttpMethod(method="POST")
    public static void save( MyModel model ){
        // yey...
    }
}

【讨论】:

    【解决方案3】:

    你可以这样做:

    public static void onlyPost() {
      if (request.method.equals("POST")) {
         // ... Do stuff
         render(); 
      }
      else
        forbidden();
    }
    

    但请记住,您的代码和路由文件可能不同步。

    此外,您可以在路由文件中使用 Groovy 代码,因此无需重复。

    # Catch all
    #{if play.mode.isDev()}
    *   /{controller}/{action}       {controller}.{action}
    #{/if}
    

    【讨论】:

    • 对路线中的 groovy 很酷 - 但除此之外 - 我需要代码才能在 Prod 中工作,而不仅仅是 Dev。
    • 我会接受你的回答,因为这是我想要的下一个最好的东西 - 但请参阅我打开的关于用注释标记它的问题 - play.lighthouseapp.com/projects/57987-play-framework/tickets/…
    • 上面的 Groovy 代码禁用了 Prod 中的全部捕获,它实现了 @mericano1 的建议。但是让我们看看他们是否接受你的票。当有人使用错误的方法访问您的操作时,您期望什么 HTTP 响应?
    • 我猜404比较合适?
    猜你喜欢
    • 1970-01-01
    • 2011-04-12
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    相关资源
    最近更新 更多