• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Joanna Qian
Stay Hungry, Stay Foolish!
博客园    首页    新随笔    联系   管理    订阅  订阅
《Play for Java》学习笔记(四)Controller

play的一大优势是可以将HTTP映射到JAVA API代码(Type-safe mapping from HTTP to an idiomatic Scala or Java API),完美的实现了RestFul架构。

Play使用 Controllers来实现MVC结构,如下图所示,Controller是用来连接服务器业务逻辑(business logic)和前台浏览器HTTP请求(HTTP requests)的桥梁。

一、Actions, Controllers and Results

  • controller其实是一个继承了父类play.mvc.Controller的类,在该类中定义了多个action的方法,该类位于controllers包中,如下图

  • 每个action是一个JAVA方法,用于处理HTTP的请求并将处理结果发还给用户(Action可以看作是一个处理请求数据并产生一个结果放回给客户端的简单Java方法)
  • 每个action方法的返回值类型均为Result(play.mvc.Result),每个Result均对应一个HTTP请求(HTTP response),代表Http响应发送到客户端,即play.mvc.Results类提供了多个helpers来产生标准的HTTP回应,如ok()构建了一个200状态的相应,它包含一个text/plain的响应体
  • Results即结果。最简单的莫过于包含一个状态码、一组HTTP头和一个Http体的被发送到web客户端的Http Resul。这些Results被play.mvc.Result定义,play.mvc.Results 类提供了一些帮助产生标准Http Results的方法,下面的代码示例创建了各种Results:
public static Result index() {
    return ok("Hello world!");
}
//------------------------------------------------
Result ok = ok("Hello world!");
Result notFound = notFound();
Result pageNotFound = notFound("<h1>Page not found</h1>").as("text/html");
Result badRequest = badRequest(views.html.form.render(formWithErrors));
Result oops = internalServerError("Oops");
Result anyStatus = status(488, "Strange response type");
//------------------------------------------------------
// 重定向同样是简单的Results,把浏览器重定向到一个新的URL也不过是一种简单的result,不同的是这些result 类型没有响应体 public static Result index() { return redirect("/user/home"); } //-------------303----------------------------------- public static Result index() { return temporaryRedirect("/user/home"); }
//-------------TODO Result-----------------------------------
return TODO;

 (Status code: ok  -- 200, error, redirect, 404)

如何使用Result

如在controller中

public static Result list() {
    ...
    return ok(list.render(products));
}

 在模板中

<a href="@routes.Products.newProduct()" class="btn"> 

 二、HTTP routing(wire URLs to action methods)——绑定HTTP参数到JAVA方法(action)里的参数

  • 路由route是将每一个进来的Http请求转换成一个Action调用(action是contoller类里的静态的、公共的方法)的组件。
  • 一个Http请求在MVC框架中被视为一个事件,这一事件包含了两个主要的信息块:     请求路径和Http方法(get,post...)
  • 路由在conf/routes文件中被定义,并且会被编译,也就是说你能直接在浏览器中看到路由错误

路由route用于传送HTTP请求到JAVA的controller的action代码中,route、controller和action的关系如下图

route的语法书写规定如下:

其中:

1、The HTTP method——Http方法指任何被Http所支持的方法

GET, POST, PUT, DELETE, HEAD

