ActFramework r1.3.0 - 激动人心的特性一览

#128 缓存页面

这个特性允许开发人员通过注解来打开页面缓存:

    @GetAction
    @CacheFor
    public void home() {
    }

上面的代码将主页缓存1个小时。开发人员也可以制定缓存失效期限,比如下面的代码让缓存在半小时之后失效:

    @GetAction
    @CacheFor(60 * 30)
    public void home() {
    }

注意缓存页面仅仅对 GET 请求有效. 但是某些特殊场合,比如 facebook 向应用主页(iframe 内)重定向是采用 POST 请求。这时候我们希望页面缓存对 POST 也有效,可以这样写:

    @GetAction
    @CacheFor(supportPost = true)
    public void home() {
    }

#154 支持配置多种策略处理无验证身份请求(Missing Authentication Request)

ActFramework 允许开发人员配置相应的策略来处理无验证身份请求。目前框架提供了两种策略:

  1. 将请求重定向到配置好的 URL (默认为 /login),一般用于普通的 web 应用
  2. 返回 401 Unauthorised 响应,通常用于前后端分离的单页应用,包括移动应用等

问题在于这是一个单一的全局性的配置不能处理应用在不同场合需要不同策略的情况。比如,一个应用的主体是提供 RESTful 服务来支持前端的单页应用或者移动应用,因此我们将策略配置为返回 401 响应。但后来我们需要给应添加一个采用常规编写的管理后台,对所有发送给管理后台的请求如果没有身份验证,我们希望重定向到 /admin/login 而不是统一地返回 401 响应

这个增强提供了处理这种情况的办法:使用 @HandleMissingAuthentication 注解来覆盖(Overwrite)全局配置:

@HandleMissingAuthentication(value = HandleMissingAuthentication.Option.REDIRECT, custom = "/admin/login")
@TemplateContext("/admin")
@UrlContext("/admin")
public class AdminConsole extends Controller.Base {
    ...
}

#163 引入 @TemplateContext 注解

r1.3.0 之前, 除非开发人员在 API 里明确指定模板路径,ActFramework 通过匹配包,类和方法名字 来定位模板,例如:

package com.mycom.myprj;

public class MyController {
    
    @GetAction("/")
    public void home() {
    }

}

这里和 home() 对应的模板应该放在:

resources/rythm/com/mycom/myprj/MyController/home.html

这个规则很简单,非常容易理解和记忆,但在我们拥有一个优秀的 IDE 插件支持之前创建和寻找模板文件都是一件痛苦单调的事情。

现在因为有了 @TemplateContext 我们可以大大地缓解这种状况:

package com.mycom.myprj;

@TemplateContext("/my")
public class MyController {
    
    @GetAction("/")
    public void home() {
    }

}

根据以上代码 ActFramework 在下面的路径寻找 home() 对应的模板:

resources/rythm/my/home.html

变得清爽多了,不是吗?

#164 分解 @Controller 注解到 @UrlContext@Port

我们刚刚引入了 @TemplateContext, 现在我们希望搞一个对应的: @UrlContext, 用来制定一个控制器类下所有的响应方法的 URL context。

实际上我们已经有了这个概念,不过是通过 act.controller.Controller 注解提供的, 如下例所示:

@Controller("admin")
public class Admin {

    @GetAction
    public String home() {
    }

}

现在我们通过引入 @UrlContext 注解让这个概念更加清晰:

@UrlContext("admin")
public class Admin {

    @GetAction
    public String home() {
    }

}

这段代码对我来讲更加清晰,因为 admin 作为 URL context 的含义被明显指定了.

@Controller 注解中还有另一个概念:命名端口,如下例所示:

@Controller(port = "admin")
public class Admin {

    @GetAction
    public String home() {
    }

}

如果应用的配置文件中有下列配置:

namedPorts=admin:5462

上面的代码表示 Admin 类里面的响应器只会处理发送到 5462 端口的请求。

