プログラミングBlog

日付書式変更処理をリファクタリング

目的

Javaの学習をしていたら、改善できる箇所を見つけたため、リファクタリングを行う
リファクタリング対象は日付書式を英語書式に変更するクラス

条件① 月によって日にちは変わるが、1-31日あるとする
条件② 入力データの書式は yyyy年MM月dd日 とする
(変換例) 2021年11月7日 ⇨ 7th-Nov-2021

リファクタリング対象

import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

class ChangeDateFormat {

    // 日付の英語表記一覧
    private static final Map<String, String> dateNotations_En = new HashMap<>()
    {
        {
            put("01", "1st");
            put("02", "2nd");
            put("03", "3rd");
            put("04", "4th");
            put("05", "5th");
            put("06", "6th");
            put("07", "7th");
            put("08", "8th");
            put("09", "9th");
            put("10", "10th");
            put("11", "11th");
            put("12", "12th");
            put("13", "13th");
            put("14", "14th");
            put("15", "15th");
            put("16", "16th");
            put("17", "17th");
            put("18", "18th");
            put("19", "19th");
            put("20", "20th");
            put("21", "21st");
            put("22", "22nd");
            put("23", "23rd");
            put("24", "24th");
            put("25", "25th");
            put("26", "26th");
            put("27", "27th");
            put("28", "28th");
            put("29", "29th");
            put("30", "30th");
            put("31", "31st");
        }
    };

    // 月の英語表記一覧
    private static final Map<String, String> monthNotions_En = new HashMap<>()
    {
        {
            put("01", "Jan");
            put("02", "Feb");
            put("03", "Mar");
            put("04", "Apr");
            put("05", "May");
            put("06", "Jun");
            put("07", "Jul");
            put("08", "Aug");
            put("09", "Sep");
            put("10", "Oct");
            put("11", "Nov");
            put("12", "Dec");
        }
    };
    
    // 日付書式を日本語表記から英語表記に変換
    public String DateConvertJpToEn(Date inputDate) {

        String result = "";

        String date = new SimpleDateFormat("yyyy年MM月dd日").format(inputDate).replaceAll("[^0-9]", "");

        Integer strLen = date.length();

        result += dateNotation_En.get(date.substring(strLen - 2)) + "-";

        result += monthNotion_En.get(date.substring(strLen - 4, strLen - 2)) + "-";

        result += date.substring(0, strLen - 4);

        System.out.println(result);
        
        return result;
    }
}

リストを定数化する

日付と月の英語表記一覧は不変な値なため変更できないよう読み取り専用にする

    // 月の英語表記一覧
    private static final Map<String, String> monthNotions_En = Collections.unmodifiableMap(new HashMap<>()
    {
        {
            put("01", "Jan");
            put("02", "Feb");  
            //  省略
        }
    });

SimpleDateFormat

SimpleDateFormatはスレッドセーフではないため、複数のスレッドから使用する場合は意図した値とならない
スレッドセーフなAPIに変更する
入力データに時間は必要がないためjava.time.LocalDateを使用する

