All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ecfront.rpc.Router.scala Maven / Gradle / Ivy

package com.ecfront.rpc

import java.util.regex.Pattern

import com.ecfront.common.Resp
import com.typesafe.scalalogging.slf4j.LazyLogging

import scala.collection.mutable

/**
 * 路由操作对象
 * @param requestClass 请求对象的类型
 * @param fun 业务方法
 */
case class Fun[E](requestClass: Class[E], private val fun: (Map[String, String], E, Any) => Any) {
  private[rpc] def execute(parameters: Map[String, String], body: Any, inject: Any): Any = {
    try {
      fun(parameters, body.asInstanceOf[E], inject)
    } catch {
      case e: Exception =>
        Resp.serverError(e.getMessage)
    }
  }
}

/**
 * 路由表
 */
private[rpc] class Router extends LazyLogging {

  //业务方法容器,非正则
  private val funContainer = collection.mutable.Map[String, collection.mutable.Map[String, (Fun[_], Server)]]()
  funContainer += ("POST" -> collection.mutable.Map[String, (Fun[_], Server)]())
  funContainer += ("GET" -> collection.mutable.Map[String, (Fun[_], Server)]())
  funContainer += ("DELETE" -> collection.mutable.Map[String, (Fun[_], Server)]())
  funContainer += ("PUT" -> collection.mutable.Map[String, (Fun[_], Server)]())
  //业务方法容器,正则
  private val funContainerR = collection.mutable.Map[String, mutable.Buffer[((Pattern, Seq[String]), (Fun[_], Server))]]()
  funContainerR += ("POST" -> mutable.Buffer[((Pattern, Seq[String]), (Fun[_], Server))]())
  funContainerR += ("GET" -> mutable.Buffer[((Pattern, Seq[String]), (Fun[_], Server))]())
  funContainerR += ("DELETE" -> mutable.Buffer[((Pattern, Seq[String]), (Fun[_], Server))]())
  funContainerR += ("PUT" -> mutable.Buffer[((Pattern, Seq[String]), (Fun[_], Server))]())
  //正则转换前后的映射,如 ^/base/test2/(?[^/]+)/$ -> /base/test2/:id/
  private val containerOriginalR = collection.mutable.Map[String, String]()


  /**
   * 获取对应的路由信息,先按非正则匹配,匹配再从正则容器中查找
   * @param method 资源操作方式
   * @param path 资源路径
   */
  private[rpc] def getFunction(method: String, path: String, parameters: collection.mutable.Map[String, String]): (Resp[Any], Fun[_], Any => Any) = {
    var urlTemplate: String = path
    var fun: Fun[_] = null
    var server: Server = null
    val r = funContainer.get(method.toUpperCase).get.get(path).orNull
    if (r == null) {
      funContainerR.get(method).get.foreach {
        item =>
          val matcher = item._1._1.matcher(path)
          if (matcher.matches()) {
            urlTemplate = containerOriginalR(item._1._1.pattern())
            fun = item._2._1
            server = item._2._2
            item._1._2.foreach(name => parameters += (name -> matcher.group(name)))
          }
      }
    } else {
      fun = r._1
      server = r._2
    }
    if (server != null) {
      val result = server.preExecute(method, urlTemplate, parameters.toMap)
      if (result) {
        (result, fun, server.postExecute)
      } else {
        (Resp.fail(result.code, result.message), null, null)
      }
    } else {
      (Resp.notImplemented("[ %s ] %s".format(method, path)), null, null)
    }
  }

  /**
   * 注册路由规则
   * @param method 资源操作方式
   * @param path 资源路径
   * @param requestClass 请求对象的类型
   * @param fun 业务方法
   * @param server server对象
   */
  private[rpc] def add[E](method: String, path: String, requestClass: Class[E], fun: => (Map[String, String], E, Any) => Any, server: Server) {
    val nPath = server.formatUrl(path)
    logger.info(s"Register [${server.getChannel}] method [$method] path : $nPath.")
    if (nPath.contains(":")) {
      //regular
      val r = Router.getRegex(nPath)
      containerOriginalR += r._1.pattern() -> nPath
      funContainerR.get(method).get += (r ->(Fun[E](requestClass, fun), server))
    } else {
      funContainer.get(method).get += (nPath ->(Fun[E](requestClass, fun), server))
    }
  }
}

object Router {

  private def getRegex(path: String): (Pattern, Seq[String]) = {
    var pathR = path
    var named = mutable.Buffer[String]()
    """:\w+""".r.findAllMatchIn(path).foreach {
      m =>
        val name = m.group(0).substring(1)
        pathR = pathR.replaceAll(m.group(0), """(?<""" + name + """>[^/]+)""")
        named += name
    }
    (Pattern.compile("^" + pathR + "$"), named)
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy