当前位置: 首页 > news >正文

ActFramework r1.2.0 带来的新特性

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

#136 @With 注解现在可以应用于方法上了

在 r1.2.0 之前 @With 注解用来将拦截器应用于某个控制器上,例如:

public class MyInterceptor extends Controller.Util {
    @Before
    public void logRequest(H.Request req) {
        Act.LOGGER.trace("<<< req to %s", req.fullUrl());
    }
    
    @After
    public void logRequestDone(H.Request req) {
        Act.LOGGER.trace(">>> req to %s", req.fullUrl());
    }
}
@With(MyInterceptor.class)
public class MyController {
    ...
}

上述代码表示拦截器 MyInterceptor 里面所有的拦截方法都将被应用于控制器 MyController 里面所有的响应方法上。现在 r1.2.0 允许应用将 @With 注解应用于具体的响应方法上,例如:

public class MyControllerV2 {
   @With(MyInterceptor.class)
   @GetAction("/foo")
   public void handlerNeedsAuditing() {
      ...
   }
   
   @GetAction("/bar")
   public void handlerWithoutAuditing() {
      ...
   }
}

改动之后的 MyControllerV2 上拦截器只作用于发送到 /foo 的请求,而发送到 /bar/ 的请求则不会应用拦截器

#152 允许将拦截器标注为全局有效

以前如果你想应用一个拦截器到控制器上,必须在控制器上使用 @With 注解来引入拦截器。现在 r1.2.0 允许我们声明某个拦截器类或者方法为全局有效:

@Global 
public class MyInterceptor extends Controller.Util {
    @Before
    public void logRequest(H.Request req) {
        Act.LOGGER.trace("<<< req to %s", req.fullUrl());
    }
    
    @After
    public void logRequestDone(H.Request req) {
        Act.LOGGER.trace(">>> req to %s", req.fullUrl());
    }
}

上面的代码告诉 ActFramework MyInterceptor 所有的拦截器方法均全局有效

你也可以将 @Global 放在某个特定的拦截器方法上面表示该拦截器方法需要全局有效:

public class MyInterceptor extends Controller.Util {
    @Global
    @Before
    public void logRequest(H.Request req) {
        Act.LOGGER.trace("<<< req to %s", req.fullUrl());
    }
    
    @After
    public void logRequestDone(H.Request req) {
        Act.LOGGER.trace(">>> req to %s", req.fullUrl());
    }
}

上面的代码表示只有 @Before 拦截器方法才是全局有效的。

#153 在 @DbBind 的时候使用 @NotNull 注解

在 ActFramework 应用里面我们可以使用 @DbBind 来绑定某个请求/URL/表单变量到响应方法(或者拦截器方法)参数上,例如:

@GetAction("/order/{id}/price")
public double update(@DbBind("id") Order order) {
    notFoundIfNull(order);
    return order.getPrice();
}

上述代码中 notFoundIfNull(order); 是告诉 ActFramework 在传入的 id 找不到对应的 Order 的时候返回 404 Not Found 响应。如果没有这一句,那当找不到绑定数据的时候你会在 return order.getPrice(); 这一行得到一个 NullPointerException,而触发一个 500 内部错误 响应。

现在 r1.2.0 我们引入了一种更加简洁的方式来描述上述逻辑:

@GetAction("/order/{id}/price")
public double update(@DbBind("id") @NotNull Order order) {
    return order.getPrice();
}

上面的 NotNull 是 Java 标准的数据有效性检验框架提供的注解.

ActFramework 还改进了(开发模式下的)错误页面,这样可以让开发人员非常清晰地看到是什么原因造成的 404 返回:

源码

code

当 ID 不正确时的错误页面

error page

#157 路由支持 SEO

现在我们可能在一些网站上发现针对搜索引擎优惠的 URL, 比如下面两个 URL 打开的页面是一样的:

  • http://stackoverflow.com/questions/43406011/actframework-run-error-org-osgl-exception-unexpectedexception-app-not-found
  • http://stackoverflow.com/questions/43406011

但是前者的 URL 带的 actframework-run-error-org-osgl-exception-unexpectedexception-app-not-found 让 URL 能够被搜索引擎理解并做相应的处理。

ActFramework r1.2.0 提供了一种机制允许应用创建类似的 URL:

@GetAction("/article/{id}/...")
public Article getArticle(@DbBind("id") Article article) {
    return article;
}

上面代码中的 URL 路径 /article/{id}/...... 结束, 表示在 /article/{id}/ 之后的任何字符都将被忽略。这样可以让开发人员构造针对 SEO 优化的 URL

#160 在 Controller.Base 中植入 ActionContext 字段

Controller.Util 类提供了丰富的工具方法来帮助应用程序,因此应用程序的控制器类通常会从 Controller.Util 类继承下来。另一方面应用程序经常会在响应方法中使用到 ActionContext 对象,而获得该对象的办法通常有两种,一种声明一个依赖注入字段,二是在响应方法的参数列表里面声明该对象。