public String DateConvertJpToEn(LocalDate inputDate) {

String date = DateTimeFormatter.ofPattern("yyyy年MM月dd日").format(inputDate).replaceAll("[^0-9]", "");

参考サイト

日付フォーマットは同期化されません。スレッドごとに別のフォーマット・インスタンスを作成することをお薦めします。複数のスレッドがフォーマットに並行してアクセスする場合は、外部的に同期化する必要があります。

docs.oracle.com  

リストメモ
qiita.com

GitHub

github.com

docker oracle memo

docker oracle memo

公式Repository clone

git clone https://github.com/oracle/docker-images.git

oracle database 本体 DL

zipファイルが自動で解凍されてしまう場合
faq.cybozu.info

build方法

./buildDockerImage.shの名前が変更されているようなので以下のコマンドとなる。

./buildContainerImage.sh -v 19.3.0 -e -I

memory変更

defaultだとmemoryの不足でエラーとなるため、増やしておく
f:id:Tokuty:20211009081825p:plain

container内の時刻変更

docker exec コンテナ名 date

VScode Remote containerでの時間同期の話とDockerのtimezone設定方法 - プログラミング学習のメモ書き

password変更

docker exec oracle ./setPassword.sh password

ログイン

sqlplus SYSTEM/password@ORCLCDB

参考サイト

qiita.com

WSL2 + Docker Hub 環境作成時のまとめ  

WindowsでDocker環境作成時のまとめ

手順

① WSL2 install
② Docker Hub install

①WSL2

以下のサイトから必要な機能をDownLoadする
docs.microsoft.com

手順 1 - LinuxWindows サブシステムを有効にする
手順 5 - WSL 2 を既定のバージョンとして設定する
手順1から手順5までを行う

②DockerHub

Docoker Hnbを以下のサイトからDownLoad
hub.docker.com

トラブルシューティング

メモリ

  • WSL2のメモリ使用量を変更する
    デフォルトだと6GBのメモリを消費するため、CPU100%超える。。。
    メモリの設定を変更しておく
    zenn.dev

  • 自動起動しないよう変更

①Docker Desktopの歯車マークをクリック
②Start Docker when you log in チェックマークをはずす
③Apply & Restart押下

f:id:Tokuty:20210918185207p:plain

Docker + Gradle + Spring Boot でWarファイル作成後にTomcatにDeproy

①Spring BootをGradleでビルド、Warファイルを作成する
TomcatにWarファイルをDeproyする
前回の続きです
Vscode + Docker + Spring Boot 構築

必要なファイル

以下の記事でアプリを構築しておく
Vscode + Docker + Spring Boot 構築
github.com

以下を確認しておく
ない場合は作成する

ServletInitializer.java

package com.example.demo;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

public class ServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(DemoApplication.class);
    }

}

別のtomcatコンテナにDeproyする場合に必要となる

build.gradle

plugins {
    id 'org.springframework.boot' version '2.5.4'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
    id 'war'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
    mavenCentral()
}

war {
    archiveName 'helloworld.war'
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
    useJUnitPlatform()
}

Warファイル作成用のpluginが追加されているかの確認
id 'war'

dependenciesにspring boot に内蔵されているtomcatを使用しない設定が追加されているかの確認
この記述がないとtomcatが多重起動してしまう
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'

手順① Spring BootをGradleでビルド、Warファイルを作成する

  • gradleがinstallされていることの確認

gradle -v

  • tomcatのversionを調べる

Deproy先のtomcatのversionを合わせるため

./gradlew dependencies

9.0.52であることを確認
Deproy先のtomcatのversionを9.0.52とする

+--- org.springframework.boot:spring-boot-starter-tomcat:2.5.4
|    |    +--- jakarta.annotation:jakarta.annotation-api:1.3.5
|    |    +--- org.apache.tomcat.embed:tomcat-embed-core:9.0.52
|    |    +--- org.apache.tomcat.embed:tomcat-embed-el:9.0.52
|    |    \--- org.apache.tomcat.embed:tomcat-embed-websocket:9.0.52
|    |         \--- org.apache.tomcat.embed:tomcat-embed-core:9.0.52
  • build.gradleを修正する

warファイルの名前を変更するため以下を追加

war {
    archiveName 'helloworld.war'
}
  • Warファイルを作成する
    gradle build

build/libs/直下にwarファイルが作成される
build/libs/helloworld.war

手順② TomcatにWarファイルをDeproyする

Deproy先のTomcatサーバーは以下を使用
tokuty.hatenablog.com

  • git clone
git clone git clone https://github.com/TakushiTokuyama/Docker.git

起動するまでは記事を参照

  • WarファイルをDeproyする

さきほど作成したhelloworld.warTomcatwebapps/にコピーして設置する

参考サイト

www.youtube.com

www.it-mure.jp.net

arcanum.hatenablog.com

Vscode + Docker + Gradle + Spring boot 構築

javaの環境をRemote - Containers(Vscode拡張機能)で構築

