编写Play 2的模块,第2部分:拦截器

在本教程的第一部分中,我们介绍了创建,发布和调用模块的基本知识。 我们创建的模块并没有真正做很多事情,因此现在是时候使用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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372908.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c# ef报错_C# EF调用MySql出现“未将对象引用设置到对象的实例”错误解决方案

C# EF调用MySql出现“未将对象引用设置到对象的实例”错误解决方案---修改步骤---1.打开Nuget管理包,把Mysql.Data替换为6.10.0以下任意版本。这里选择的是6.8.82.修改完毕后,继续把Mysql.Data.Entity也修改为对应版本6.8.8。3.安装完成后可以看到App.Co…

js格式化时间

Date.prototype.format function(fmt) {var o { "M" : this.getMonth()1, //月份 "d" : this.getDate(), //日 "h" : this.getHours(), //小时 "m" : this.getMinu…

PHP---函数

一.函数定义的四个要素 返回类型,函数名,参数列表,函数体 //1.最简单的定义方式/*function show(){ echo "hello";}show();*///2.有参数的函数定义/*function show($a){ echo $a;}show("bbbbb");*///3.有默认值的函数定义…

ServletRequest startAsync()的有用性有限

前段时间我遇到了Servlet 3.0中AsyncContext.start(…)的目的是什么? 题。 引用上述方法的Javadoc : 使容器调度线程(可能从托管线程池中)运行指定的Runnable 。 提醒大家, AsyncContext是Servl…

mysql所支持的比较运算符_mysql比较运算符有哪些?Mysql比较运算符详解

比较运算符可用于比较数字和字符串。今天发一篇Mysql比较运算符详解,希望对初学者有所帮助,虽然现在流行NoSQL,但是MYSQL还是很有用的,数字作为浮点值进行比较,字符串以不区为例进行比较,运算符用于比较表达…

数据结构0类模板的使用

类模板的使用 #include <iostream> #include <conio.h> #include <string> #define N 3 using namespace std;template <class numtype> class Swap{public :Swap(numtype a,numtype b){xa;yb;}numtype ___(){tempx;xy;ytemp;return x;}//testnumtype …

JavaScript 函数

函数 由于JavaScript的函数也是一个对象&#xff0c;所以类似function abs(v){}函数实际上是一个函数对象&#xff0c;而函数名abs可以视为指向该函数的变量。 因此&#xff0c;第二种定义函数的方式如下&#xff1a; var abs function (x) {if (x > 0) {return x;} else {…

Http Invoker的Spring Remoting支持

Spring HTTP Invoker是Java到Java远程处理的重要解决方案。 该技术使用标准的Java序列化机制通过HTTP公开服务&#xff0c;并且可以被视为替代解决方案&#xff0c;而不是Hessian和Burlap中的自定义序列化。 而且&#xff0c;它仅由Spring提供&#xff0c;因此客户端和服务器应…

mysql 日期列表_MySQL 生成日期表

1、创建一个num表&#xff0c;用来存储数字0~9CREATE TABLE num (i int);2、在num表中生成0~9INSERT INTO num (i) VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);3、生成一个存储日期的表&#xff0c;datalist是字段名CREATE TABLE if not exists calendar(dateli…

学习后缀自动机想法

小序&#xff1a;学习后缀自动机是要有耐心的&#xff0c;clj的论文自己看真心酸爽&#xff01;&#xff08;还是自己太弱&#xff0c;ls&#xff0c;oyzx好劲啊&#xff0c;狂膜不止&#xff09; 刚刚在写博客之前又看了篇论文&#xff0c;终于看懂了&#xff0c;好开心 正文&…

【BZOJ】3575: [Hnoi2014]道路堵塞

题目链接&#xff1a;http://www.lydsy.com/JudgeOnline/problem.php?id3575 大概的做法是&#xff0c;按照顺序枚举每一条要删去的边&#xff0c;(假设当前点为$u$&#xff0c;在最短路径上的下一个点是$v$)然后强制不走${u->v}$这条边&#xff0c;将$u$入队&#xff0c;做…

结合使用slf4j和Logback教程

在当前文章中&#xff0c;我将向您展示如何配置您的应用程序以使用slf4j和logback作为记录器解决方案。 Java简单日志记录外观&#xff08;slf4j&#xff09;是各种日志记录框架的简单外观&#xff0c;例如JDK日志记录&#xff08;java.util.logging&#xff09;&#xff0c;lo…

mysql 分组top_MySQL:如何查询出每个分组中的 top n 条记录?

问题描述需求&#xff1a;查询出每月 order_amount(订单金额) 排行前3的记录。例如对于2019-02&#xff0c;查询结果中就应该是这3条&#xff1a;解决方法MySQL 5.7 和 MySQL 8.0 有不同的处理方法。1. MySQL 5.7我们先写一个查询语句。根据 order_date 中的年、月&#xff0c;…

ACM第四站————最小生成树(普里姆算法)

对于一个带权的无向连通图&#xff0c;其每个生成树所有边上的权值之和可能不同&#xff0c;我们把所有边上权值之和最小的生成树称为图的最小生成树。 普里姆算法是以其中某一顶点为起点&#xff0c;逐步寻找各个顶点上最小权值的边来构建最小生成树。 其中运用到了回溯&#…

利用jenkins的api来完成相关工作流程的自动化

[本文出自天外归云的博客园] 背景 1. 实际工作中涉及到安卓客户端方面的测试&#xff0c;外推或运营部门经常会有很多的渠道&#xff0c;而每个渠道都对应着一个app的下载包&#xff0c;这些渠道都记录在安卓项目下的一个渠道列表文件中。外推或运营部门经常会有新的渠道产生&a…

拥有成本分析:Oracle WebLogic Server与JBoss

Crimson Consulting Group 撰写的非常有趣的白皮书 &#xff0c;比较了Weblogic和JBoss之间的拥有成本 。 尽管JBoss是免费的&#xff0c;但该白皮书却严肃地宣称&#xff0c;从长远来看&#xff0c;Weblogic更便宜。 尽管此研究是由Oracle赞助的&#xff0c;但它看起来非常严肃…

mysql limit 分页 0_Mysql分页之limit用法与limit优化

Mysql limit分页语句用法与Oracle和MS SqlServer相比&#xff0c;mysql的分页方法简单的让人想哭。--语法&#xff1a;SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset--举例&#xff1a;select * from table limit 5; --返回前5行select * from table limit 0…

与硒的集成测试

总览 我已经使用了一段时间&#xff0c;遇到了一些似乎可以使生活更轻松的事情。 我以为可以将其作为教程分享&#xff0c;所以我将向您介绍这些部分&#xff1a; 使用Maven设置Web项目&#xff0c;配置Selenium以在CI上作为集成测试运行 寻找使用“页面对象”为网站中的页面…

linux每天一小步---sed命令详解

1 命令功能 sed是一个相当强大的文件处理编辑工具&#xff0c;sed用来替换&#xff0c;删除&#xff0c;更新文件中的内容。sed以文本行为单位进行处理&#xff0c;一次处理一行内容。首先sed吧当前处理的行存储在临时的缓冲区中&#xff08;称为模式空间pattern space&#xf…

mysql trace工具_100% 展示 MySQL 语句执行的神器-Optimizer Trace

在上一篇文章《用Explain 命令分析 MySQL 的 SQL 执行》中&#xff0c;我们讲解了 Explain 命令的详细使用。但是它只能展示 SQL 语句的执行计划&#xff0c;无法展示为什么一些其他的执行计划未被选择&#xff0c;比如说明明有索引&#xff0c;但是为什么查询时未使用索引等。…