Spring Boot ガンマン時計


Spring Boot の、ガンマン時計です。

単独のjarファイルになるので、どこでも実行可能。
試しに、GCP で動かしてみました。


Spring Boot ガンマン時計

ガンマン時計 (35.225.1.11:28080@GCP)

35.188.68.139 (gunman@GCP):停止中(メモリ不足)
35.202.98.32:28080/gunclocks (gunman@GCP) :VMのIP変わった。
http://gunman.mydns.jp:28081/gunclocks

  • Java の WebAP フレームワーク
  • view は thymeleaf で、オブジェクトから情報を取り出して表示
  • DBは、derby でローカルファイルに保存。
    JPA でアクセスするので、とても簡単。
  • buildをすると、1つの jarファイルになります。
    tomcat を梱包してくれる。
    試しに GCP で動作させました。


github


SpringBoot-Gunclcok.tar
展開して、./GunclockSpringBoot.start で起動。
derbyのDBにいくつかデータが入った状態。


【メモ】

■Sprint Boot 概要
- java で WebAP を作るフレームワーク
- Webコンテナ(tomcat)を含む 単独の jar を作ることができる
-- war にすることもできる
- view(html記述)は、thymleaf を使うのが基本。JSPを使うことも可能

■APのソース作り方(何通りかある)
・SpringInitialzrでWeb上で設定をして、一式をzipとして download
  - https://start.spring.io

  - dependency には、
    ・Spring Web : Webアプリケーションのひな型
    ・Thymeleaf:Web-APのview(html)
    [・Jersey:REST の Clientを作るとき ]

・コマンドでも作れるのかも
  $ mvn -B archetype:generate -DgroupId=com.sample -DartifactId=demo -Dversion=1.0.0-SNAPSHOT

・その後、自分で、ごりごりと? pom.xml を書いてゆく(感じか)

■APのbuild
・maven(もしくは gradle)で、buildを行う

■APの実行
・jarにしない場合は、
  $ cd xxxx
  $ ./mvnw spring-boot:run

・jarにする場合は、
  $ cd xxxx
  $ ./mvnw package
  $ cd target
  $ java -jar xxxx-0.0.1-SNAPSHOT.jar
 ※ tomcat を jar の中に、内在

・warにする場合は、
  tomcat の配下にコピー(かな)


・アクセスURLは、
   http://xxxx.xxxx.xxxx:8080/

  ポートを変えるときは、
  $ java -jar xxxx-0.0.1-SNAPSHOT.jar --server.port=28081


■準備
・maven
  - https://maven.apache.org/download.cgi
    ⇒ http://us.mirros.quenda.co/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
  - tar.gz を展開し、パスを通す

  ※ちなみに、mvnコマンドは、シェルスクリプト

  $ mkdir /home/ryuba/maven
  $ wget https://dlcdn.apache.org/maven/maven-3/3.9.12/binaries/apache-maven-3.9.12-bin.tar.gz
  $ gunzip a*
  $ tar xvf a*
  
  - PATHを通す
    ~/.bash_profile
-----
PATH=$PATH:/home/ryuba/maven/apache-maven-3.9.12/bin

export PATH
-----

・mvnw (maven Wrapper)
  $ mvn -N io.takari:maven:wrapper
  
  なお、SpringInitialzr で、プロジェクトの中に、「mvnwコマンド」が含まれるので、
  個別にmvnwを、インストールするひつようは、なさげ



■Spring Initializr
  https://start.spring.io/

- Starterを選ぶ
  - Spring Web
  - Thymeleaf
  - JPA
  - Derby
  - Actuator

- install
----------
mvnw clean install
----------

- 実行
--------
mvnw spring-boot:run
--------
 
- jar作成

pom.xmlに maven-jar-plugin.version を追加
---------------------------------
	
		1.8
		3.1.1
	
---------------------------------

----------
mvnw clean package
----------

----
java -jar target/xxxxxxxx.jar --server.port=28080
----

■maven
- https://udemy.benesse.co.jp/development/maven.html
javaのプロジェクト管理ツール
Apache maven
POM というフレームで、ビルドしたり実行したり。(pom.xml)
そのひな形を作るのが、SpringBoot

■GCPに仕込む

http://35.188.68.139:28080/gunclocks

