spring+kotlinでJSONのリクエストとレスポンスをやってみた

Controller

package com.example.demo

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController

@RestController
class DemoController() {
    @GetMapping("/user")
    fun getUser(): User {
        val user = User(
            username = "grahamcox",
            screenName = "Graham"
        )
        return user
    }

    @PostMapping("/user")
    fun  registerUser(@RequestBody user: User): User {
        return user
    }
}

Userクラス

package com.example.demo

import com.fasterxml.jackson.annotation.JsonCreator

data class User @JsonCreator constructor(
    val username: String,
    val screenName: String
)

GETリクエス

http://localhost:8080/userにアクセスすると,{"username":"grahamcox","screenName":"Graham"}のようなJSONが返ってくる

POSTリクエス

下のようなリクエストをcurlで送る

curl --data '{"username":"test", "screenName":"mituba"}' -v -X POST -H 'Content-Type:application/json' http://localhost:8080/user

{"username":"test","screenName":"mituba"}のようなJSONが返ってくる

参考

参考にしました

scotch.io

kotlin+springをSpring Initializrを使ってサクッとhello worldまで

とりあえず今回は以下のバージョンで行いました

  • spring:2.0.0

Generate Projectを押すとzipファイルが落ちてきます. それを解答して,開発を始めます.

Controllerの追加

DemoApplicationが指定したgroupID, ArtifactIDの階層にあると思うので,そこと同じ階層にDemoControllerを作成します.

package com.example.demo

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RestController

@RestController
class CustomerController() {

    @GetMapping("/")
    fun hello() = "hello"

    @GetMapping("/{name}")
    fun helloName(@PathVariable name:String)
            = name
}

ルーティング

  • 今回は以下のようなルーティングにした
Method Route
GET /
GET /{name}

あとはgradle bootRunで起動する.http://localhost:8080にアクセスすると確認できる.

sbtのプロジェクト作成からAkka Streamの触りまでをやってみた

  • scala version:2.12.3
  • sbt version:1.0.2

sbtプロジェクト作成する

sbt new sbt/scala-seed.g8 

name [Scala Seed Project]:と聞かれるのでプロジェクト名を入力します.

プロジェクトのディレクトリが作成されます.

build.sbtの依存関係にAkka Streamを追加する

import Dependencies._

lazy val root = (project in file(".")).
  settings(
    inThisBuild(List(
      organization := "com.example",
      scalaVersion := "2.12.3",
      version      := "0.1.0-SNAPSHOT"
    )),
    name := "Hello",
    // 以下のように変更(libraryDependenciesを変更)
    libraryDependencies ++= Seq(
        scalaTest % Test,
        "com.typesafe.akka" %% "akka-actor" % "2.5.6",
        "com.typesafe.akka" %% "akka-stream" % "2.5.6"
        )
  )

コードを変更する

プロジェクト作成時に作成されているHello.scalaを以下のように変更しました.

package example

import akka.stream._
import akka.stream.scaladsl._
import akka.actor.ActorSystem

object Hello extends Greeting with App {
  implicit val system = ActorSystem("QuickStart")
  implicit val materializer = ActorMaterializer()

  val source = Source[Int](1 to 5)
  val sink = Sink.foreach[Int](println)

  source
   .map(_ * 2)
   .runWith(sink)


  println(greeting)
}

trait Greeting {
  lazy val greeting: String = "hello"
}

以下のように出力されたら成功です.

hello
[debug]     Thread run-main-0 exited.
[debug] Waiting for thread QuickStart-akka.actor.default-dispatcher-2 to terminate.
2
4
6
8
10

参考にしました

adtech.cyberagent.io

Apache Solrで,(カンマ)の扱いを任意の処理にさせる

Apache Solrのコアを作成したあと,$SOLR/server/solr/birth_3gram.xml/conf/managed-schemaのstringsフィールドの設定を以下のように変更します.(今回はカンマが含まれる文字列をsolrにsplitさせて検索させる方法です)

<fieldType name="strings" class="solr.TextField" multiValued="true">
      <analyzer type="index">
          <tokenizer class="solr.PatternTokenizerFactory" pattern="\s*,\s*"/>
          <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
         <filter class="solr.LowerCaseFilterFactory"/>
     </analyzer>
     <analyzer type="query">
         <tokenizer class="solr.PatternTokenizerFactory" pattern="\s*,\s*"/>
         <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
         <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
         <filter class="solr.LowerCaseFilterFactory"/>
     </analyzer>
 </fieldType>

その後,Analysisで確認すると分割されていることがわかります.

f:id:MitubaEX:20171006020950p:plain

今回はindex, query両方共に適応していますが,どちらかだけしかいらない場合はその都度消します.

GOでのファイル読み取り(標準入力も)

以下のコードでできる

package main

import (
    "bufio"
    "fmt"
    "os"
)



func main() {
    // ファイル読み取り(引数でファイル名受け取り)
    fp, err := os.Open(os.Args[1])
    if err != nil {
        panic(err)
    }
    defer fp.Close()
    scanner := bufio.NewScanner(fp)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
    if err := scanner.Err(); err != nil {
        panic(err)
    }

        // 標準入力読み取り
    s := bufio.NewScanner(os.Stdin)
    for s.Scan() {
        fmt.Println(s.Text())
    }
}

Dockerを用いてMySQLコンテナをCLIで立ち上げる方法

備忘録として置いておきます.

起動

docker run --tty -p 3306:3306 --detach --name=DB-mysql --env MYSQL_DATABASE=DB --env MYSQL_USER="user" --env MYSQL_PASSWORD="password" --env MYSQL_ROOT_PASSWORD="PASSWORD" mysql:latest --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci 

データベース名はDB,コンテナ名はDB-mysqlとしています.

テーブル作成

docker exec --interactive DB-mysql mysql --host localhost --default-character-set=utf8mb4 --user=root --password=PASSWORD DB < data.sql

適当にdata.sqlというファイルを用意してください.

以下にdata.sqlの例を示しておきます.

USE DB;

CREATE TABLE users(
    user_id varchar(64) NOT NULL,
    password varchar(128) NOT NULL
);

あとは各アプリでlocalhost:3306/<database_name>にアクセスするとつながると思います.

まとめ

テスト用にDBが欲しい時などに手軽に作成ができるのが,良い点だと思いました.

おまけ

dbの情報をsqlファイルにエクスポートする

docker exec CONTAINER /usr/bin/mysqldump -u root --password=root DATABASE > backup.sql

CONTAINER, DATABASEなどは適宜変更をお願いします.