我正在使用Scala Play 2.6,并尝试使用依赖注入来实例化基于请求参数的服务类。如下面的示例代码所示,控制器类从查询字符串中获取支付方法
package controllers
import com.google.inject.Inject
import play.api.mvc._
import scala.concurrent.ExecutionContext
class PaymentController @Inject()()
(implicit ec: ExecutionContext)
extends InjectedController {
def doPayment() = Action.async { implicit request =>
request.getQueryString("payment-method").getOrElse("") match {
case "paypal" => // Inject a PaypalPaymentService
val paymentService = Play.current.injector.instanceOf[PaypalPaymentService]
paymentService.processPayment()
case "creditcard" => // Inject a CreditCardPaymentService
val paymentService = Play.current.injector.instanceOf[CreditCardPaymentService]
paymentService.processPayment()
case _ => // Return error
}
}
}
以及处理PayPal或信用卡付款的服务类
package services
import scala.concurrent.Future
trait PaymentService {
def processPayment(): Future[Boolean]
}
package services
import com.google.inject.Inject
import scala.concurrent.{ExecutionContext, Future}
import play.api.libs.ws.WSClient
class PaypalPaymentService @Inject()(ws: WSClient)
(implicit ec: ExecutionContext)
extends PaymentService {
def processPayment(): Future[Boolean] = {
//Process paypal payment
}
}
class CreditCardPaymentService @Inject()(ws: WSClient)
(implicit ec: ExecutionContext)
extends PaymentService {
def processPayment(): Future[Boolean] = {
//Process credit card payment
}
}
对于Play 2.5以后的版本,<code>Play。当前和播放。应用程序
已被弃用。
我有两个问题:
您已经正确地说明了Play.current
和Play.application
已经被弃用,从2.5开始,使用它们的方式确实是通过注入它们。
我将更改您的控制器定义,以便您使用DI来包括所需的组件。类似于:
class PaymentController @Inject()(configuration: Configuration)
(implicit ec: ExecutionContext) extends Controller {
// your code goes here
}
现在是棘手的部分。您可能会认为可以只注入应用程序:播放。应用程序
,但这并不完全正确,因为您将遇到循环依赖项。这是正常的,因为您希望在实际进入应用程序时注入整个应用程序。有一个黑客,它是通过注入提供者[应用程序]。
我称之为黑客,因为通常您不需要/不想注入整个应用程序。在 99% 的情况下,您只对特定部分感兴趣 - 例如配置
、环境
等。
解决方案来了。您只需注射注射器
class PaymentController @Inject()(injector: Injector)
(implicit ec: ExecutionContext) extends Controller {
// your code goes here
}
从这里看,这场比赛很容易。只需使用Injector
即可获得所需的服务。这样地:
case "paypal" => // Inject a PaypalPaymentService
val paymentService = injector.instanceOf(classOf[PaypalPaymentService])
paymentService.processPayment()
最后一句话是关于“正确的使用方法”。我实际上觉得你的方法还可以,不一定会改变。这个方向上的一个想法是,您创建一个模块
,如下所示:
import com.google.inject.AbstractModule
import com.google.inject.name.Names
class PaymentModule extends AbstractModule {
def configure() = {
bind(classOf[PaymentService])
.annotatedWith(Names.named("paypal"))
.to(classOf[PaypalPaymentService])
bind(classOf[PaymentService])
.annotatedWith(Names.named("creditcard"))
.to(classOf[CreditCardPaymentService])
}
}
在这种情况下,拥有一个共同的特性(正如你所做的那样)会有所帮助,你可以有多个实现,甚至可以为你的测试模拟实现。如果模块位于根包中,则将自动注册该模块。否则,你应该告诉Play它的位置:
play.modules.enabled="模块.支付模块"
我正在开发的应用程序已经具有Spring Security来处理基于表单的身份验证。现在,如果在某个请求参数中发现了令牌,则需要通过外部服务以编程方式登录用户。 换句话说,如果存在一个特定的请求参数,比如“token”,它需要用该令牌调用一个外部服务来验证它是否是一个有效的令牌。如果是,则用户将登录。 我不知道如何以及在哪里“触发”或“挂钩”Spring Security来检查这个参数并进行验证,
可以在模板中直接使用$Request对象,直接输入它的属性或调用它的大部分方法,但只支持方法的第一个参数; // 调用Request对象的get方法 传入参数为id {$Request.get.id} // 调用Request对象的param方法 传入参数为name {$Request.param.name} // 调用Request对象的param方法 传入参数为post.post_title
可以在模板中直接使用$Request对象,直接输入它的属性或调用它的大部分方法,但只支持方法的第一个参数; // 调用Request对象的get方法 传入参数为id {$Request.get.id} // 调用Request对象的param方法 传入参数为name {$Request.param.name} // 调用Request对象的param方法 传入参数为post.post_title
我已经浪费了10个小时试图弄明白一件简单的事情。 我有一个反应前端和一个Spring Boot后端在端口8080上运行。 我在前端有自己的登录表单。 在一个理想的世界里,我所希望的是让Spring Boot像往常一样进行表单验证,而没有那个丑陋的引导表单。 我设置了一个基本的内存身份验证只是为了练习,但它根本不起作用 我有两个选择: > 在Restendpoint中处理身份验证,然后将安全上下文设
问题内容: 而且我正在尝试更改方法注释,但是java.lang.reflect.Method不包含任何地图字段(例如“ annotations”)或方法(例如“ getDeclaredAnnotationMap”) 只有但是我可以用这个字节数组做什么? 那么,如何修改方法的注释呢? 编辑: 我创建了:http : //pastebin.com/T2rewcwU 但是,仅编辑此方法实例,如果取消注释
我试图写一个Spring MVC GET控制器,它需要Java8即时作为请求参数: 与: 我正在从一些React/Javascript代码触发一个GET请求,如下所示: Spring似乎不喜欢它,并抛出一个错误。以下是错误消息: 知道我为什么会收到这个吗? 谢谢你