Play Framework 2.5.1 路由和依赖项注入(适用于 Java)

2024-05-22

我的“路线”文件中有这个:

POST        /accounts/        controllers.AccountsController.createOneAccount

在我的 AccoutsController.java 中:

package controllers;

import com.google.inject.Inject;
import play.Application;
import play.mvc.Controller;
import play.mvc.Result;
import services.AccountService;
import java.io.IOException;

public class AccountsController extends Controller {
    @Inject
    private Application application;
    final String host = application.configuration().getString("db.default.host");
    final int port = application.configuration().getInt("db.default.port");
    final String dbName = application.configuration().getString("db.default.dbname");

    @Inject
    private AccountService accountService;
    public Result createOneAccount() throws IOException {
        return accountService.createOneAccount(request().body().asJson());
    }
}

这段代码编译得很好,但在运行时我得到了这样的错误:

ProvisionException:无法配置,看到以下错误:1) 注入构造函数时出错,java.lang.NullPointerException at 控制器.AccountsController.(AccountsController.java:11)
找到controllers.AccountsController时 对于 router.Routes.(Routes.scala:28) 处的参数 1,同时定位 router.Routes 同时定位 play.api.inject.RoutesProvider 找到 play.api.routing.Router 时 对于 play.api.http.JavaCompatibleHttpRequestHandler 处的参数 0。(HttpRequestHandler.scala:200) 查找 play.api.http.JavaCompatibleHttpRequestHandler 时 定位 play.api.http.HttpRequestHandler 对于 play.api.DefaultApplication.(Application.scala:221) 处的参数 4 play.api.DefaultApplication.class(Application.scala:221) 而 定位时定位 play.api.DefaultApplication play.api.Application 1 错误

我可以通过将 @ 添加到路由文件来解决此问题:

POST        /accounts/        @controllers.AccountsController.createOneAccount

但我不确定为什么需要这样做,以及如何避免“@”。请给一些建议。


首先,请参阅此答案以了解使用与不使用之间的区别@在你的routes file:

https://stackoverflow.com/a/34867199/4600 https://stackoverflow.com/a/34867199/4600

然后,正如所述Play 2.5.x 迁移文档 https://www.playframework.com/documentation/2.5.x/Migration25#Routes-generated-with-InjectedRoutesGenerator:

路线现已生成使用依赖注入 aware InjectedRoutesGenerator,而不是之前的StaticRoutesGenerator假设控制器是单例对象。

因此,从 Play 2.5.0 开始,控制器默认使用依赖注入,您不需要@让他们使用依赖注入。


现在让我们看看您的情况发生了什么。首先我要说的是,构造函数注入是注入依赖项的首选方式。 Guice 甚至建议(作为最佳实践)将final带有构造函数注入的字段最小化可变性 https://github.com/google/guice/wiki/MinimizeMutability。 Guice 文档还建议您尝试仅注入直接依赖项 https://github.com/google/guice/wiki/InjectOnlyDirectDependencies。在你的情况下,你正在使用application访问一个configuration。为什么不注入configuration对象代替?这将使您的依赖关系更加清晰(这将使每个实例的测试更容易)。

因此,按照此建议,您的代码将被重写为:

package controllers;

import com.google.inject.Inject;
import play.Configuration;
import play.mvc.Controller;
import play.mvc.Result;
import services.AccountService;
import java.io.IOException;

public class AccountsController extends Controller {

    private final Configuration configuration;
    private final AccountService accountService;

    private final String host;
    private final int port;
    private final String dbName;

    @Inject
    public AccountsController(Configuration configuration, AccountService accountService) {
        this.configuration = configuration;
        this.accountService = accountService;
        // initialize config variables
        this.host = configuration.getString("db.default.host");
        this.port = configuration.getInt("db.default.port");
        this.dbName = configuration.getString("db.default.dbname");
    }

    public Result createOneAccount() throws IOException {
        return accountService.createOneAccount(request().body().asJson());
    }
}

但为什么现场注入会中断呢?

我们首先需要了解对象初始化。根据Java 规范 http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.5:

在对新创建的对象的引用作为结果返回之前,将使用以下过程处理指定的构造函数以初始化新对象:

  1. 将构造函数的参数分配给为此构造函数调用新创建的参数变量。

  2. 如果此构造函数以同一类中另一个构造函数(使用 this)的显式构造函数调用(第 8.8.7.1 节)开始,则评估参数并使用这相同的五个步骤递归地处理该构造函数调用。如果该构造函数调用突然完成,则此过程也会出于同样的原因突然完成;否则,继续步骤 5。

  3. 此构造函数不会以显式构造函数调用同一类中的另一个构造函数(使用 this)开始。如果此构造函数用于除 Object 之外的类,则此构造函数将以显式或隐式调用超类构造函数(使用 super)开始。使用这五个步骤递归地评估参数并处理超类构造函数调用。如果该构造函数调用突然完成,则此过程也会出于同样的原因突然完成。否则,继续步骤 4。

  4. 执行此类的实例初始值设定项和实例变量初始值设定项,将实例变量初始值设定项的值按照类源代码中文本出现的从左到右的顺序分配给相应的实例变量。如果执行任何这些初始化程序导致异常,则不会再处理其他初始化程序,并且此过程会突然完成并出现相同的异常。否则,继续步骤 5。

  5. 执行该构造函数主体的其余部分。如果该执行突然完成,则该过程也会出于同样的原因突然完成。否则,该过程将正常完成。

特别注意步骤 4,它解释了变量是在对象初始化期间初始化的。