- /etc/init.d にスクリプトを仕込むが
  derby DBのアクセス権が足りなくて、動かない
  rootで実行をしたいが、よくわからん
  ・su をスクリプトの中にかけない
  ・スティッキービットとか、うまくつかえないか?
  ・そもそも init.d が、誰ユーザで動くのかわからん
 → GunclockSpringBoot.start スクリプトを、手動実行することにした
    root で動かす必要がある。

$ sudo GunclockSpringBoot.start

root で background で動かすので、
gunman_forever00 は、ログアウトしてもOK。

■github
https://github.com/gunman-vagabond/GunclockSpringBoot

 $ mkdir SpringBoot/
 $ mkdir SpringBoot/Gunclock
 $ cd SpringBoot/Gunclock
 $ git clone https://github.com/gunman-vagabond/GunclockSpringBoot.git
 $ cd GunclockSpringBoot
 $ mvn install  (★mvnw install はエラー)
[$ mvn clean package ] ★mvnw package はエラー。mvn install で package相当も動作する
 $ sudo firewall-cmd --add-port=28081/tcp
 $ sudo firewall-cmd --add-port=28081/tcp --permanent


■systemd で動かす
- systemd 向けの定義ファイル
 $ cat /etc/systemd/system/my_gunclock_springboot.service 
 [Unit]
 Description=SpringBoot Gunclock
 After=network.target
 
 [Service]
 User=ryuba
 Type=simple
 #Type=forking
 ExecStart=/home/ryuba/SpringBoot/Gunclock/GunclockSpringBoot.start.forService
 Restart = always
 
 [Install]
 WantedBy=multi-user.target

- 実行するファイル
 $ cat /home/ryuba/SpringBoot/Gunclock/GunclockSpringBoot.start.forService 
-----
 #!/bin/sh
 
 #whoami
 
 cd /home/ryuba/SpringBoot/Gunclock/GunclockSpringBoot/target
 #su -c 'java -jar Gunclock-0.0.1-SNAPSHOT.jar' &
 #nohup java -jar Gunclock-0.0.1-SNAPSHOT.jar --server.port=28080 &
 java -jar /home/ryuba/SpringBoot/Gunclock/GunclockSpringBoot/target/Gunclock-0.0.1-SNAPSHOT.jar --server.port=28081
-----

※ gunman.mydns.jp は、28081にしてみる

- 実行
  $ sudo systemctl start my_gunclock_springboot
- 自動起動
  $ sudo systemctl enable my_gunclock_springboot
- 状態表示
  $ sudo systemctl status my_gunclock_springboot

■SpringBootソース概要

●htmlテンプレート
- Thymeleaf で記述
- th:text="*(color) などで、値を表示
- th:href="@{/gunclocks/{id}(id=*{id})
- 
- src/main/resources/templates/gunclocks/index.html -- https://github.com/gunman-vagabond/GunclockSpringBoot/blob/master/src/main/resources/templates/gunclocks/index.html --------- Listing Gunclocks

Listing Gunclocks