②Dockerコンテナ内でSpring Bootを構築

前提条件

docker version

構成

vscode + docker + spring の最終的な構成となります。

.
└── demo
    ├── HELP.md
    ├── bin
    │   ├── main
    │   │   ├── application.properties
    │   │   ├── com
    │   │   │   └── example
    │   │   │       └── demo
    │   │   │           ├── DemoApplication.class
    │   │   │           ├── ServletInitializer.class
    │   │   │           └── controller
    │   │   │               └── HelloController.class
    │   │   └── templates
    │   │       └── index.html
    │   └── test
    │       └── com
    │           └── example
    │               └── demo
    │                   └── DemoApplicationTests.class
    ├── build.gradle
    ├── gradle
    │   └── wrapper
    │       ├── gradle-wrapper.jar
    │       └── gradle-wrapper.properties
    ├── gradlew
    ├── gradlew.bat
    ├── settings.gradle
    └── src
        ├── main
        │   ├── java
        │   │   └── com
        │   │       └── example
        │   │           └── demo
        │   │               ├── DemoApplication.java
        │   │               ├── ServletInitializer.java
        │   │               └── controller
        │   │                   └── HelloController.java
        │   └── resources
        │       ├── application.properties
        │       ├── static
        │       └── templates
        │           └── index.html
        └── test
            └── java
                └── com
                    └── example
                        └── demo
                            └── DemoApplicationTests.java

必要なファイル

今回はRemote - Containers(Vscode拡張機能)で環境構築していくため、特に必要なし

手順① Remote-Container

  • Vscodeのコマンドパレット起動

ctrl + shift + p もしくは command + shift + p

  • Remote - containerの機能を使ってjava環境作成

Remote-Containers:Add Development Container Configuration Files選択
f:id:Tokuty:20210911084242p:plain

Java選択
f:id:Tokuty:20210911084308p:plain

11選択
f:id:Tokuty:20210911084425p:plain

16選択
f:id:Tokuty:20210911084436p:plain

Gradleを選択
f:id:Tokuty:20210911084446p:plain

以下のフォルダとファイルが作成される
f:id:Tokuty:20210911092103p:plain

devcontainer.jsonにextensionを追加
"vscjava.vscode-spring-initializr"
spring boot 作成時に使う

 "extensions": [
        "vscjava.vscode-java-pack",
        "vscjava.vscode-spring-initializr"
    ],

右下に表示されたReopen Containerを選択
もしくは右下の緑色の箇所をクリックしReopen Containerを選択
f:id:Tokuty:20210911084457p:plain

左下に下記の表示が出たらコンテナ内にアクセス成功
f:id:Tokuty:20210911084505p:plain

手順② Spring Boot 作成

  • Vscodeのコマンドパレット起動
    ctrl + shift + p もしくは command + shift + p

create java project選択
f:id:Tokuty:20210911085639p:plain

spring boot 選択
f:id:Tokuty:20210911092357p:plain

Gradle Project選択
f:id:Tokuty:20210911092619p:plain

2.5.4選択
f:id:Tokuty:20210911092651p:plain

Java選択
f:id:Tokuty:20210911092711p:plain

ルートパッケージ名 src/main/java直下の名前を選択
f:id:Tokuty:20210911093101p:plain

プロジェクト名
f:id:Tokuty:20210911093158p:plain

今回はWarを選択   
f:id:Tokuty:20210911093220p:plain

11を選択し、開発環境のJava versionと合わせる
f:id:Tokuty:20210911093240p:plain

spring webThymeleaf選択
f:id:Tokuty:20210911093312p:plain

workspaceを作成したい場所を選択
f:id:Tokuty:20210911093402p:plain

openを選択すると作成したプロジェクトを開く
f:id:Tokuty:20210911093430p:plain

以下のフォルダとファイルが作成される
f:id:Tokuty:20210911093529p:plain

  • controllerとviewを追加

以下のパスに追加する
src/main/java/com/example/demo/controller/HelloController.java

