天天看點

Scala微服務架構 三四 Controller層※. 本期文法糖

四 Controller層

之前我們已經把基層架構搭建好了,那麼要如何使用呢?

首先看看我的Controller層代碼

@Singleton
class BMAuthController @Inject()(implicit cc: ControllerComponents, actorSystem: ActorSystem)
            extends AbstractController(cc) with Circe with CirceJsonapiSupport {

    val entry = PlayEntry()

    def parseJson(jsonString: String) : Json = io.circe.parser.parse(jsonString).right.get
    def decodeJson[T](json: Json)(implicit d: io.circe.Decoder[T]) : T = json.as[T].right.get

    def login = Action(circe.json[RootObject]) { implicit request =>
            request
        import model.request.requestsJsonApiOpt.requestsJsonapiRootObjectReader._
        val tt = fromJsonapi(request.body)
        val reVal = entry.commonExcution(
                SequenceSteps(testStep(tt.reqs.head) :: Nil, None))

        val ctest = company("12", "alfred")
        val ctestj = asJsonApi(ctest)
        println(ctestj)

        val result = asJsonApiResult(reVal.asInstanceOf[userdetailresult])
        Ok(result.asJson)
    }
}           

4.1 Controller 的聲明

4.1.1 @Inject() 注解

@Inject()(implicit cc: ControllerComponents, actorSystem: ActorSystem)           

首先這個@Inject會查詢Play的System環境,并将查到的==單例執行個體==注入到參數中.

4.1.2 AbstractController 特質

官網解釋

  • AbstractController: an abstract class extending BaseController with a ControllerComponents constructor parameter that can be injected using constructor injection.

也就是說,這就是BaseController的抽象子類,但是要帶有一個ControllerComponents作為構造函數.

4.1.3 Circe 特質

circe是一個Scala的Json解析庫.并且目前已經支援Play.

Play的使用方式很簡單,首先引入項目:

libraryDependencies += "com.dripower" %% "play-circe" % "2609.1"           

然後繼承play.api.libs.circe.Circe特質

使用起來也很簡單,上面代碼的

circe.json[RootObject]

部分就是在使用Circe解析JsonApi的Root部分.

4.1.4 CirceJsonapiSupport 特質

對JsonApi協定的支援,裡面主要就是兩個隐式,代碼如下:

trait CirceJsonapiSupport extends CirceJsonapiEncoders with CirceJsonapiDecoders {
    implicit val circeJsonapiMarshaller = Marshaller.delegate[RootObject, String](
        `application/vnd.api+json`,
        `application/json`,
        ContentTypes.`application/json`
    )(_.asJson.noSpaces)
    implicit val circeJsonapiUnmarshaller = Unmarshaller.delegate[String, RootObject](
        `application/vnd.api+json`,
        `application/json`
    )(decode[RootObject](_).right.get)
}

object CirceJsonapiSupport extends CirceJsonapiSupport           

4.2 login 代碼解析

對不起,各位,暫時沒寫!!! ,有興趣的可以私信我,後期我會補上.

※. 本期文法糖

※.1 Scala的構造函數

學自

https://www.w3cschool.cn/scala/scala-constructors.html

今天要說的當然不是大家熟知的構造函數,而是以前我們可能忽略的細節.

class User1(var id: String, var name: String)

class User2(val id: String, val name: String)

class User3(private var id: String,private  var name: String)

class User4(id: String, name: String)           

上面代碼定義了四個User類,每個類都有兩個參數

id

name

,當然,他們構造函數的差別也很明顯.那麼這幾種不同的定義方式,有什麼差別呢?

  • User1,定義了可變構造參數,同時編譯器會自動生成setter和getter方法,但因為是預設修飾符,是以外部可以直接通路

    user1.id

    ,或者指派

    user1.id("001")

  • User2,因為定義的構造參數是不可變的,是以隻會生成getter方法,不會有setter方法,也是預設修飾符,是以外部隻可以通路

    user2.id

    ,無法指派
  • User3,和User1很像,但是修飾符改為private,是以即便是var的構造參數,也不會生成getter方法和setter方法
  • User4,我們最常用的寫法,其實就是

    private[this] val

    ,也就是說對于自己和伴生類而言是可見的

應楊總要求,我們列印上面四個User類的編譯資訊

def tree1 = reify { class User1(var id: String, var name: String) }.tree
def tree2 = reify { class User2(val id: String, val name: String) }.tree
def tree3 = reify { class User3(private var id: String,private  var name: String) }.tree
def tree4 = reify { class User4(id: String, name: String) }.tree           

然後分别列印上面的四個樹,輸出結果如下:

tree1:

{
  class User1 extends AnyRef {
    <paramaccessor> var id: Predef.String = _;
    <paramaccessor> var name: Predef.String = _;
    def <init>(id: Predef.String, name: Predef.String) = {
      super.<init>();
      ()
    }
  };
  ()
}           

tree2:

{
  class User2 extends AnyRef {
    <paramaccessor> val id: Predef.String = _;
    <paramaccessor> val name: Predef.String = _;
    def <init>(id: Predef.String, name: Predef.String) = {
      super.<init>();
      ()
    }
  };
  ()
}           

tree3:

{
  class User3 extends AnyRef {
    <paramaccessor> private var id: Predef.String = _;
    <paramaccessor> private var name: Predef.String = _;
    def <init>(id: Predef.String, name: Predef.String) = {
      super.<init>();
      ()
    }
  };
  ()
}           

tree4:

{
  class User3 extends AnyRef {
    <paramaccessor> private[this] val id: Predef.String = _;
    <paramaccessor> private[this] val name: Predef.String = _;
    def <init>(id: Predef.String, name: Predef.String) = {
      super.<init>();
      ()
    }
  };
  ()
}