play框架使用起来(8)


1、拦截器

  控制器中可以定义拦截方法(也可称之为拦截器),为控制器及其子类的所有Action提供服务。当所有的Action都需要进行通用的处理时,该功能就显得非常有用:比 如验证用户的合法性,加载请求范围内的信息等。

        读者在使用时需要注意的是,这些拦截器方法不能定义为public,但必须是static,并通过有效的拦截标记进行注解。

1.1 @Before#

      使用@Before注解的方法会在每个Action调用之前执行。如创建具有用户合法性检查的拦截器:

public class Admin extends Application {
 
   
@Before
   
static void checkAuthentification() {
       
if(session.get("user") == null) login();
   
}
 
   
public static void index() {
       
List<User> users = User.findAll();
        render
(users);
   
}
 
   
...
 
}

 如果不希望@Before注解拦截所有的Action方法,那么可以使用unless参数列出需要排除的方法:

public class Admin extends Application {
 
   
@Before(unless="login")
   
static void checkAuthentification() {
       
if(session.get("user") == null) login();
   
}
 
   
public static void index() {
       
List<User> users = User.findAll();
        render
(users);
   
}
 
   
...
 
}

      或者直接使用only参数把需要拦截的方法列举出来:

public class Admin extends Application {
 
   
@Before(only={"login","logout"})
   
static void doSomething() {  
       
...
   
}
   
...
}

      unless和only参数对@After,@Before以及@Finally注解都适用。


1.2 @After#

      使用@After注解的方法会在每个Action调用之后执行:

public class Admin extends Application {
 
   
@After
   
static void log() {
       
Logger.info("Action executed ...");
   
}
 
   
public static void index() {
       
List<User> users = User.findAll();
        render
(users);
   
}
 
   
...
 
}

1.3 @Catch#

      如果有Action方法抛出了异常,那么使用@Catch注解的方法就会执行,且抛出的异常会以参数的形式传递到@Catch注解的方法中。具体实现如下:

public class Admin extends Application {
       
   
@Catch(IllegalStateException.class)
   
public static void logIllegalState(Throwable throwable) {
       
Logger.error("Illegal state %s…", throwable);
   
}
   
   
public static void index() {
       
List<User> users = User.findAll();
       
if (users.size() == 0) {
           
throw new IllegalStateException("Invalid database - 0 users");
       
}
        render
(users);
   
}
}

      使用@Catch注解和普通的Java异常处理程序一样,捕获父类往往可以获得更多的异常类型。如果拥有多个需要捕获的方法,可以通过指定优先级来确定他们的执行顺序。具体实现如下:

public class Admin extends Application {
 
   
@Catch(value = Throwable.class, priority = 1)
   
public static void logThrowable(Throwable throwable) {
       
// Custom error logging…
       
Logger.error("EXCEPTION %s", throwable);
   
}
 
   
@Catch(value = IllegalStateException.class, priority = 2)
   
public static void logIllegalState(Throwable throwable) {
       
Logger.error("Illegal state %s…", throwable);
   
}
 
   
public static void index() {
       
List<User> users = User.findAll();
       
if(users.size() == 0) {
           
throw new IllegalStateException("Invalid database - 0 users");
       
}
        render
(users);
   
}
}


1.4 @Finally#

      @Finally注解的方法总是在每个Action调用之后执行(无论Action是否成功执行):

public class Admin extends Application {
 
   
@Finally
   
static void log() {
       
Logger.info("Response contains : " + response.out);
   
}
 
   
public static void index() {
       
List<User> users = User.findAll();
        render
(users);
   
}
 
   
...
 
}

      如果@Finally注解的方法中包含的参数是可抛出的异常,其方法中的内容还是可以继续执行的,具体如下:

public class Admin extends Application {
 
   
@Finally
   
static void log(Throwable e) {
       
if( e == null ){
           
Logger.info("action call was successful");
       
} else{
           
Logger.info("action call failed", e);
       
}
   
}
 
   
public static void index() {
       
List<User> users = User.findAll();
        render
(users);
   
}


1.5 使用@with注解增加更多拦截器#

      如果某个控制器是其他一些类的父类,那么该控制器中定义的所有拦截器会影响到所有子类。由于Java不允许多重继承,对单纯通过继承来使用拦截器造成了一定的局限性。Play可以通过@With注解,调用其他控制器中已经定义好的拦截方法,从而突破这一局限。比如创建Secure控制器,定义checkAuthenticated()拦截方法验证用户合法性:

public class Secure extends Controller {
   
   
@Before
   
static void checkAuthenticated() {
       
if(!session.containsKey("user")) {
            unAuthorized
();
       
}
   
}
}    

      在其他的控制器中,可以通过@With(Secure.class)注解将其包含进来:

@With(Secure.class)
public class Admin extends Application {
   
   
...
}

1.6 Session和Flash作用域

      在Play开发中,如果需要在HTTP请求之间保存数据,可以将数据保存在Session或者Flash内。保存在Session中的数据在整个用户会话中都是有效的,而保存在Flash的数据只对下一次请求有效。