ID サイズ 生成日付
参照 編集
新規作成
--------- ●エンティティ (Gunclock) - DBをオブジェクトで表現 - getter/setterを記述 - id(キー値)用の、 @GeneratedValue(strategy = GenerationType.IDENTITY) - src/main/java/com/gunman/Gunclock/Gunclock.java -- https://github.com/gunman-vagabond/GunclockSpringBoot/blob/master/src/main/java/com/gunman/Gunclock/Gunclock.java ------- package com.gunman.Gunclock; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "gunclock") public class Gunclock { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private Integer size; private String color; private String createdDate; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public Integer getSize() { return size; } public void setSize(Integer size) { this.size = size; } public String getCreatedDate() { return createdDate; } public void setCreatedDate(String createdDate) { this.createdDate = createdDate; } @Override public String toString() { return "Gunclock [id=" + id + ", size=" + size + ", color=" + color + ", createdDate=" + createdDate + "]"; } } ------- ●Repository - JPAで、DBとのつなぎ -- DBアクセスのメソッドが実装されている( --- https://spring.pleiades.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html --- count, delete, deleteAll, deleteAll, deleteAllById, deleteById, existsById, findById, save など - インタフェースの継承のみ、JpaRepository<オブジェクト, IDの型> Repository T - リポジトリが管理するドメイン型 ID - リポジトリが管理するエンティティの ID の型 - src/main/java/com/gunman/Gunclock/GunclockRepository.java -- https://github.com/gunman-vagabond/GunclockSpringBoot/blob/master/src/main/java/com/gunman/Gunclock/GunclockRepository.java --------- package com.gunman.Gunclock; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface GunclockRepository extends JpaRepository { } --------- ●Service - DBアクセスのインタフェース(JPA)の実装 --- count, delete, deleteAll, deleteAll, deleteAllById, deleteById, existsById, findById, save など - src/main/java/com/gunman/Gunclock/GunclockService.java -- https://github.com/gunman-vagabond/GunclockSpringBoot/blob/master/src/main/java/com/gunman/Gunclock/GunclockService.java ------- package com.gunman.Gunclock; import java.util.List; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class GunclockService { @Autowired private GunclockRepository gunclockRepository; public List findAll() { return gunclockRepository.findAll(); } public Gunclock findOne(Long id) { // return gunclockRepository.findOne(id); // Gunclock gunclock = null; Optional gunclockOpt = gunclockRepository.findById(id); if ( gunclockOpt.isPresent() ) { return gunclockOpt.get(); } else { return null; } // gunclockOpt.ifPresent(gunclock -> {return (Gunclock)gunclock;}); } public Gunclock save(Gunclock gunclock) { return gunclockRepository.save(gunclock); } public void delete(Long id) { // gunclockRepository.delete(id); // Gunclock gunclock = null; Optional gunclockOpt = gunclockRepository.findById(id); gunclockOpt.ifPresent(gunclock -> gunclockRepository.delete(gunclock)); // gunclockRepository.delete(gunclock); } } ------- ●Controller - URL のマッピング定義 - Serviceをつなぐ - src/main/java/com/gunman/Gunclock/GunclockController.java -- https://github.com/gunman-vagabond/GunclockSpringBoot/blob/master/src/main/java/com/gunman/Gunclock/GunclockController.java --------- package com.gunman.Gunclock; import java.util.List; import java.text.SimpleDateFormat; import java.util.Date; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import gunman.GunClockBean; @Controller @RequestMapping("/gunclocks") public class GunclockController { @Autowired private GunclockService gunclockService; @GetMapping public String index(Model model) { List gunclocks = gunclockService.findAll(); model.addAttribute("gunclocks", gunclocks); return "gunclocks/index"; } @GetMapping("new") public String newGunclock(Model model) { return "gunclocks/new"; } @GetMapping("{id}/edit") public String edit(@PathVariable Long id, Model model) { Gunclock gunclock = gunclockService.findOne(id); model.addAttribute("gunclock", gunclock); return "gunclocks/edit"; } @GetMapping("{id}") public String show(@PathVariable Long id, Model model) { Gunclock gunclock = gunclockService.findOne(id); model.addAttribute("gunclock", gunclock); GunClockBean gcBean = new GunClockBean(); gcBean.setStrNewline("\n"); gcBean.setClockSize(gunclock.getSize()); String gunclockString = gcBean.getGunClock(); model.addAttribute("gunclockString", gunclockString); return "gunclocks/show"; } @PostMapping public String create(@ModelAttribute Gunclock gunclock) { Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); gunclock.setCreatedDate(sdf.format(date)); gunclockService.save(gunclock); return "redirect:/gunclocks"; } @PutMapping("{id}") public String update(@PathVariable Long id, @ModelAttribute Gunclock gunclock) { gunclock.setId(id); gunclockService.save(gunclock); return "redirect:/gunclocks"; } @PostMapping("{id}/update") public String updatePost(@PathVariable Long id, @ModelAttribute Gunclock gunclock) { gunclock.setId(id); gunclockService.save(gunclock); return "redirect:/gunclocks"; } @DeleteMapping("{id}") public String destroy(@PathVariable Long id) { gunclockService.delete(id); return "redirect:/gunclocks"; } @PostMapping("{id}/delete") public String destroyPost(@PathVariable Long id) { gunclockService.delete(id); return "redirect:/gunclocks"; } } ---------

[ ガンマンのページへ戻る ]