为什么这很重要?因为 Guice 首先创建对象(然后上面的所有步骤都会发生),然后执行注入绑定(请参阅吉斯引导程序 https://github.com/google/guice/wiki/Bootstrap and Guice注射点 https://github.com/google/guice/wiki/InjectionPoints更多细节)。因此,您的字段在对象初始化时需要变量(application)尚未注入,导致NullPointerException.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Play Framework 2.5.1 路由和依赖项注入(适用于 Java) 的相关文章

  • WebSphere 中跨 JVM 的会话复制

    我们建立了一个基础设施 其中网络服务器是集群的 而应用程序服务器不是 Web 服务器根据循环策略将请求路由到应用程序服务器 在这种情况下 一个应用程序服务器中可用的会话数据在另一应用程序服务器中不可用 无论如何 是否可以使来自第一个应用程序
  • 更改启动 Java 运行时后 IntelliJ IDEA 无法在 Ubuntu 上启动

    之前 我的 IntelliJ 运行得很好 但我使用的是 java 6 所以我的项目无法使用 gradle 运行 我用命令将java切换到版本8sudo update alternatives config java 我检查了java ver
  • Java Swing 应用程序消息对话框帮助

    我正在开发 Java Swing 应用程序 我需要创建一个如图所示的对话框 我不知道这个的名字 我无法解释 所以我附上一张照片 请告诉我这叫什么以及如何在我的 GUI 应用程序中创建它 给猫剥皮的方法不止一种 public final cl
  • Android:对于具有 LinearLayout 定义的成员的 ListView,上下文菜单不显示?

    我有一个 ListActivity 和 ListView 并且我已将一些数据绑定到它 数据显示得很好 而且我还为视图注册了一个上下文菜单 当我将列表项显示为简单的 TextView 时 它工作正常
  • Spring安全+LocaleResolver

    我需要在身份验证成功后更改区域设置 区域设置解析器
  • 检查从 arrayadapter 获取的复选框

    我有标题清单 CheckBox 我想控制默认检查哪一个 所以我试图获得正确的视图并检查它 但由于某种原因它不起作用 知道为什么吗 form checkbox item xml
  • 有没有办法让Maven自动下载快照版本?

    所以我有一个项目依赖于另一个项目的快照版本 依赖关系是
  • org.openqa.selenium.NoSuchSessionException:会话 ID 为空。调用 quit() 后使用 WebDriver?

    我已经进行了一些搜索 但仍然遇到同样的问题 我相信这可能是由于我的网络驱动程序是静态的造成的 我不太确定 在我的主课中 我包括了 BeforeTest and AfterTest BeforeTest包括根据我的 XML 文件启动新浏览器
  • Android:TelephonyManager 类

    我不明白为什么 API 文档中这么写TelephonyManager类是public 但是当我尝试创建一个实例时 它说它不是公共类 并且无法从包中访问 我看到它也说使用Context getSystemService Context TEL
  • Java - 调整图像大小而不损失质量

    我有 10 000 张照片需要调整大小 因此我有一个 Java 程序来执行此操作 不幸的是 图像的质量损失很大 而且我无法访问未压缩的图像 import java awt Graphics import java awt AlphaComp
  • 为什么不自动装箱泛型的 Java 基本类型?

    Java 不允许在通用数据结构中使用原始类型 例如 不允许使用 ArrayList 原因是 原始类型不能直接转换为Object 然而 Java 1 5 确实支持自动装箱 并且包装类在通用数据结构中工作 那么为什么编译器不能将其自动装箱到 A
  • 如何在java中从包含.0的浮点数中删除小数部分

    我只想删除包含的浮点数的小数部分 0 所有其他数字都是可以接受的 例如 I P 1 0 2 2 88 0 3 56666 4 1 45 00 99 560 O P 1 2 2 88 3 567 4 1 45 99 560 有什么方法可以做到
  • java中永远不会出现的异常

    我为点和向量编写一个类 我想用它们来计算向量的点和范数 这些是点类和向量类 public class Point public float x y public class MyVector public Point start end 我
  • 使用 Haskell 将函数注入到 Java .class 文件中

    我使用 Haskell 编写了一个 Java 字节码解析器 它工作得很好 然而下一步让我完全难住了 我的 Haskell 程序需要修改 class 文件 以便在执行时 Java 程序打印 输入 此处的方法名称 在执行方法之前 并且 退出 此
  • Eclipse Juno 指标插件

    Eclipse JUNO 版本有哪些 Eclipse 指标插件 我尝试了一些通用指标插件 但没有一个能够在 Eclipse 的 JUNO 版本中正常运行 差点忘了 我们正在使用 Java 作为编程语言 我想要诸如圈复杂度 代码行数 方法长度
  • 将一个整数从 C 客户端发送到 Java 服务器

    我使用此代码将一个整数从我的 Java 客户端发送到我的 Java 服务器 int n rand nextInt 50 1 DataOutputStream dos new DataOutputStream socket getOutput
  • 在Java内存管理中,“PS”代表什么?

    每当我看到 Java 中对内存的引用时 各种空格总是以 PS 为前缀 PS 是什么意思 它开始困扰我 到目前为止我唯一的猜测是 泳池空间 但这将是多余的 例子 PS伊甸园空间 PS 幸存者空间 PS 终身空间 老一代 PS Perm Gen
  • 空检查时可能未初始化错误

    我正在检查变量是否已初始化 但此时 netbeans 给了我variable reader might not have been initialized警告 我该如何解决 抑制这个问题 这是我的代码 摘要 final Reader rea
  • Android Webview:无法调用确定的可见性() - 从未见过 pid 的连接

    我有一个 Android Webview 当我单击链接下载文件 pdf 图像等 时 我收到一条错误消息 Error message Cannot call determinedVisibility never saw a connectio
  • Volley 在第一次调用方法时返回 null

    我正在尝试使用 volley 从服务器检索数据 但是当我第一次调用此方法时 我收到服务器的响应 但该方法返回 null 如果我第二次调用它 我会得到最后的响应 public String retrieveDataFromServer Str

随机推荐

  • Android 原生 AAssetManager 的文件层次结构

    Issue 我想知道如何从本机代码创建 Android 中资产文件夹的文件层次结构 我在用着AAssetManager openDir but AAssetDir getNextFileName不返回任何目录名称 因此基本上我无法深入了解层
  • 用等号完成命令选项

    我正在尝试为可能需要表单上的长选项的命令编写一个 Bash 完成脚本 option or param value 如果用户已经在命令行上输入了一个选项 则该选项应从完成列表中排除 假设仅在命令行上指定一次给定选项才有意义 这是第一次尝试 m
  • MongoDB C# 驱动程序检查身份验证状态和角色

    这是我使用 MongoDB 身份验证机制登录 MongoDB 的代码 try var credential MongoCredential CreateMongoCRCredential test admin 123456 var sett
  • 当我尝试在 Azure 上部署无框架静态 Web 应用程序时,为什么会从 GitHub Actions 收到生成错误?

    我有一个简单的静态网站 我尝试使用 GitHub Actions 将其部署为 Azure 静态 Web 应用程序 无框架 我的目录结构是 github workflows css img js index html 当我推送到 GitHub
  • 错误:grid.mongo.GridStore不是构造函数,使用mongoose、Grid-fs-stream和grid multer存储

    我收到以下提到的错误 基本配置如下 我已经将文件上传到服务器上 我想下载它们但出现这些错误 我向 api files delete fileId 调用了 POST 请求 它应该调用路由并将文件返回给浏览器 而不是使用网格相关模块获取错误 M
  • React:未捕获的引用错误:未定义需求

    我正在阅读 React 教程 http facebook github io react docs animation html http facebook github io react docs animation html 并且我无法
  • msal.js 访问令牌中的自定义声明

    我使用 msal js 保护了我的 Angular 7 应用程序 我创建了一个自定义策略 该策略返回 id token 和 access token 中的自定义声明类型 为了实现这一目标 我一直在遵循本教程 https learn micr
  • 模板类包装任意类型/非类型模板类

    假设我有一个模板类base和一个班级wrapper其中包含一个实例化成员base 我想定义班级wrapper这样它依赖于模板参数包 该参数包只是 传递 给实例化成员base 例如 考虑下面的代码 它工作得很好 include
  • PDO获取最后插入的ID

    我有一个查询 我想获取插入的最后一个 ID 字段ID是主键并且自动递增 我知道我必须使用这个声明 LAST INSERT ID 该语句适用于如下查询 query INSERT INTO cell place ID VALUES LAST I
  • 压缩很多小字符串的算法?

    我正在寻找一种压缩小 ASCII 字符串的算法 它们包含大量字母 但也可以包含数字和很少的特殊字符 它们很小 平均约为 50 100 字节 最多 250 个字节 例子 Android show EditText setError above
  • 如何在 UIWebView 中启用放大/缩小选项?

    如何在 UIWebView 中启用放大 缩小选项 这是 UIWebView 的默认功能 用你的手指
  • 动态更新 LookAndFeel 值

    我希望能够动态更新 Swing GUI 的 LookAndFeel 属性 在本例中 我有一个简单的 Swing Awt 游戏 运行最初为 Nimbus 的游戏LookAndFeel 在启动后的各个时刻 我只想更改 比方说 一个细节 应用程序
  • .net 4.5 可以与 .net 4.0 并行工作吗?

    我有兴趣安装 NET 4 5 但我听说这是就地升级 由于我公司的用户使用的是Windows XP 我无法发布任何使用 NET 4 5 的客户端应用程序 http visualstudio uservoice com forums 12157
  • C#中如何检测字符串是否为货币

    通常当我需要转换时currency string 如 1200 55 z 或 1 249 到十进制值我这样做 if currencyString Contains z decimal value Decimal Parse dataToCh
  • 我可以使用反射更改 C# 中的私有只读字段吗?

    我想知道 由于很多事情都可以使用反射完成 我可以在构造函数完成执行后更改私有只读字段吗 注 只是好奇 public class Foo private readonly int bar public Foo int num bar num
  • 如何改进 kubernetes 集群容器中的随机数生成?

    我发现运行的容器内的随机数生成存在一些问题 在 kubernetes 集群中 重复值 可能是缺乏熵 在容器内部 或者它可能是更高级别的其他东西 但是 我想研究熵角 我有几个问题 很难找到答案 proc sys kernel random e
  • 高级 Win32 图像文件 I/O?

    我想在 Windows C 应用程序中将图像文件读入内存 什么是一个相当简单的解决方案 也许类似于 IOS 提供的UIImage 我希望支持合理数量的文件格式 我需要为图像处理的位图提供一些低级访问权限 我在互联网上阅读了很多内容 看起来
  • 如何在代码块中包含内部引用?

    在我的 Sphinx rst 文档中 我有一个代码块 其中包含使用 UNIX 的产品结构的树视图tree命令 parent child grandchild 它位于代码块中 以便 Sphinx 保留空格 我希望读者能够单击每个节点来关注内部
  • 使用 SQL 扩展事件捕获链接服务器查询

    我尝试了许多事件类型 但无法实现链接服务器的日志记录 我可以找出所有其他数据库的事件 但对于链接服务器却没有运气 有什么建议 您可以使用OLEDB DATA READ跟踪对链接服务器的查询的事件 如果此事件的结果比您想要的更详细 您可能需要
  • Play Framework 2.5.1 路由和依赖项注入(适用于 Java)

    我的 路线 文件中有这个 POST accounts controllers AccountsController createOneAccount 在我的 AccoutsController java 中 package controll