现在 r1.2.0 我们引入了一个新的控制器基类:Controller.Base。该基类和 Controller.Util 的区别是前者声明了一个依赖注入字段 protected ActionContext context; 这样应用从该基类派生出的控制器类自动拥有了 context 字段而无需声明:

public class MyController extends Controller.Base {
    @GetAction("/foo")
    public String foo() {
        return context.i18n("foo");
    }
}

注意Controller.Base 派生出的控制器类可以直接使用 Controller.Util 所有的方法,因为 Controller.Base 继承 了 Controller.Util

看到这里大家可能会问,为什么不直接在 Controller.Util 类里面声明 protected ActionContext context 字段呢? 原因在于 ActionContext context 字段是有状态的,即每次请求带来的 context 都是不同的. 因此 ActFramework 在响应新请求的时候必须创建控制器的新实例. 而并非所有的控制器都需要一个 ActionContext 类型的字段。在这种情况下保持 Controller.Util 的无状态性可以让无状态的控制器从其派生而不至于损失单例的资格。

#161 提供一种机制标注注入字段为无状态的

ActFramework 的灵动之处体现在很多地方,其中一处是自动检测到没有声明字段的控制器类的时候使用同样的实例来响应不同的请求,这很酷. 不过我们需要做到更进一步,在某些时候我们注入的对象本身是无状态的,比如

public class OrderService {
    @Inject
    private Order.Dao dao;
    
    ...
}

上面的OrderService 控制器注入了一个字段 Order.Dao dao, 但是因为 Order.Dao 是无状态的(假设如此), 或者说我们注入的每个 Order.Dao 都是同行一个实例,在这种情况下,我们没有理由为 OrderService 控制器对每个请求创建一个新实例,完全可以将其当作单例处理. r1.2.0版我们提供了两种方式实现上述需求

方法一, 在注入的字段上添加 @Global 注解:

public class OrderService {
    @Inject
    @Global
    private Order.Dao dao;
    
    ...
}

上面的 @Global 注解告诉 ActFramework dao 实例是跨所有的 OrderService实例存在的, 因此 ActFramework 不需要因为这个字段而将OrderService` 控制器考虑为有状态控制器。

方法二 如果你能控制注入类,比如这个例子中的 Order.Dao 类, 你可以在类上加上 @Stateless 注解:

@Entity("order")
public class Order {
   ...
   @Stateless
   public static class Dao extends EbeanDao<Order> {
      ...
   }
}

现在你在注入 OrderDao dao 字段的时候不需要加上 @Global 注解,ActFramework 自动根据 Order.Dao 类上的 @Stateless 注解推断出了这个字段的无状态性:

public class OrderService {
    @Inject
    private Order.Dao dao;
    
    ...
}

因为Order.Dao类被标注为@Stateless,即使上面的代码没有使用@Global,ActFramework 也将会把 OrderService 当作无状态的单例控制器处理

相关链接

  • ActFramework 的详细介绍:点击查看
  • ActFramework 的官方网站:点击查看

转载于:https://my.oschina.net/greenlaw110/blog/886424

相关文章:

  • p2p网贷3种运营模式
  • [转][译] Closures in Lua - Lua中的闭包
  • MyBatis介绍和架构
  • JS 创建对象的5种写法
  • python之转义字符(学习笔记三)
  • 1015. 德才论 (25)
  • atitit. groupby linq的实现(1)-----linq框架选型 java .net php
  • Linux下安装MySQLdb模块(Python)
  • LWIP移植
  • G-Code 详解
  • umask值与Linux中文件和目录权限的关系
  • 2017-4-28 ListView控件
  • Vue2 第一天学习
  • 《Haskell趣学指南》—— 第2章,第2.2节Haskell的常见类型
  • awk 系列:如何使用 awk 的 ‘next’ 命令
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • Apache Pulsar 2.1 重磅发布
  • css布局,左右固定中间自适应实现
  • JAVA之继承和多态
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • Otto开发初探——微服务依赖管理新利器
  • PAT A1092
  • PHP变量
  • rc-form之最单纯情况
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • yii2权限控制rbac之rule详细讲解
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 二维平面内的碰撞检测【一】
  • 诡异!React stopPropagation失灵
  • 聚类分析——Kmeans
  • 事件委托的小应用
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 7行Python代码的人脸识别
  • Java总结 - String - 这篇请使劲喷我
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • ​configparser --- 配置文件解析器​
  • ​比特币大跌的 2 个原因
  • ​如何防止网络攻击?
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • #if和#ifdef区别
  • #考研#计算机文化知识1(局域网及网络互联)
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • $forceUpdate()函数
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (4)事件处理——(7)简单事件(Simple events)
  • (办公)springboot配置aop处理请求.
  • (二)换源+apt-get基础配置+搜狗拼音
  • (黑马C++)L06 重载与继承
  • (四)linux文件内容查看
  • (一)Thymeleaf用法——Thymeleaf简介
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)