play 拦截器

在本教程的第一部分中,我们介绍了创建,发布和调用模块的基本知识。 我们创建的模块并没有真正做很多事情,因此现在是时候使用Play的某些功能来扩展功能了。

1.拦截器

拦截器使您可以拦截对控制器的调用,并增强或阻止其行为。 在第一个示例应用程序中,我们向MyLogger添加了显式调用,以将消息记录到控制台。 如果我们扩大规模,并且您想在每个控制器方法调用中都使用这个非常有用的插件,那么您将编写大量样板代码。 拦截器使我们能够自动应用动作,从而减少样板。

1.1添加代码

在app目录中,创建一个名为action的新程序包。 在这里,我们将添加LogMe注释,以及将在存在注释时执行的LogMeAction。

此时,LogMe.java是一个非常简单的注释,它不需要任何参数

package actions;import play.mvc.With;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author Steve Chaloner (steve@objectify.be)*/
@With(LogMeAction.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Inherited
@Documented
public @interface LogMe
{
}

看一下注释,然后您将看到(LogInAction.class)–这让Play知道遇到此注释时,它应该在实际目标之前执行LogInAction。

package actions;import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;/*** @author Steve Chaloner (steve@objectify.be)*/
public class LogMeAction extends Action{@Overridepublic Result call(Http.Context context) throws Throwable{System.out.println("MyLogger: " + context.request().path());return delegate.call(context);}
}

这是非常优雅的东西–动作具有LogMe的通用参数类型,该参数类型可以访问分配给LogMe批注的任何参数。 这使您可以自定义动作的行为。 当我们添加一些额外的功能时,我们将看到这一点。 一旦完成您的代码(在本例中为System.out的另一个类),然后您将返回proxy.class(context)的结果以恢复正常执行流程。 同时,如果将@LogMe添加到控制器方法,则操作的路径将记录到控制台; 如果将@LogMe添加到控制器,则对该控制器中任何方法的调用都将导致该路径记录到控制台。

1.2更新Build.scala

由于我们拥有新版本的mylogger,因此我们应该更改版本号。 打开项目/Build.scala并进行更改

val appVersion      = "1.0-SNAPSHOT"

val appVersion      = "1.1"

1.3确保已检测到您的项目更改

如果您已经在mylogger / project-code中运行Play控制台,则需要执行“重新加载”以获取对Build.scala的更改。 如果未打开控制台,请立即打开它-更改将在启动时自动进行。

[mylogger] $ reload
[info] Loading project definition from C:\Temp\mylogger\project-code\project
[info] Set current project to mylogger (in build file:/C:/Temp/mylogger/project-code/)

1.4清理并发布

如前所述,在发布之前进行清理始终是一个好主意,以确保您不会推出任何不应存在的对象。

[mylogger] $ clean
[success] Total time: 0 s, completed Mar 19, 2012 9:17:25 PM
[mylogger] $ publish-local
[info] Packaging /tmp/mylogger/project-code/target/scala-2.9.1/mylogger_2.9.1-
1.1 -sources.jar ...
[info] Done packaging.
[info] Wrote /tmp/mylogger/project-code/target/scala-2.9.1/mylogger_2.9.1- 1.1
 .pom
[info] Updating {file:/tmp/mylogger/project-code/}mylogger...
[info] Done updating.
[info] :: delivering :: mylogger#mylogger_2.9.1;1.1 :: 1.1 :: release ::
Mon Mar 19 21:17:30 CET 2012
[info] Generating API documentation for main sources...
[info] Compiling 3 Java sources to /tmp/mylogger/project-code/target/scala-2.9.1
/classes...
[info]  delivering ivy file to /tmp/mylogger/project-code/target/scala-2.9.1
/ivy- 1.1 .xml
model contains 7 documentable templates
[info] API documentation generation successful.
[info] Packaging /tmp/mylogger/project-code/target/scala-2.9.1/mylogger_2.9.1- 1.1
 -javadoc.jar ...
[info] Done packaging.
[info] Packaging /tmp/mylogger/project-code/target/scala-2.9.1/mylogger_2.9.1- 1.1 .jar ...
[info] Done packaging.
[info]  published mylogger_2.9.1 to /home/steve/development/play/play-2.0/framework
/../repository/local/mylogger/mylogger_2.9.1/ 1.1 /poms/mylogger_2.9.1.pom
[info]  published mylogger_2.9.1 to /home/steve/development/play/play-2.0/framework
/../repository/local/mylogger/mylogger_2.9.1/ 1.1 /jars/mylogger_2.9.1.jar
[info]  published mylogger_2.9.1 to /home/steve/development/play/play-2.0/framework
/../repository/local/mylogger/mylogger_2.9.1/ 1.1 /srcs/mylogger_2.9.1-sources.jar
[info]  published mylogger_2.9.1 to /home/steve/development/play/play-2.0/framework
/../repository/local/mylogger/mylogger_2.9.1/ 1.1 /docs/mylogger_2.9.1-javadoc.jar
[info]  published ivy to /home/steve/development/play/play-2.0/framework/../repository
/local/mylogger/mylogger_2.9.1/ 1.1 /ivys/ivy.xml
[success] Total time: 3 s, completed Mar 19, 2012 9:17:31 PM

请注意,模块的版本在日志记录中已更改。 如果仍然看到1.0-SNAPSHOT,请确保在发布之前重新加载了项目!

1.5更新示例应用程序

返回示例应用程序,在project / Build.scala中更改所需的模块版本

val appDependencies = Seq("mylogger" % "mylogger_2.9.1" % "1.1")

重新加载并运行“依赖项”以确保您具有正确的版本。 现在,您可以更新app / controllers / Application.java以使用以下新代码:

package controllers;import actions.LogMe;
import play.mvc.Controller;
import play.mvc.Result;
import views.html.index;@LogMe
public class Application extends Controller
{public static Result index(){return ok(index.render("Your new application is ready."));}
}

运行此示例,您现在将看到通过注释应用的MyLogger输出。

2.添加了拦截器参数

仅记录请求的路径并不是特别有用或令人兴奋。 如果应该为每种控制器或控制器方法提供特定的日志消息怎么办? 在这种情况下,我们需要添加一些参数。

2.1更改注释签名

上传action / LogMe.java以使用value()参数-这是默认的注释参数,因此在使用时无需显式命名。 该值默认为空字符串,因此,如果此处不存在此消息,则可以在操作中提供标准消息。

public @interface LogMe
{String value() default "";
}

在操作中,将继承的配置字段键入通用参数(在本例中为LogMe),并提供对参数的访问。 更新call(Http.Context)方法以利用这一点。

public Result call(Http.Context context) throws Throwable
{String value = configuration.value();if (value == null || value.isEmpty()){value = context.request().path();}System.out.println("MyLogger: " + value);return delegate.call(context);
}

2.2发布更改

再次重复步骤1.2至1.4,这次将appVersion更改为1.2

2.3更新示例应用程序

与以前一样,在Build.scala中更新依赖项版本,重新加载并使用“ dependencies”进行确认。 现在,您可以向LogMe批注添加一条消息:

@LogMe("This is my log message")
public class Application extends Controller

运行该应用程序,现在您将在控制台中看到注释消息。

[info] play - Application started (Dev)
MyLogger: This is my log message

3.使拦截器交互

现在,您(希望)掌握了这一点,我们将加快一些速度。 在本节中,我们将研究拦截器如何相互交互。 Play首先将拦截器应用于方法,然后应用于控制器,因此,如果在方法和控制器级别都存在相同的注释,它将执行两次。 LogMe批注可以同时应用于类级别和方法级别,但是,如果您对整个控制器有一条通用的日志记录消息,而一个方法需要使用另一条消息,那该怎么办呢? 另外,我们只希望每次调用一个日志消息。 为此,我们可以使用传递给每个动作的上下文。

3.1更新模块

更新LogMeAction以使其了解以前的调用:

package actions;import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;/*** @author Steve Chaloner (steve@objectify.be)*/
public class LogMeAction extends Action{public static final String ALREADY_LOGGED = "already-logged";@Overridepublic Result call(Http.Context context) throws Throwable{Result result;if (context.args.containsKey(ALREADY_LOGGED)){// skip the logging, just continue the executionresult = delegate.call(context);}else{// we're not using the value here, only the key, but this// mechanism can also be used to pass objectscontext.args.put(ALREADY_LOGGED, "");String value = configuration.value();if (value == null || value.isEmpty()){value = context.request().path();}System.out.println("MyLogger: " + value);result = delegate.call(context);}return result;}
}

更新版本号,清理,重新加载和本地发布。

3.2更新示例应用程序

这次,我们将在index方法中添加第二个注释。 这将覆盖控制器级别的注释。 因此,在Build.scala中更新依赖项编号,重新加载并运行。

package controllers;import actions.LogMe;
import play.mvc.Controller;
import play.mvc.Result;
import views.html.index;@LogMe("This is my log message")
public class Application extends Controller
{@LogMe("This is my method-specific log message")public static Result index(){return ok(index.render("Your new application is ready."));}
}

当您访问http:// localhost:9000时,现在您将在控制台中看到以下内容:

@LogMe("This is my log message")
[info] play - Application started (Dev)
MyLogger: This is my method-specific log message

4.又是啤酒时间

您现在拥有了支持参数化操作的基础结构。 请记住,很多东西都可以作为注释参数传递,但是-重要的是-并非所有东西都可以传递。 您可能需要为某些任务发挥创造力!

您可以在此处下载完整的源代码。

参考: Play 2的编写模块,第2部分: Objective博客上JCG合作伙伴 Steve Chaloner的拦截器 。

翻译自: https://www.javacodegeeks.com/2012/04/writing-modules-for-play-2-part-2.html

play 拦截器

play 拦截器_编写Play 2的模块,第2部分:拦截器相关推荐

  1. python类修饰器_《Python有什么好学的》之修饰器

    "Python有什么好学的"这句话可不是反问句,而是问句哦. 主要是煎鱼觉得太多的人觉得Python的语法较为简单,写出来的代码只要符合逻辑,不需要太多的学习即可,即可从一门其他语 ...

  2. android 调用系统自带文件管理器_编写使用Android 系统自带的文字转语音代码

    调用Android系统语音TextToSpeech实例对象 具体代码写法如下: TextToSpeech mTextToSpeech = new TextToSpeech(this, new Text ...

  3. python写小说阅读器_手把手教你用Python制作简易小说阅读器

    /前言/ 不知从什么时候开始.小说开始掀起了一股浪潮,它让我们平日里的生活不在枯燥乏味,很多我们做不到的事情在小说里都能轻易实现. 今天我们要做的就是一个小说阅读器了,一个可以将你的文章中的字每隔多少 ...

  4. 查看器_三款完美替代Windows10自带照片查看器的神器!

    Windows10系统中的看图软件Microsoft 照片,被吐槽已经不是一天两天了,2020年马上过完了,我在使用照片功能查看图片时还会出现假死问题. 如果少点bug,说实话Microsoft 照片 ...

  5. python编写自定义模块_编写和导入自定义模块/类

    我有一个类,我正试图编写一个名为dbObject的类,并试图从另一个文件夹中的脚本导入它.我的结构如下:/var/www/html/py/testobj.py /var/www/html/py/obj ...

  6. java 上下文加载器_如何将JDK6 ToolProvider和JavaCompiler与上下文类加载器一起使用?...

    我的用例是使用JDK 6中提供的ToolProvider和 JavaCompiler类从java程序编译生成的源文件.源文件包含对上下文类加载器中的类的引用(它在J2EE容器中运行),但不包含在系统类 ...

  7. linux开源视频播放器_什么定义了Linux的顶级开源音乐播放器?

    linux开源视频播放器 在我撰写此音乐专栏的两年左右的时间里,Linux发烧友的世界得到了发展. 出现了新的Linux发行版和开源音频播放器,旧的已经消失了,随着高质量的数字下载,新的和高质量的播放 ...

  8. java 访问器_网络之美 JavaScript中Get和Set访问器的实现代码

    标准的Get和Set访问器的实现 function Field(val){ this.value = val; } Field.prototype = { get value(){ return th ...

  9. python写小说阅读器_用python给自己DIY一款小说阅读器,如此看来,很简单!

    前一段时间书荒的时候,在喜马拉雅APP发现一个主播播讲的小说-大王饶命.听起来感觉很好笑,挺有意思的,但是只有前200张是免费的,后面就要收费.一章两毛钱,本来是想要买一下,发现说的进度比较慢而且整本 ...

最新文章

  1. 【c语言】蓝桥杯算法训练 简单加法(基本型)
  2. 数据迁移工具Sqoop和DataX功能比较
  3. android最新框架,XUpdate 一个轻量级、高可用性的Android版本更新框架
  4. 仿拉钩app(一)---爬虫数据准备
  5. 无处不在的xss攻击
  6. k-means算法原理及实战
  7. windows控件常用缩写
  8. 控件中按回车键就关闭对话框问题怎么解决?
  9. VMware vSphere ESX 迁移到 ESXI 指南
  10. 这款应用,让Windows软件也能在Mac上使用起来
  11. Real-Time Rendering——16.1 Sources of Three-Dimensional Data三维数据的来源
  12. 基于协同过滤的推荐算法
  13. 利用沙盒技术破解APP的API协议加密
  14. 海康8700服务器系统,海康8700安防综合管理平台安装使用指南.pdf
  15. oracle的month函数的使用方法,oracle next_day,add_month函数
  16. 爆款“小黄鸭”之后,实在RPA助力电商人双11提销量
  17. 一.stm32的内部flash操作笔记
  18. Duilib异形窗口
  19. 电影网站 php asp,asp电影网址导航大全 V20201218
  20. 由开启coredump引起的对shell的深入探究

热门文章

  1. Java Enumeration接口与Iterator接口
  2. c语言程序设计--图书管理系统
  3. 为了金秋那沉甸甸的麦穗,我绝不辜负春天
  4. JavaScript操作BOM简单案例
  5. 从oracle里面取直,45个非常有用的 Oracle 查询语句小结
  6. php file_put_contents(quot;,php file_put_contents函数怎么用?
  7. java凯撒密码_JAVA凯撒密码 选择问题
  8. 转:Java并发编程与高并发解决方案(一)
  9. jmc线程转储_查找线程转储中的异常和错误
  10. 网络研讨室_即将举行的网络研讨会:调试生产中Java的5种最佳实践