2、URI pattern

  • 静态路径:   GET       /clients/all         controllers.Clients.list()
  • 动态路径:   GET      /product/:ean     controllers.Products.details(ean: String)
    • 带默认值的动态路径:        GET    /clients                                  controllers.Clients.list(page: Integer ?= 1)
    • 带固定值的路径:             GET    /                                            controllers.Application.show(page = "home")
    • 带可选项的动态路径:        GET  /api/list-all              controllers.Api.list(version ?=null)—— /api/list-all?version=3.0(???)
    • 带正则表达式的动态路径: GET    /product/$ean<[0-9]{13}>     controllers.Products.details(ean: Long) ——使用$id<regex>
    • 带可捕捉多个用/分隔的URI路径的动态路径:  GET  /files/*name  controllers.Application.download(name) ————如:GET /files/images/logo.png, name部分代表了 images/logo.png

3、反向路径:

说明: 没搞明白,以后补充

4、路由优先级

多个路由匹配同一个请求的时候就会产生冲突,这时候第一个路由会被使用。

三、处理HTTP响应

1、Play的Result的默认content type和字符集

  • 默认的Content-Type是text/plain, 如: Result textResult = ok("Hello World!"); 返回 text/plain
  • 默认的字符集为 utf-8
  • 修改为application/json, 如: Result jsonResult = ok(jerksonObject);

2. 设置content type
    Result htmlResult = ok("<h1>Hello World!</h1>").as("text/html");
   或

public static Result index() {
  response().setContentType(text/html; charset=iso-8859-1"); 
return ok("<h1>Hello World!</h1>");
}

3. 设置HTTP response头信息

public static Result index() {
  response().setContentType("text/html");
  response().setHeader(CACHE_CONTROL, "max-age=3600");
  response().setHeader(ETAG, "xxx");
  return ok("<h1>Hello World!</h1>");
}

4.将content type设置为返回JSON格式

public static Result index(){
  Map<String, String> itworks = new HashMap<String, String>();  
  itworks.put("message","It works");      
  return ok(plays.libs.Json.toJson(itworks));
}

返回结果为:     

四、Scope

有了controller和route,我们可以从接受用户的输入数据,并将处理结果返回给用户。现在我们开始讨论储存数据的有效范围和时间——scope。

  • play不保存任何服务器段的数据,数据要么保存在服务器,要么保存在客户端
  • 和J2EE有所不同,play有四种scope,如下图所示

(Session scope,Flash scope,Request scope,Response scope)

  • 如果要保持跨多个Http请求的数据,可以把他们保存在Session或者Flash作用域中。保存在Session中的数据在整个用户会话中可用,保存在Flash作用域中的数据仅在下个请求中可用。
  •  Session和Flash数据没有在服务器上储存,而是使用cookies在后续的Http请求之间传递(而是使用cookies被添加到后续的每个Http请求中),理解这一点很重要。也就是说数据大小受限制了(最大到4KB),并且只能存储字符。

 1. Context对象

  • Play中所有scope均存放在Context对象中,Context是一个final static类,其子对象有Request, Response, Session, 和Flash。
  • 我们可以使用current()方法获取当前的scope,然后进入Play的各个scope

 2. scope类型

1) request scope

该scope不能用于存储数据对象,只是用来进入当前请求的数据,如用HTML的表单的数据就是通过request scope提交的。

2)response scope
该scope不能用于存储数据对象,只是用来设置响应的content类型的,如设置响应的类型为XML:
     Context.current().response().setContentType("application/xml");

另外response对象还可以用来设置和删除Cookies

  • response().setCookie("theme","blue");
  • response().discardCookies("theme");

如根据Cookie设置主题

public static Result index() {
    if ("blue".equals(cookies("theme").value())){
    // Do something
    }
    ....
}

3) session scope

  • 只要客户端浏览器没有关闭,存储在session中是数据均不会消失。
  • 需要说明的是sessions不是存储在服务器端的,在每一次HTTP请求的时候添加上的。
  • sessions使用Cookie机制,使用数据大小是4kB,而且只能存储字符串

   3.1) 存储数据到session

   3.2) 在controller中使用session

4)flash scope

  • flash scope的生命周期位于两个请求之间, 这就是说当进行重定向的时候存储在flash scope的数据的有效的。
  • flash作用域的工作方式和Session很相似,但是有两点是不同的:
    • 数据仅保持在一个请求中
    • 数据未被签名,因此用户可以修改Flash cookie的数据

注意:Flash作用域仅应该被用于在简单的非Ajax应用中传递成功/失败消息。因为其数据仅仅传递给下一个请求,但是在复杂的web应用中它无法确保请求的顺序。总之,Flash作用域受到竞争条件限制。

有和没有flash的对比如下所示:

五、数据的安全性

针对存储在客户端的数据的安全性问题,play提供了一个Cookie key来确保用户无法修改Cookie数据。这个Cookie key存放在conf/application.conf文件中,如

    application.secret="FuqsIcSJlLppP8s?UpVYb5CvX1v55PVgHQ1Pk"

说明:  如果你的应用程序有多个实例,程序之间需要共享secret key(如两个服务器必须有相同的secret key),否则另一个程序无法验证数据

  • Use flash scope—— Flash scope is ideal for passing messages to the user (when a redirect is involved).
  • Use action methods——This is the entry point for your business logic. Keep them short and delegate all business logic to your business models.
  • Simple data binding is URL-centric data mapping to your action methods
posted on 2014-04-01 01:15  Joanna Qian  阅读(990)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3