      特别需要注意的是,Session和Flash作用域中的数据都是采用Cookie机制添加到随后的HTTP响应中的(并没有存储在服务器上的),所以数据大小非常有限(不能超过4K),而且只能存储字符串类型的数据。

      由于Cookie是使用密钥签名过的,所以客户端不能轻易修改Cookie的数据(否则会失效)。不要将Play的Session当作缓存来使用,如果需要在特定的会话中缓存一些数据,那么可以使用Play内置的缓存机制,并将session.getId()作为缓存的key进行储存。

public static void index() {
   
List messages = Cache.get(session.getId() + "-messages", List.class);
   
if(messages == null) {    
       
// 处理缓存失效
        messages
= Message.findByUser(session.get("user"));
       
Cache.set(session.getId() + "-messages", messages, "30mn");
   
}
    render
(messages);
}

      Session在用户关闭浏览器后就会失效,除非修改配置文件中的application.session.maxAge属性。设置方法如下:

application.session.maxAge=7d  # Remember for one week.

      使用Play内置的Cache缓存时需要注意,Cache与传统Servlet的HTTP Session对象是不同的。框架无法保证这些缓存对象会一直存在,所以在业务代码中必须处理缓存失效的问题,以便保持应用完全无状态化。




控制层基本的工作流程为:接收HTTP请求的参数,通过对域模型的操作来实现业务逻辑,最终调用视图进行渲染。有时候控制器所做的仅仅是简单的查询操作,有时候需要改变域模型的状态(更新数据),或者通过Action链将处理转发至其他控制器方法。值得注意的是,Play将Session数据以Cookie的机制存放在客户端,而服务器端则用Cache的方式进行数据缓存。

拦截器
MVC应用程序模型 - 7 - app/controllers - 8 - app/models - 8 - app/views - 8 - 请求生命周期 - 8 - 标准应用程序布局layout - 9 - app目录 - 9 - public目录 - 10 - conf目录 - 10 - lib目录 - 11 - 开发生命周期 - 11 - 连接到java调试器 - 12 - 类增强Enhancement - 13 - 02.HTTP路由 - 13 - 关于REST - 14 - routes文件语法 - 14 - HTTP方法 - 15 - URI范示 Pattern - 15 - Java调用定义 - 17 - 把404当作action来用 - 17 - 指派静态参数 - 17 - 变量和脚本 - 18 - 路由优先级 - 18 - 服务器静态资源 - 18 - staticDir: mapping - 18 - staticFile: mapping - 19 - URL 编码 - 19 - 反转路由:用于生成某些URL - 19 - 设置内容风格(CSS) - 20 - HTTP 内容协商 negotiation - 21 - 从http headers开始设置内容类型 - 21 - 定制格式 - 22 - 03.控制器 - 23 - 控制器概览 - 23 - 获取http参数 - 24 - 使用params map - 25 - 还可以从action方法签名实现转换 - 25 - 高级HTTP Java绑定 - 26 - 简单类型 - 26 - Date类型 - 26 - Calendar日历 - 27 - File - 27 - 支持类型的数组或集合 - 28 - POJO对象绑定 - 29 - JPA 对象绑定 - 30 - 定制绑定 - 30 - @play.data.binding.As - 30 - @play.data.binding.NoBinding - 31 - play.data.binding.TypeBinder - 31 - @play.data.binding.Global - 32 - 结果类型 - 32 - 返回一些文本类型的内容 - 33 - 返回一个JSON字符串 - 33 - 返回一个XML字符串F - 34 - 返回二进制内容 - 34 - 作为附件下载文件 - 34 - 执行一个模板 - 35 - 跳转到其他URL - 36 - Action链 - 36 - 定制web编码 - 37 - 拦截器 - 38 - @Before - 38 - @After - 39 - @Catch - 40 - @Finally - 41 - 控制器继承 - 42 - 使用@With注释添加更多的拦截器 - 42 - Because Java does not allow multiple inheritance, it can be very limiting to rely on the Controller hierarchy to apply interceptors. But you can define some interceptors in a totally different class, and link them with any controller using the @With annotation.由于java不允许多继承,通过控制器继承特点来应用拦截器就受到极大的限制。但是我们可以在一个完全不同的类里定义一些拦截器,然后在任何控制器里使用@With注释来链接他们。 - 42 - Session和Flash作用域 - 42 - 04.模板引擎 - 43 - 模板语法 - 43 - Expressions: ${…} - 44 - Template decorators : #{extends /} and #{doLayout /} - 44 - Tags: #{tagName /} - 45 - Actions: @{…} or @@{…} - 46 - Messages: &{…} - 46 - Comment: *{…}* - 46 - Scripts: %{…}% - 46 - Template inheritance继承 - 47 - 定制模板标签 - 48 - 检索tag参数 - 48 - 调用标签体 - 48 - 格式化特定标签 - 49 - 定制java标签 - 49 - 标签命名空间 - 50 - 在模板里的Java对象扩展 - 51 - 创建定制扩展 - 52 - 模板里可以使用的保留对象 - 52 - 05.用play验证http数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值