我们不希望把命名端口指定放进 @UrlContext 注解. 因此引入了另一个注解来处理命名端口: Port:

@Port("admin")
public class Admin {

    @GetAction
    public String home() {
    }

}

这段使用 @Port 的代码比上面使用 @Controller(port = "admin") 的代码更简单清楚.

#168 让所有的扫描器处理 @Env 相关注解

ActFramework 有三个和 Env(环境)相关的注解,用于在特定运行环境开关一些逻辑/特性例如:

@Env.Mode(PROD)
public class ModuleForProd extends Module {
    @Override
    protected void configure() {
        bind(HiService.class).to(HiServiceImpl.class);
        bind(ByeService.class).to(ByeServiceImpl.class);
    }
}

上面的代码表示只有当应用运行在 prod 模式下依赖注入模块 ModuleForProd 才会被调用配置.

这个 #168 issue 让 Env 注解的含义扩充到所有的类扫描器,比如:

@Env.Group("test")
public class TestController {
   ...
}
@Env.Group(value = "test", unless = true)
public class NoTestController {
   ...
}

上面的代码表示当前环境是 test 组的时候 TestController 才生效,而 NoTestController 则正好相反,只有当前环境不是 test 组才生效

#169 路径中新的正则表达式变量

ActFramework 支持在路由中指定正则表达式变量,例如:

    @GetAction("/int/{<[0-9]+>n}")
    public int n(int n) {
        return n;
    }

r1.3.0 版引入了另外两种表达法:

    @GetAction("/int/{n<[0-9]+>}")
    public int n(int n) {
        return n;
    }

    @GetAction("/int/n:[0-9]+")
    public int n(int n) {
        return n;
    }

#170 更容易地定制全局模板变量

r1.3.0 之前创建全局模板变量的过程是很繁复的。首先需要建立一个新项目, 然后创建一个 ImplicitVariableProvider 插件的实现类, 编译并发布这个插件项目作为单独的 jar 库,然后才能在应用项目中使用其中定义的全局变量。

r1.3.0 版提供了一种新的机制让应用可以非常轻松自由地定于全局模板变量:

    @ProvidesImplicitTemplateVariable("foo")
    public String foo() {
        return "bar";
    }

    @ProvidesImplicitTemplateVariable("bar")
    public static int bar() {
        return 3;
    }

    @ProvidesImplicitTemplateVariable("reqUrl")
    public static String url(H.Request request) {
        return request.url();
    }

上面的代码定义了三个全局模板变量: foo, barreqUrl. 注意 reqUrl 变量的方法上有个 H.Request 类型的参数, 这个没有问题,只要参数是可以被注入的,ActFramework 都能够处理。

#171 提供一个 jQuery 增强 javascript 库

这个增强库可以通过 /asset/act/js/jquery.ext.js 引入,提供如下功能:

$.put(url, [data], function)
$.patch(url, [data], function)
$.delete(url, [data], function)
$.postJSON(url, [data], function)
$.putJSON(url, [data], function)
$.patchJSON(url, [data], function)
$.deleteJSON(url, [data], function)

另外这个库能够处理针对 ajax 请求的 278 重定向响应. 参见 这个 SO

#174 支持 profile 特定的路由配置

除了通过注解,ActFramework 从 resources/routes.conf 文件中读取路由配置. 新版本我们提供了 profile 特定路由配置的功能,框架会从下面的文件中读取配置:

resources/routes.conf
resources/conf/routes.conf
resources/conf/common/routes.conf
resources/conf/{profile}/routes.conf

其中 {profile} 是当前运行的 profile 名字

#175 当增强类出错的时候提供更友好的错误报告

以前当发生类增强错误的时候看不到任何错误报告:

r1.3.0 改进了这个地方,可以看到很清晰的错误报告:

#177 当控制器响应方法或拦截器方法重名时提供友好的错误报告

ActFramework 不允许响应器/拦截器方法重名。过去关于这点没有清晰的错误报告,而开发人员会因为违反了这个规定而出现不知所措的局面. 现在的关于这种错误的报告可以非常明确的告诉程序员问题所在:

#179 提供注解来标识需要输出到模板变量的字段或者方法参数

r1.3.0 版中引入了一个新的注解 @Output 来标明某个字段或者方法参数需要输入到模板变量列表。代码演示:

常规方法:

@UrlContext("/my")
public class MyController {
  
  @LoginUser
  private User me;
  
  @GetAction("order/{id}")
  public void order(@DbBind @NotNull Order order) {
    render(me, order); // put me and order into the render arguments
  }

}

使用 @Output 注解的新方法:

@UrlContext("/my")
public class MyController {
  
  @LoginUser
  @Output
  private User me;
  
  @GetAction("order/{id}")
  public void order(@DbBind @NotNull @Output Order order) {}

}

#181 让 redirect API 接受控制器的 URL context

r1.3.0redirect API 做了一点改变,让开发人员更容易指定重定向 URL

原来的方式:

@Controller("/admin")
public class AdminController {

    @GetAction("login")
    public void loginForm(){}    

    @GetAction("logout")
    public void logout(H.Session session) {
        session.clear();
        redirect("/admin/login"); // 这里必须放 URL 全路径
    }

    ...
}

新方式:

@UrlContext("/admin")
public class AdminController {

    @GetAction("login")
    public void loginForm(){}    

    @GetAction("logout")
    public void logout(H.Session session) {
        session.clear();
        redirect("login"); // 只需放针对 URL context `/admin` 相对的路径
    }

    ...
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器之心

代码优化指南:人生苦短,我用Python

选自pythonfiles 机器之心编译 参与:Panda 前段时间,Python Files 博客发布了几篇主题为「Hunting Performance i...

31213
来自专栏EAWorld

揭秘:RESTEasy如何完美支持JAVA 微服务中的多种数据格式

本文获得stackify.com授权翻译发表,转载需要注明来自公众号EAWorld。

1044
来自专栏Java架构师学习

Spring5都有那些新特性与增强,需要了解的Java程序员来看一看

Spring FrameWork 5.0新的功能 JDK 8+和Java EE7+以上版本 整个框架的代码基于java8 通过使用泛型等特性提高可读性 对j...

3587
来自专栏java学习

学习java需要会哪些知识才能够去应聘工作?

按照我去培训机构的学习经历,给初学还有自学Java 的同学一个基本的学习脉络,希望对大家有帮助。 不建议找到一本书死啃,没啥用,不要有这一页看不明白我就不往下看...

26610
来自专栏pangguoming

Maven WEB 项目使用ProGuard进行混淆,最佳解决方案

近期公司的Android项目做了混淆,虽说对于保护代码并不是100%的,但混淆后的代码可以使那些不法份子难以阅读,这样也能对代码的保护做出贡献。  于是,公司写...

1251
来自专栏aoho求索

Spring Cloud OpenFeign集成Protocol Buffer

在之前的文章中,我们介绍过基于Spring Cloud微服务架构,其中,微服务实例之间的交互方式一般为RESTful HTTP请求或RPC调用。Spring C...

782
来自专栏逸鹏说道

前后端分离了,然后呢?

  前言   前后端分离已经是业界所共识的一种开发/部署模式了。所谓的前后端分离,并不是传统行业中的按部门划分,一部分人纯做前端(HTML/CSS/JavaSc...

2837
来自专栏编程一生

乐视开放平台技术架构-servlet和spring mvc篇

1052
来自专栏阿杜的世界

Spring AOP的最佳实践一、异常处理二、安全检查三、缓存

抛开业界对checked exception和unchecked exception的论战不谈,重点看着两类异常的应用场景:

713
来自专栏互联网杂技

再谈前后端分离

前言 前后端分离已经是业界所共识的一种开发/部署模式了。所谓的前后端分离,并不是传统行业中的按部门划分,一部分人纯做前端(HTML/CSS/JavaScript...

3588

扫码关注云+社区