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

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 拦截器

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

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

相关文章

java string blob_java String类型转换为Blob类型

展开全部这个是mysql下存取blob字段的一个很简单的类,跟据自己的需要32313133353236313431303231363533e4b893e5b19e31333332623936改改就行了/*** Title: BlobPros.java* Project: test* Description: 把图片存入mysql中的blob字段,并取出* Call Module…

架构之Nginx(负载均衡/反向代理)

Nginx (“engine x”) 是一个高性能的 HTTP 和 反向代理 服务器 ,也是一个 IMAP/POP3/SMTP 代理 服务器 。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式…

Neo4j:特定关系与一般关系+属性

为了在Neo4j查询中获得最佳的遍历速度,我们应该使关系类型尽可能具体 。 让我们看一下几周前我在Skillsmatter上发表的“ 建模建议引擎建模 ”演讲中的一个例子。 我需要决定如何为成员和事件之间的“ RSVP”关系建模。 一个人可以对事件表示“是”或“否”&#…

java 获取 网卡名称_Java获取网卡信息详解

InterfaceAddress 类表示一个由名称和分配给此接口的 IP 地址列表组成的网络接口。它用于标识加入多播组的本地接口。 接口通常是按名称(如 "le0")区分的。NetworkParameterDemo.javaimport java.net.InterfaceAddress;import java.net.NetworkInterface;import java…

java 按位置格式化字符串_Java字符串格式化,{}占位符根据名字替换实例

我就废话不多说了,大家还是直接看代码吧~import java.beans.PropertyDescriptor;import java.lang.reflect.Method;import java.util.HashMap;import java.util.Map;import java.util.regex.Matcher;import java.util.regex.Pattern;public class StringFormatUtil …

Dropzone.js实现文件拖拽上传

dropzone.js是一个开源的JavaScript库,提供 AJAX 异步文件上传功能,支持拖拽文件、支持最大文件大小、支持设置文件类型、支持预览上传结果,不依赖jQuery库。 查看演示 下载源码使用Dropzone 我们可以建立一个正式的上传form表单,…

java 获取系统时间 8小时 jre_Java获取时间与系统时间相差8小时终极解决方案

0、引言Druid中时区的问题一直困扰着我们,所以我专门去研究了一下世界时区和Java中的时区,对使用Druid很用帮助.1、UTC时间&GMT时间UTC时间是时间标准时间(Universal Time Coordinated),UTC是根据原子钟来计算时间,误差非常小…

Apache Drill 1.4性能增强的简要概述

今天,我们很高兴宣布Apache Drill 1.4现已在MapR发行版中可用。 钻1.4是MAPR生产就绪和支持的版本,可以从下载这里 ,找到1.4版本说明这里 。 Drill 1.4以其高度灵活和可扩展的体系结构为基础,带来了多种新功能以及对查询性能的增…

【01背包】洛谷P1282多米诺骨牌

题目描述 多米诺骨牌有上下2个方块组成,每个方块中有1~6个点。现有排成行的 上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|。例如在图8-1中,S161119,S2153211,|S1-S2|2。每个多米诺骨牌…

java geolitecity_GeoLite2 Java根据IP获得城市、经纬度

之前我们介绍过通过 qqwry.dat 根据IP获得所属城市和运营商信息。但是这个 qqwry.dat 已经太久没更新了,数据有些不准确,而且现在我们有个需求就是想获取某个IP所在的经纬度。这里我们可以使用 GeoLite2,这个是国外开源的一个库,需…

Leetcode:search_insert_position

一、 题目 给定一个数组和要插入数的大小。求插入的位置。 二、 分析 太水&#xff0c;直接扫描。过……. class Solution { public:int searchInsert(int A[], int n, int target) {for(int i0;i<n;i) {if(target<A[i]) {return i;} }return n;} };转载于:https…

java mvc 面试题_2018年java技术面试题整理

1、servlet执行流程客户端发出http请求&#xff0c;web服务器将请求转发到servlet容器&#xff0c;servlet容器解析url并根据web.xml找到相对应的servlet&#xff0c;并将request、response对象传递给找到的servlet&#xff0c;servlet根据request就可以知道是谁发出的请求&…

交叉编译指定运行时库路径_运行时vs编译时类路径

交叉编译指定运行时库路径这确实应该是一个简单的区别&#xff0c;但是我一直在回答有关Stackoverflow的许多类似问题&#xff0c;并且经常有人误解此事。 那么&#xff0c;什么是类路径&#xff1f; 应用程序所需的一组所有类&#xff08;以及带有类的jar&#xff09;的集合。…

计算机专业英语第二版张强华翻译_计算机语言发展的三个阶段,机器语言、汇编语言与高级语言...

在如今信息发达的时代&#xff0c;科技日新月异&#xff0c;计算机和Internet网络的发展也成为人们日常生活的重要部分。学习一两门计算机编程语言也如当初学习英文一样的火热&#xff0c;随着人工智能AI和云计算的不断发展&#xff0c;Python语言和Scala语言已经成为这两个领域…

java netty html_源码时代JAVA干货分享|带你用Netty框架实现WebSocket通信

功能介绍Netty开发服务器HTML实现客户端实现服务端与客户端时实时交互开发步骤1.导包io.nettynetty‐all5.0.0.Alpha22.工程配置文件&#xff1a;NettyConfig/*** 这里放的是工程中相应的配置*/public class NettyConfig{/*** 用于存储每一个客户端接入进来时的channel对象*/pu…

使用Apache Drill REST API通过Node构建ASCII仪表板

Apache Drill有一个隐藏的瑰宝&#xff1a;易于使用的REST接口。 该API可用于查询&#xff0c;分析和配置Drill引擎。 在此博客文章中&#xff0c;我将说明如何使用Brilled Contrib使用Drill REST API创建ascii仪表板。 ASCII仪表盘如下所示&#xff1a; 先决条件 Node.js …

mysql+cast+0x_mysql cast与convert 函数的用法

MySQL 的CAST()和CONVERT()函数可用来获取一个类型的值&#xff0c;并产生另一个类型的值。两者具体的语法如下&#xff1a;CAST(value as type);CONVERT(value, type);就是CAST(xxx AS 类型), CONVERT(xxx,类型)。可以转换的类型是有限制的。这个类型可以是以下值其中的一个&a…

影子场vs.属性访问器接口第2轮

如果你们还没有注意到Dirk Lemmerman和我之间的&#xff08;轻松&#xff09; 对决 &#xff0c;那么让我快速提及一下我们是如何做到这一点的。 首先&#xff0c;Dirk创建了JavaFX技巧23&#xff1a;“ 为属性保存内存阴影字段 ”&#xff0c;以帮助应用程序开发人员在使用Jav…

java wmi远程桌面服务器_WMI实现远程监控多台windows服务器

简介WMI简介&#xff1a;WMI(Windows Management Instrumentation,Windows 管理规范)是一项核心的 Windows 管理技术&#xff1b;用户可以使用 WMI 管理本地和远程计算机。WQL简介&#xff1a;WQL就是WMI中的查询语言&#xff0c;WQL的全称是WMI Query Language&#xff0c;简称…

如何:在Spring中使用@Conditional和Condition注册组件

Spring中的Profile批注可以用于任何自动检测候选的Spring组件&#xff08;例如&#xff0c; Service Component&#xff0c; Service Component &#xff0c; Service Configuration等&#xff09;。 Profile批注接受单个配置文件或一组必须是活动的配置文件&#xff0c;以使带…