HelloController.java

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HelloController {
    @RequestMapping("/hello")
    public String index(){
        return "hello";
    }
}

index.html

以下のパスに追加する
src/main/resources/templates/index.html

<html xmlns:th="http://www.thymeleaf.org">

<h1>helloworld</h1>

</html>
  • VscodeにDebug構成を追加する

構成の追加
f:id:Tokuty:20210912115819p:plain

Java
f:id:Tokuty:20210912115840p:plain

launch.json追加
f:id:Tokuty:20210912115853p:plain

  • Spring boot実行

デバッグなしで実行
f:id:Tokuty:20210912115957p:plain

起動
f:id:Tokuty:20210912120021p:plain

http://localhost:8080 にアクセス
f:id:Tokuty:20210912120040p:plain

GiitHub

github.com

次回

次回は
①ビルドツール Gradleを使用して、warファイルを作成
TomcatでwarファイルをDeproyする

Deproy場所は以下を使用
Tomcat + nginx でReverseProxsyServer

参考サイト

blog.kondoumh.com

Vscode + Docker + Nginx + Tomcat でhelloworld

DockerにてNginxとTomcatを構築。
Nginxはリバースプロキシサーバー、 Tomcatアプリケーションサーバーとしてhelloworldを表示させる
今回はNginxコンテナとTomcatコンテナ、二つ作成する

前提条件

  • Vscode上で作成

  • Dockerが使える環境が必要です

  • install 確認コマンド

docker version

構成

docker-compose build 前の段階では以下の構成となります

.
├── docker-compose.yml
├── nginx
│   ├── Dockerfile
│   └── conf.d
│       └── nginx.conf
└── tomcat
    └── Dockerfile

最終的な構成となります。

.
├── docker-compose.yml
├── nginx
│   ├── Dockerfile
│   ├── conf.d
│   │   └── nginx.conf
│   └── log
│       ├── access.log
│       ├── error.log
│       ├── tomcat_access.log
│       └── tomcat_error.log
└── tomcat
    ├── Dockerfile
    ├── log
    │   ├── catalina.2021-09-06.log
    │   ├── host-manager.2021-09-06.log
    │   ├── localhost.2021-09-06.log
    │   ├── localhost_access_log.2021-09-06.txt
    │   └── manager.2021-09-06.log
    └── webapps
        └── sample
            └── helloworld.html

必要なファイル

  • docker-compose.yml
  • Dockerfile(nginx)
  • nginx.conf(nginx)
  • Dockerfile(tomcat)

docker-compose.yml

services:
  nginx:
    build:
      context: ./nginx
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d/
      - ./nginx/log:/var/log/nginx
    ports:
      - 80:80

  tomcat:
    build:
      context: ./tomcat
    volumes:
      - ./tomcat/webapps:/usr/local/tomcat/webapps
      - ./tomcat/log:/usr/local/tomcat/logs
    ports:
      - 8080:8080

リバースプロキシの設定用にconf.dを修正する必要があるため、マウントしておきます。
ログも何かと必要となるため、マウント。
webapps配下はアプリケーションのデプロイ場所となるためこちらも同様

dockerfile(nginx)

FROM nginx

RUN apt-get update && apt-get install -y vim

EXPOSE 80

RUN rm -rf /etc/nginx/conf.d/

COPY ./conf.d/nginx.conf /etc/nginx/conf.d/
  • defaultのnginx設定を削除して作成した設定に入れ替える
RUN rm -rf /etc/nginx/conf.d/

COPY ./conf.d/nginx.conf /etc/nginx/conf.d/

nginx.conf

server {
    listen 80;
    server_name localhost;

    access_log /var/log/nginx/tomcat_access.log;
    error_log /var/log/nginx/tomcat_error.log;
    location / {
        proxy_pass http://host.docker.internal:8080;
    }
}
  • リバースプロキシの設定

http://localhost:80(nginx)でリクエストした場合に、
http://localhost:8080(tomcat)にリクエストを転送するようにする
dockerの場合はlocalhostではなくhost.docker.internalでないと読み込んでくれないため、注意。 めちゃハマりました。

