本文整理汇总了Scala中com.twitter.util.Future类的典型用法代码示例。如果您正苦于以下问题:Scala Future类的具体用法?Scala Future怎么用?Scala Future使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了Future类的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Scala代码示例。
示例1: beforeAll
//设置package包名称以及导入依赖的类
package placeholder.base
import java.net.InetSocketAddress
import com.twitter.finagle
import com.twitter.finagle.Service
import com.twitter.finagle.http.{Request, Response}
import com.twitter.util.Future
import org.scalatest._
import placeholder.Main
import scala.concurrent.Await
import scala.concurrent.duration._
trait IntegrationTestBase extends FeatureSpec with GivenWhenThen with Matchers with BeforeAndAfterAll {
val server = Main
var serverAddress: InetSocketAddress = _
var client: Service[Request, Response] = _
var requestHost: String = _
server.main(Array())
override def beforeAll(): Unit = {
serverAddress = Await.result(server.getServerAddress, 10.seconds)
requestHost = s"localhost:${serverAddress.getPort.toString}"
client = finagle.Http.newService(requestHost)
}
def performRequest(request: Request): Future[Response] = {
request.host = requestHost
client(request)
}
}
开发者ID:scala-academy,项目名称:skeleton-project,代码行数:35,代码来源:IntegrationTestBase.scala
示例2: HandleRefusedByRateLimiterFilter
//设置package包名称以及导入依赖的类
package com.lookout.ratelimitingfilter
import com.twitter.finagle.http.{Request, Response}
import com.twitter.finagle.{Failure, Service, SimpleFilter, RefusedByRateLimiter}
import com.twitter.util.Future
import com.twitter.logging.Logger
case class HandleRefusedByRateLimiterFilter() extends SimpleFilter[Request, Response] {
val LOG = Logger.get(getClass)
def apply(request: Request, service: Service[Request, Response]): Future[Response] = Future {
service(request) handle {
case _: RefusedByRateLimiter => {
val rateLimitedMessage = s"Request is rate limited: ${request.encodeString()}"
LOG.info(rateLimitedMessage)
RefusedByRateLimiterError(rateLimitedMessage).toResponse
}
}
}.flatMap(identity _)
}
开发者ID:lookout,项目名称:rate-limiting-strategy,代码行数:22,代码来源:HandleRefusedByRateLimiterFilter.scala
示例3: LookoutRateLimitingStrategy
//设置package包名称以及导入依赖的类
package com.lookout.ratelimitingfilter
import java.util.UUID
import com.twitter.finagle.http.{Request}
import com.twitter.util.{Future}
import com.twitter.logging.Logger
import shapeless.tag._
import com.lookout.ratelimitingfilter.models._
case class LookoutRateLimitingStrategy(
serviceLookup: Request => Option[String @@ ServiceName],
claimLookup: Request => Option[(UUID @@ EntClaim, UUID @@ SubClaim)],
rulesLookup: () => List[RateLimitRule],
processRule: RateLimitRule => Boolean
) {
val LOG = Logger.get(getClass)
def apply(request: Request): Future[Boolean] = {
val normalizedRequests = RequestNormalization(serviceLookup, claimLookup, request)
val matchedRules = RateLimitRuleMatcher(rulesLookup, normalizedRequests)
val underThreshold = try {
matchedRules.map(processRule).reduce(_ && _)
} catch {
case e: RedisError => {
LOG.info(s"Redis error. Rate limiting is switched off. ${e.getMessage}")
true
}
}
Future.value(underThreshold)
}
}
开发者ID:lookout,项目名称:rate-limiting-strategy,代码行数:33,代码来源:LookoutRateLimitingStrategy.scala
示例4: TemperatureSensorStatic
//设置package包名称以及导入依赖的类
package net.gutefrage.basic
import com.twitter.conversions.time._
import com.twitter.finagle.ThriftMux
import com.twitter.finagle.util.DefaultTimer
import com.twitter.server.TwitterServer
import com.twitter.util.{Await, Future}
import net.gutefrage.temperature.thrift._
import net.gutefrage.{Dtabs, Env}
import org.slf4j.bridge.SLF4JBridgeHandler
object TemperatureSensorStatic extends TwitterServer {
val env = flag[Env]("env", Env.Local, "environment this server runs")
premain {
SLF4JBridgeHandler.removeHandlersForRootLogger()
SLF4JBridgeHandler.install()
// initialise custom dtabs
Dtabs.init()
}
onExit {
log.info("Shutting down sensor")
}
def main(): Unit = {
// create a thrift client and resolve address via dtabs
val client = ThriftMux.client.newIface[TemperatureService.FutureIface](
// schema ! args
dest = s"zk2!127.0.0.1:2181!/service/${env().name}/temperature",
label = "temperature-sensor"
)
implicit val timer = DefaultTimer.twitter
val randomTemp = new java.util.Random()
def sendLoop: Future[Unit] = {
val datum = TemperatureDatum(randomTemp.nextInt(40) - 10,
System.currentTimeMillis / 1000)
log.info(s"Sending data: $datum")
for {
_ <- Future.sleep(1.second)
_ <- client.add(datum)
_ <- sendLoop
} yield ()
}
Await.ready(sendLoop)
}
}
开发者ID:gutefrage,项目名称:the-finagle-docs,代码行数:54,代码来源:TemperatureSensorStatic.scala
示例5: WhichUserLogin
//设置package包名称以及导入依赖的类
package com.bob.reservefund.scala.Filter
import javax.inject.Inject
import com.twitter.finagle.filter.LogFormatter
import com.twitter.finagle.http.{Request, Response}
import com.twitter.finagle.{Service, SimpleFilter}
import com.twitter.inject.Logging
import com.twitter.util.{Stopwatch, Future}
case class WhichUserLogin(id: Long)
object WhichUserLoginContext {
private val UserField = Request.Schema.newField[WhichUserLogin]()
class RequestAopFilter[R <: Request] @Inject()(
logFormatter: LogFormatter[R, Response])
extends SimpleFilter[R, Response] with Logging {
override def apply(request: R, service: Service[R, Response]): Future[Response] = {
if (!isInfoEnabled) {
service(request)
}
else {
val elapsed = Stopwatch.start()
service(request) onSuccess { response =>
info(response.contentString)
} onFailure { e =>
// should never get here since this filter is meant to be after the exception barrier
info(logFormatter.formatException(request, e, elapsed()))
}
}
}
}
开发者ID:bobxwang,项目名称:ReserveFundService,代码行数:37,代码来源:WhichUserLoginFilter.scala
示例6: AvroUtils
//设置package包名称以及导入依赖的类
package pulse.kafka.avro
import java.io.{ByteArrayInputStream, ByteArrayOutputStream, DataInputStream, File}
import com.twitter.util.Future
import org.apache.avro.Schema
import org.apache.avro.file.DataFileWriter
import org.apache.avro.generic.{GenericDatumReader, GenericDatumWriter, GenericRecord}
import org.apache.avro.io.DecoderFactory
import pulse.kafka.extensions.managedByteArrayInputStream
import pulse.kafka.extensions.managedByteArrayOutputStream
import pulse.kafka.extensions.catsStdInstancesForFuture
import scala.concurrent.ExecutionContext.Implicits._
object AvroUtils {
import pulse.common.syntax._
def jsonToAvroBytes(json: String, schemaFile: File): Future[Array[Byte]] =
use(new ByteArrayOutputStream()) { output =>
for {
s <- loadSchema(schemaFile)
_ <- convertImpl(json, output, s)
} yield output.toByteArray
}
private def convertImpl(json: String, output: ByteArrayOutputStream, schemaSpec: Schema): Future[GenericDatumReader[GenericRecord]] =
use(new ByteArrayInputStream(json.getBytes)) { input =>
for {
w <- getWriter(output, schemaSpec)
r <- getReader(input, schemaSpec, w)
} yield r
}
def getReader(input: ByteArrayInputStream, schemaSpec: Schema, w: DataFileWriter[GenericRecord]) = Future.value {
val reader = new GenericDatumReader[GenericRecord](schemaSpec)
val datum = reader.read(null, getJsonDecoder(input, schemaSpec))
w.append(datum)
w.flush()
reader
}
private def getJsonDecoder(input: ByteArrayInputStream, schema: Schema) =
DecoderFactory.get.jsonDecoder(schema, new DataInputStream(input))
private def getWriter(output: ByteArrayOutputStream, schemaSpec: Schema) = {
Future.value {
val writer = new DataFileWriter[GenericRecord](new GenericDatumWriter[GenericRecord]())
writer.create(schemaSpec, output)
}
}
private def loadSchema(schemaFile: File): Future[Schema] =
Future {
new Schema.Parser().parse(schemaFile)
}
}
开发者ID:gpulse,项目名称:kafka,代码行数:60,代码来源:AvroUtils.scala
示例7: PromiseOps
//设置package包名称以及导入依赖的类
package pulse.kafka.extensions
import com.twitter.util.{Future, Promise}
object PromiseOps {
implicit def onComplete[T](p: Promise[T], payload: T, exception: Exception) = {
if (payload != null) p.setValue(payload) else p.setException(exception)
}
implicit def toTwitter[T](body: Promise[T] => Unit) : Future[T] = {
val p = Promise[T]()
body(p)
p
}
}
开发者ID:gpulse,项目名称:kafka,代码行数:16,代码来源:PromiseOps.scala
示例8: FibonacciSequenceService
//设置package包名称以及导入依赖的类
package services
import algorithms.sequences.{FibonacciFinder, MatricesFibonacciFinder}
import com.twitter.finagle.Service
import com.twitter.finagle.httpx.{Request, Response}
import com.twitter.util.Future
import io.finch.request.param
import io.finch.response._
object FibonacciSequenceService extends Service[Request, Response] {
val fibonacciFinder: FibonacciFinder = new MatricesFibonacciFinder()
override def apply(request: Request): Future[Response] = {
for {
termNumber <- param("termNumber")(request).map(_.toInt)
} yield {
val result = fibonacciFinder.findNthTermInSequence(termNumber)
Ok(s"$result")
}
}
}
开发者ID:willb611,项目名称:algorithms-service,代码行数:22,代码来源:FibonacciSequenceService.scala
示例9: PathToHostIdentifier
//设置package包名称以及导入依赖的类
package com.askattest.http.identifiers.pathtohost
import java.net.URI
import com.twitter.finagle.http.Request
import com.twitter.finagle.{Dtab, Path}
import com.twitter.util.Future
import io.buoyant.router.RoutingFactory
import io.buoyant.router.RoutingFactory.{RequestIdentification, UnidentifiedRequest}
case class PathToHostIdentifier(
prefix: Path,
baseDtab: () => Dtab = () => Dtab.base
) extends RoutingFactory.Identifier[Request] {
private[this] val MoveOn =
Future.value(new UnidentifiedRequest[Request]("MoveOn to next identifier"))
def apply(req: Request): Future[RequestIdentification[Request]] = {
// Example request URI: /www.google.com:80
val host = new URI(s"http:/${req.uri}").getHost
req.headerMap.set("Host", host)
MoveOn
}
}
开发者ID:Attest,项目名称:linkerd-plugins,代码行数:27,代码来源:PathToHostIdentifier.scala
示例10: ControllerCollection
//设置package包名称以及导入依赖的类
package io.peregrine
import com.twitter.finagle.http.{Request => FinagleRequest, Response => FinagleResponse}
import com.twitter.util.Future
class ControllerCollection {
var controllers: Seq[Controller] = Seq.empty
var notFoundHandler = { request: Request =>
render.status(404).plain("Not Found").toFuture
}
var errorHandler = { request: Request =>
request.error match {
case Some(e: UnsupportedMediaType) =>
render.status(415).plain("No handler for this media type found").toFuture
case _ =>
render.status(500).plain("Something went wrong!").toFuture
}
}
def render: ResponseBuilder = new ResponseBuilder
def dispatch(request: FinagleRequest): Option[Future[FinagleResponse]] = {
var response: Option[Future[FinagleResponse]] = None
controllers.find { ctrl =>
ctrl.route.dispatch(request) match {
case Some(callbackResponse) =>
response = Some(callbackResponse)
true
case None =>
false
}
}
response
}
def add(controller: Controller) {
notFoundHandler = controller.notFoundHandler.getOrElse(notFoundHandler)
errorHandler = controller.errorHandler.getOrElse(errorHandler)
controllers = controllers ++ Seq(controller)
}
}
开发者ID:pairi,项目名称:pairi,代码行数:46,代码来源:ControllerCollection.scala
示例11: Route
//设置package包名称以及导入依赖的类
package io.peregrine
import com.twitter.util.Future
import org.jboss.netty.handler.codec.http._
case class Route(method: HttpMethod, path: String, pattern: PathPattern, callback: Request => Future[ResponseBuilder])
class RouteVector {
var vector = Vector[Route]()
def add(x: Route) {
vector = x +: vector
}
def withPrefix(prefix: String) = {
vector = vector.map { r =>
val composedPath = prefix + r.path
r.copy(
path = composedPath,
pattern = SinatraPathPatternParser(composedPath)
)
}
}
}
开发者ID:pairi,项目名称:pairi,代码行数:25,代码来源:RouteVector.scala
示例12: HelloFinagleClient
//设置package包名称以及导入依赖的类
package jp.gr.java_conf.massakai.application
import com.twitter.finagle.{Http, Service, http}
import com.twitter.util.{Await, Future}
object HelloFinagleClient extends App {
val client: Service[http.Request, http.Response] = Http.newService("www.scala-lang.org:80")
val request = http.Request(http.Method.Get, "/")
request.host = "www.scala-lang.org"
val response: Future[http.Response] = client(request)
response.onSuccess { resp: http.Response =>
println("GET success: " + resp)
}
Await.ready(response)
}
开发者ID:massakai,项目名称:finagle-kafka-sample,代码行数:16,代码来源:HelloFinagleClient.scala
示例13: Pong
//设置package包名称以及导入依赖的类
package com.github.ikhoon.app.v1.ping
import javax.inject.Inject
import com.github.ikhoon.swagger.SimpleSwaggerController
import com.google.inject.Singleton
import com.twitter.finagle.http.Request
import com.twitter.util.Future
import com.typesafe.config.Config
case class Pong(pong: String)
@Singleton
class PingController @Inject() (config: Config) extends SimpleSwaggerController {
{
get("/ping") { request: Request =>
info("ping")
Future.value(Pong("pong"))
}
}
}
开发者ID:ikhoon,项目名称:finatra-mysql-seed,代码行数:23,代码来源:PingController.scala
示例14: OAuthService
//设置package包名称以及导入依赖的类
package me.kamkor.yaas.oauth2
import javax.inject.{Inject, Singleton}
import com.twitter.finagle.http.Message
import com.twitter.finagle.http.Status._
import com.twitter.finatra.http.exceptions.InternalServerErrorException
import com.twitter.finatra.httpclient.RequestBuilder
import com.twitter.finatra.json.FinatraObjectMapper
import com.twitter.inject.Logging
import com.twitter.util.Future
import me.kamkor.finatra.httpclient.HttpClient
import me.kamkor.yaas.oauth2.model.{AccessToken, ClientCredentials}
@Singleton
class OAuthService @Inject()(
@OAuthClient client: HttpClient,
mapper: FinatraObjectMapper
) extends Logging {
def getToken(credentials: ClientCredentials): Future[AccessToken] = {
val postRequest = RequestBuilder
.post("token")
.body(createTokenForm(credentials), Message.ContentTypeWwwFrom)
postRequest.authorization = credentials.basicAuthorization
client.execute(postRequest) map { response =>
response.status match {
case Successful(code) => mapper.parse[AccessToken](response.contentString)
case _ => {
error(s"OAuth2 service returned status'${response.status}' and body '${response.contentString}.")
throw InternalServerErrorException("Backing service error")
}
}
}
}
private def createTokenForm(credentials: ClientCredentials): String = {
val scopeParam = if (credentials.scope.isEmpty) "" else s"&scope=${credentials.scope.mkString(" ")}"
s"grant_type=client_credentials$scopeParam"
}
}
开发者ID:kamkor,项目名称:yaas-wishlist-service,代码行数:45,代码来源:OAuthService.scala
示例15: YaasHeaders
//设置package包名称以及导入依赖的类
package me.kamkor.yaas.http.filters
import com.twitter.finagle.http.{Request, Response}
import com.twitter.finagle.{Service, SimpleFilter}
import com.twitter.util.Future
object YaasHeaders {
val HybrisTenant = "hybris-tenant"
}
case class YaasHeaders(hybrisTenant: String)
class YaasHeadersFilter extends SimpleFilter[Request, Response] {
override def apply(request: Request, service: Service[Request, Response]): Future[Response] = {
YaasHeadersContext.setYaasHeaders(request)
service(request)
}
}
// create a context, see https://twitter.github.io/finatra/user-guide/build-new-http-server/filter.html
object YaasHeadersContext {
private val YaasHeadersField = Request.Schema.newField[YaasHeaders]
implicit class YaasAwareContextSyntax(val request: Request) extends AnyVal {
def yaasHeaders: YaasHeaders = request.ctx(YaasHeadersField)
}
private[filters] def setYaasHeaders(request: Request): Unit = {
val hybrisTenant = request.headerMap(YaasHeaders.HybrisTenant)
val yaasAware = YaasHeaders(hybrisTenant)
request.ctx.update(YaasHeadersField, yaasAware)
}
}
开发者ID:kamkor,项目名称:yaas-wishlist-service,代码行数:36,代码来源:YaasHeadersFilter.scala
示例16: YaasProxyClient
//设置package包名称以及导入依赖的类
package me.kamkor.yaas.proxy
import com.github.benmanes.caffeine.cache.{Cache, Caffeine}
import com.twitter.conversions.time._
import com.twitter.finagle.http.{Request, Response}
import com.twitter.finatra.utils.FutureUtils
import com.twitter.util.Future
import me.kamkor.finatra.httpclient.HttpClient
import me.kamkor.yaas.oauth2.OAuthService
import me.kamkor.yaas.oauth2.model.{AccessToken, ClientCredentials}
object YaasProxyClient {
def apply(oauthService: OAuthService, httpClient: HttpClient) = new YaasProxyClient(oauthService, httpClient)
}
class YaasProxyClient(oauthService: OAuthService, httpClient: HttpClient) {
val cache: Cache[ClientCredentials, AccessToken] = Caffeine.newBuilder()
.build()
def execute(request: Request)(implicit clientCredentials: ClientCredentials): Future[Response] = {
getToken(clientCredentials) flatMap { token =>
request.authorization = token.bearerAuthorization
httpClient.execute(request)
}
}
private def getToken(credentials: ClientCredentials): Future[AccessToken] = {
Option(cache.getIfPresent(credentials)) match {
case Some(token) => Future.value(token)
case None => refreshToken(credentials)
}
}
private def refreshToken(credentials: ClientCredentials): Future[AccessToken] = {
def invalidateCache(): Future[Unit] = Future(cache.invalidate(credentials))
oauthService.getToken(credentials) map { token =>
cache.put(credentials, token)
val invalidateIn = token.expiresIn - Math.round((token.expiresIn * 0.2))
FutureUtils.scheduleFuture(invalidateIn.seconds)(invalidateCache)
token
}
}
}
开发者ID:kamkor,项目名称:yaas-wishlist-service,代码行数:47,代码来源:YaasProxyClient.scala
示例17: UserFilter
//设置package包名称以及导入依赖的类
package com.example
import com.example.db.DB
import com.google.inject.Inject
import com.twitter.finagle.http.{Request, Response, Status}
import com.twitter.finagle.{Filter, Service, SimpleFilter}
import com.twitter.util.Future
class UserFilter @Inject() extends SimpleFilter[Request, Response] {
override def apply(request: Request, service: Service[Request, Response]): Future[Response] = {
val token = request.cookies.get("auth_token")
DB.isValidToken(token.map(x => x.value).getOrElse("")) flatMap {
case true => service(request)
case false => redirectToLoginPage
}
}
def redirectToLoginPage = Future {
val response = Response(Status.TemporaryRedirect)
response.location = "/loginform"
response
}
}
开发者ID:Sergey778,项目名称:finatra_test,代码行数:27,代码来源:UserFilter.scala
示例18: ThriftMuxGlobalServer
//设置package包名称以及导入依赖的类
package com.example
import com.twitter.finagle.example.thriftscala.Hello
import com.twitter.finagle.example.thriftscala.Hello.Hi.{Args, Result}
import com.twitter.finagle.thrift.ClientId
import com.twitter.finagle.{Service, SimpleFilter, Thrift, ThriftMux}
import com.twitter.util.{Await, Future}
object ThriftMuxGlobalServer {
def main(args: Array[String]) {
val iface = new Hello.FutureIface {
def hi() = {
println("received request")
println(s"Client id: ${ClientId.current}")
Future("hi there")
}
override def hello(): Future[String] = {
Future("hello there")
}
}
val filter = new SimpleFilter[Array[Byte], Array[Byte]] {
override def apply(request: Array[Byte], service: Service[Array[Byte], Array[Byte]]): Future[Array[Byte]] = {
println("filtered")
service(request)
}
}
val service = new Hello.FinagledService(iface, Thrift.protocolFactory)
val server = ThriftMux.serve("localhost:8081", filter andThen service)
Await.ready(server)
}
}
开发者ID:vtatai,项目名称:finagleThriftPlayground,代码行数:33,代码来源:ThriftMuxGlobalServer.scala
示例19: ThriftMuxServer
//设置package包名称以及导入依赖的类
package com.example
import com.twitter.finagle.example.thriftscala.Hello
import com.twitter.finagle.example.thriftscala.Hello.Hi.{Args, Result}
import com.twitter.finagle.{Service, SimpleFilter, Thrift, ThriftMux}
import com.twitter.util.{Await, Future}
object ThriftMuxServer {
def main(args: Array[String]) {
val filter = new SimpleFilter[Hello.Hi.Args, Hello.Hi.Result] {
override def apply(request: Args, service: Service[Args, Result]): Future[Result] = {
println("hahaha")
service(request)
}
}
val hiService = new Service[Hello.Hi.Args, Hello.Hi.Result] {
override def apply(request: Hello.Hi.Args): Future[Hello.Hi.Result] = {
Future(Hello.Hi.Result(Some("hi!")))
}
}
val helloService = new Service[Hello.Hello.Args, Hello.Hello.Result] {
override def apply(request: Hello.Hello.Args): Future[Hello.Hello.Result] = {
Future(Hello.Hello.Result(Some("hello!")))
}
}
val serviceImpl = Hello.ServiceIface(hi = filter andThen hiService, hello = helloService)
val server = ThriftMux.serveIface("localhost:8081", Hello.MethodIfaceBuilder.newMethodIface(serviceImpl))
Await.ready(server)
}
}
开发者ID:vtatai,项目名称:finagleThriftPlayground,代码行数:32,代码来源:ThriftMuxServer.scala
示例20: MySotonResponses
//设置package包名称以及导入依赖的类
package com.aluxian.susucatbot.domains
import com.aluxian.susucatbot.ai.{BotInterface, BotPast, ImageBotResponse, TextBotResponse}
import com.aluxian.susucatbot.models.Phrase._
import com.aluxian.susucatbot.models._
import com.aluxian.susucatbot.{ResponseGenerator, Story}
import com.twitter.util.Future
object MySotonResponses extends ResponseGenerator {
}
object MySotonActions {
}
object MySotonStory extends Story {
val phrases = List(
"Do I have any mail?" \\ EntityDef.Intent.GetMail,
"I hate coursework" \\ EntityDef.Intent.GetCoursework,
"I'm lost" \\ EntityDef.Intent.GetMap
)
def analyse(past: BotPast, bot: BotInterface): Boolean = {
past.currentMessage.hasIntent("get_mail") ||
past.currentMessage.hasIntent("get_coursework")||
past.currentMessage.hasIntent("get_map")
}
def run(past: BotPast, bot: BotInterface): Future[List[BotAction]] = {
Future(
if (past.currentMessage.hasIntent("get_mail"))
List(Respond(TextBotResponse("You have 1 parcel to collect")))
else if (past.currentMessage.hasIntent("get_coursework"))
List(Respond(TextBotResponse("Great, your ECS coursework is due in exactly 18 days!")))
else if (past.currentMessage.hasIntent("get_map"))
List(Respond(TextBotResponse("https://www.ocs.soton.ac.uk/public/site/images/ms4v09/Highfield_JUNE2012.jpg")))
else
List()
)
}
}
开发者ID:aluxian,项目名称:SusuCatBot,代码行数:43,代码来源:mysoton.scala
注:本文中的com.twitter.util.Future类示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论