【问题标题】:Render output format (HTML, JSON, XML) depending on parameter?根据参数呈现输出格式(HTML、JSON、XML)?
【发布时间】:2012-05-20 19:38:56
【问题描述】:

是否有 好的 或正确的方法来根据参数在 Play Framework 中呈现输出?示例:

对于 HTML:

http://localhost:9000/user/get/5?v=HTML // should render HTML template

对于 JSON:

http://localhost:9000/user/get/5?v=JSON // should render JSON template

我认为请求拦截器可以实现这一点,但我不知道如何开始或从哪里开始:-(

或者,也许,写一个通用的render method 来读取参数并按要求输出,但这在我看来有点矫枉过正?

【问题讨论】:

    标签: rest playframework-2.0


    【解决方案1】:

    如果/user/5?v=html/user/5?v=json 返回相同资源的两个表示,它们应该是相同的 URL,例如/user/5,根据REST principles.

    在客户端,您可以在请求中使用 Accept 标头来指示您希望服务器向您发送哪种表示形式。

    在服务器端,您可以使用 Play 2.1 编写以下代码来测试 Accept 标头的值:

    public static Result user(Long id) {
    
      User user = User.find.byId(id);
      if (user == null) {
        return notFound();
      }
    
      if (request().accepts("text/html")) {
        return ok(views.html.user(user));
      } else if (request().accepts("application/json")) {
        return ok(Json.toJson(user));
      } else {
        return badRequest();
      }
    }
    

    请注意,针对"text/html" 的测试应始终在任何其他内容类型之前编写,因为浏览器将其请求的Accept 标头设置为匹配所有类型的*/*

    如果您不想在每个操作中写入if (request().accepts(…)),您可以将其分解出来,例如像下面这样:

    public static Result user(Long id) {
      User user = User.find.byId(id);
      return representation(user, views.html.user.ref);
    }
    
    public static Result users() {
      List<User> users = User.find.all();
      return representation(users, views.html.users.ref);
    }
    
    private <T> Result representation(T resource, Template1<T, Html> html) {
      if (resource == null) {
        return notFound();
      }
    
      if (request().accepts("text/html")) {
        return ok(html.apply(resource));
      } else if (request().accepts("application/json")) {
        return ok(Json.toJson(resource));
      } else {
        return badRequest();
      }
    }
    

    【讨论】:

    • 好的,我想我会更喜欢这个。但是如何基于 HTML 表单或 JSON 对象(来自请求)绑定到 Java 对象,我还需要使用 if / else 语句来实现它们吗?还是bindFromRequest 两者都提供?
    • bindFromRequest 使用查询字符串和请求正文(可以是 JSON、url 形式编码等)。
    【解决方案2】:

    编写 2 个方法,使用 2 个路由(如您未指定,我将使用 Java 示例:

    public static Result userAsHtml(Long id) {
        return ok(someView.render(User.find.byId(id)));
    }
    
    public  static Result userAsJson(Long id) {
        return play.libs.Json.toJson(User.find.byId(id));
    }
    

    路线:

    /GET    /user/get/:id/html     controllers.YourController.userAsHtml(id:Long)
    /GET    /user/get/:id/json     controllers.YourController.userAsJson(id:Long)
    

    接下来你可以在其他视图中建立一个链接来显示用户的数据

    <a href="@routes.YourController.userAsHtml(user.id)">Show details</a>
    <a href="@routes.YourController.userAsJson(user.id)">Get JSON</a>
    

    或者别的什么...

    编辑#1

    您也可以使用普通的ifcase 来确定最终输出

    public static Result userAsV() {
        String vType = form().bindFromRequest().get("v");
    
        if (vTtype.equals("HTML")){
            return ok(someView.render(User.find.byId(id)));
        }
    
        return play.libs.Json.toJson(User.find.byId(id));
    }
    

    【讨论】:

    • 这可行,但复制内容不是我的首选。我没有直接的用例,但将来如果我想制作一个原生移动应用程序,我想请求只检索 JSON...
    【解决方案3】:

    我希望用户能够在浏览器中以 html 或 json 格式查看,因此接受方法对我不起作用。

    我通过将通用的 renderMethod 放在具有以下样式语法的基类中解决了这个问题

    public static Result requestType( )
    {
        if( request().uri().indexOf("json") != -1)
        {
            return ok(Json.toJson(request()));
        }
        else 
        {
            return ok("Got HTML request " + request() );
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-19
      • 1970-01-01
      • 2021-04-26
      • 1970-01-01
      • 2015-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多