proxy_pass http://host.docker.internal:8080;

Dockerfile(tomcat)

FROM tomcat:9.0.52

RUN apt-get update && apt-get install -y vim

EXPOSE 8080

versionはデプロイしたいアプリに合わせると良い。
今回はhelloworldを表示させたいだけ、なので気にしなくても良いが、こちらを使用

RUN apt-get update && apt-get install -y vim
何かしらのエラーがあった場合、設定を確認していく必要があるため、vimを入れておきます
vimにはだいぶ助けられました

手順

* image作成

docker-compose build

* コンテナ起動

docker-compose up -d

* http:localhost:80にアクセス

f:id:Tokuty:20210906203926p:plain

何もデプロイするものがないため404 not foundが返却されているが
tomcatの表示がされている。

http://localhost:80(nginx)にアクセスするとnginx.confで設定したproxy_pass http://localhost:8080(tomcat)に転送されていることの確認ができました

マウントしたログで確認しても良い

* webapps直下にhelloworld.htmlを設置する

webapps/sample/helloworld.html

helloworld.html

<h1>helloworld</h1>

* コンテナを作り直して起動する
停止と削除
docker-compose down

構築
docker-compose build

起動
docker-compose up -d

* http:localhost:80/helloworld.htmlにアクセスする

f:id:Tokuty:20210906205432p:plain

無事に表示できました!!

コンテナ内の設定を確認したい場合は以下のコマンドでコンテナ内に入り、vimで確認していきましょう

docker-compose exec tomcat bash

GitHub

https://github.com/TakushiTokuyama/Docker/tree/develop/ReverseProxyServer

参考サイト

qiita.com www.jcsc.co.jp

C# .NET dockerで環境構築

普段はWindowsを使ってますが、Mac mini環境でもC#をさわってみたくなりました。
最初から環境を作成するのはとても大変なため、dockerで環境構築してみることに。

前提条件

  • DockerHubのアカウント登録後、Docker for Mac を install

hub.docker.com

  • install 確認コマンド

docker version

構成

最終的にsampleフォルダ内にプロジェクトが作成されます

.
├── Dockerfile
├── docker-compose.yml
└── sample

必要なファイル

  • docker-compose.yml
  • Dockerfile

docker-compose.yml

version: '3'
services:
  web:
    build: .
    ports:
      - 5000:5000
    tty: true
    volumes:
      - ./sample:/sample
  • コンテナを起動させ続ける

tty: true

  • データの永続化

- ./sample:/sample

localのsampleフォルダ内にコンテナのsampleフォルダをマウントさせる
これをすることで、コンテナを削除してもデータを保存しておくことができる

Dockerfile

FROM mcr.microsoft.com/dotnet/core/sdk:3.1

RUN mkdir /sample
WORKDIR /sample
  • 公式のimageを使用

FROM mcr.microsoft.com/dotnet/core/sdk:3.1

hub.docker.com

手順

  • image作成

docker-compose build

  • コンテナを作成 起動

docker-compose up -d
ここでlocalにsampleフォルダが作成されます

  • コンテナ内に入る

docker-compose exec web bash

  • プロジェクト作成

dotnet new mvc

  • 起動

dotnet run

エラー

warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
      Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {36020275-9c58-4ee1-bc60-9c7050c13fa7} may be persisted to storage in unencrypted form.
crit: Microsoft.AspNetCore.Server.Kestrel[0]
      Unable to start Kestrel.
System.InvalidOperationException: Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date.
To generate a developer certificate run 'dotnet dev-certs https'. To trust the certificate (Windows and macOS only) run 'dotnet dev-certs https --trust'.

コンテナからアクセスできるようにエンドポイントの設定をする

  • appsettings.Development.jsonに設定を追加

"urls": "http://*:5000;"

http://localhost:5000にアクセスして確認

f:id:Tokuty:20210828181457p:plain

参考サイト

qiita.com
qiita.com
mseeeen.msen.jp

GitHub

github.com