Minemalize

新米エンジニア奮闘記

使用中のポートをキル

たまにあるやつ

springとかdjangoとかで、落としたサーバーのプロセスがポートに残っちゃってるやつをキルする方法です。 Macの方法。Winはわかりません。

lsof -i:1234(適当なポート番号)

出てきたプロセスPIDをキルする。

kill 1234

以上。

参考ウェブサイト

テックノート – [Mac] 8080番ポートをkillする方法

SQLで最近使ったもの

備忘録。
SQLは勉強するのだるくて、ずっと後回しにしているせいで、分からないことが多すぎる。

datetimeのカラムから、年月だけを検索条件にしたい場合

DATE_FORMAT(created_at, '%Y%m') = '201807'

datetimeって、数字だけで引っ張ってこれるもんだと思ってたら、そうでもないんですね。 これで、「createed_at」が2018年7月のレコードだけ引っ張ってこれます。

特定の文字列を含むものを検索したい場合

name LIKE '%java%'

これでnameカラムに「java」という文字を含むレコードを引っ張ってこれます。
LIKE 'java'ってやったら同じ挙動をするものだと思ってたら全然違った。

IEでjavaアプリが起動しないときの対処法

対応ケース

  • ウチのシステム、javaで動いてるっぽいんですけど、なんか動かすと文字化けしたページが表示されるだけで、起動しないんですよねー。みてもらえますかー?

しらんがな。

対応方法

インターネットオプション

  1. インターネットオプションを開く
  2. セキュリティタブを開く
  3. 「セキュリティを表示または変更するゾーンを選択してください。」欄で、信頼済みサイトをクリック、直下のサイトボタンを押下。
  4. 該当サイトURLを入力して追加ボタンを押下。閉じる。
  5. 適応ボタンを押下。

互換性表示設定

  1. IE右上の歯車ボタンをクリック、互換性表示設定をクリック。
  2. 該当のURLを入力して追加ボタンを押下。閉じる。

起動しました。

ちなみに、僕じゃない人がやってたのを横で見てただけです。

Django公式チュートリアルを完成させた話

なぜDjangoなのか

このまえ、Spring bootをいじっていて、やっぱりウェブアプリづくりって楽しいよなーと思ったので、せっかくだから最近気になってるpythonで書けるフレームワークDjangoを触ってみることにしました。

数あるフレームワークの中でDjangoを選んだのは、ただ一番流行ってそうだから。

開発環境

チュートリアル触ってみての感想

いいなーと思ったところ

やっぱりpythonのコードは簡潔。

  • そのおかげで、コードが書きやすい。見やすい。チュートリアルだと、ミスタイプも多く発生してしまうから、ミスにすぐ気づけるのは、本当にありがたい。

テンプレートエンジンを選ぶときに迷わないで済む。

  • Spring bootのときは、thymeleaf以外にも選択肢があるっぽくて、なんか話し合ってた経緯があった。(俺は参画していないので知らない)

勝手に作ってくれる管理サイトが優秀。

  • 今開発してるSpring bootの件が、後々、管理CMSも作ってくれみたいな流れになりそうなんだけど、そういうのにも柔軟に対応できるってすごい。

テスト機能すげえ

  • これは、もしかしたらspring bootでもできるのかもしれないけど、使ったことないから感動した。今の仕事は、基本一生テストしてるような現場なので、こういうのもっと使えばいいのにとか思っちゃう。

微妙だなーと思ったところ

  • なんか文字列系みたいな感じで、カッコが多すぎて理解しずらい部分がいっぱいあった。というか、理解していない。時間があるときに他のチュートリアルを眺めつつ、理解を深める感じになると思う。

今後

ざっくり触って、まだ全然理解が及んでいないまま、半ば写経的に実施した部分もある。 次は、Qiitaの作ってみた系を適当にあさってみて、もう少し実践的なものを作って見ようと思う。

さぁ始めましょう | Django documentation | Django

SQLで、情報が片方のテーブルにあって、片方のテーブルにないレコードを取り出す

LEFT JOIN で IS NULL を使ったら思ったように情報を取れなかった

連結のされ方によっては、下記の書き方だと両方あるレコードも引っ張ってきちゃうみたい。

SELECT ta.hoge as ahoge, tb.hoge as bhoge
FROM table_a ta
LEFT JOIN table_b tb
ON ta.hoge = tb.hoge
AND tb.hoge is NULL

NOT INをつかう

下記のようにしたらちゃんと絞込ができました。

SELECT ta.hoge
FROM table_a ta
WHERE ta.hoge NOT IN(
SELECT tb.hoge
FROM table_b tb
)

Spring bootでメールフォームの実装

何故Spring bootなのか

自社のHP開発で使ったからです。

何故メールフォームなのか

僕が担当した箇所だからです。

開発環境

仕様について

アプリの仕様はこんな感じ。

  • 入力内容は、「メールアドレス・名前・性別・問い合わせ内容」の3つ。入力のバリデーションは無し。
  • DBに情報を残すといったことは今回はなし。
  • 画面遷移は下記の感じ。
    1. 入力画面
    2. 入力内容の確認画面
    3. 管理者のメールアドレスに入力内容の送信し、完了画面へ遷移

プロジェクトを作る

実際の業務開発では、Backlogのgitからプルして、Mavanプロジェクトとして置き換えて… (ここは、実は地味に1時間くらい躓きました。プロジェクトを右クリック =>実行 を見ると、実行の構成とか書いてあって「全然起動しねーじゃねぇか!」ってなってました。) ということをしていたのですが、今回は、全部自分でやるので、プロジェクトを作るところからはじめます。

  1. 下記の方法で、新しいプロジェクトを作成。適当にプロジェクト名を決める。

    • パッケージエクスプローラ内右クリック => 新規 => プロジェクト
    • Spring boot => Spring スタータープロジェクト
  2. 会社では、Mavenを使ってたけど、なんかgradleのほうが、いろいろ情報が載ってて便利そうだし、練習も兼ねてgradleを選択。

  3. とりあえず、参考サイトをみつつ、初期ライブラリの選択。別に後からgradleとかMavenとか弄れば追加できるっぽいから、今回必要そうなものだけ。

    • コア => Devtools: ホットデプロイとかできるようになる。セーブすると勝手に立ち上げなおしてくれて便利。
    • テンプレートエンジン => Thymeleaf: テンプレートエンジン。会社でやってるときは、「なんでフロントまわりまでやらなきゃならないんだ、死ね」って思ったけど、割と最近は友達になってきてる。
    • Web => Web: Spring MVCでアプリが作れるようになるやつ。ウェブアプリ系ならたぶん必須。
  4. プロジェクトが出来たら起動テスト。問題なし。

フォームを作る。

ハロワとか一応やったけど、面倒なので、書くのは省略。メールフォームのクラスから書きます。

package com.hatenablog.threeroots.model;

public class MailForm{
  private String mail;
  private String name;
  private String sex;
  private String content;

  //getter & setter
}

Formの仕様的に全部Stringで取得したほうが楽そうだから、とりあえずコレで。改善の余地、あり。 これを、modelというpackageを作って入れる。

コントローラーを作る。

この程度だったらやらなくてもいいんだろうけど、一応controllerってパッケージを作ってその中に作る。

package com.hatenablog.threeroots.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.hatenablog.threeroots.model.MailForm;
import com.hatenablog.threeroots.service.SendMailService;

@Controller
public class ContactController {

    @Autowired
    private SendMailService sendMailService;

    @GetMapping("/")
    public String index(Model model){
        return "index";
  }
    @PostMapping("/confirm")
    public String confirm(@ModelAttribute MailForm mailForm, Model model){
        model.addAttribute("mailForm", mailForm);
        return "confirm";
  }

    @PostMapping("/complete")
    public String complete(@ModelAttribute MailForm mailForm){
        sendMailService.send(mailForm);
        return "complete";
  }
}

送信実行部分(SendMailService)を作る。

メールの送信方法には、いくつかやり方があるようだけど、一番簡単そうだったspring-boot-starter-mailを使用した。

実装の前に、必要な設定をする。

1. build.gradleに依存関係の追加

compile('org.springframework.boot:spring-boot-starter-mail')

2. application.ymlの追記

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=hogehoge@gmail.com
spring.mail.password=password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

ちなみに、ここの記法を、なぜか変な感じにしていたせいで、ビルドエラーを吐いていた。基本コピペでやってたから、どっかのサイトが多分間違ってるか、僕が勘違いして変な情報を貼り付けた。

実装してみる

serviceパッケージを作って実装。

package com.hatenablog.threeroots.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Service;

import com.hatenablog.threeroots.model.MailForm;

@Service
public class SendMailService{

    @Autowired
    private MailSender mailSender;

    public void send(MailForm mailForm) {
        SimpleMailMessage msg = new SimpleMailMessage();
        msg.setFrom(mailForm.getMail());
        msg.setTo("hogehoge@hogehoge.com"); // 管理者アドレス
        msg.setSubject("お問い合わせがありました");
        msg.setText(makeContent(mailForm));
        mailSender.send(msg);
        }

    public String makeContent(MailForm mailForm){
            return "名前: " + mailForm.getName() + "\n" +
            "性別: " + mailForm.getSex() + "\n" +
            "問い合わせ内容: " + mailForm.getContent();
    }
}

フロント画面を作る

超簡単につくる。

入力画面

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org">
    <div>
        <form action="/confirm" method="post">
            <div>お名前</div>
            <div>
                <input type="text" id="name" name="name">
            </div>
            <div>メールアドレス</div>
            <div>
                <input type="email" id="mail" name="mail">
            </div>
            <div>
                <input type="radio" name="sex" id="sex" value="男性" checked="checked" />男性
                <input type="radio" name="sex" id="sex" value="女性" />女性
            </div>
            <div>
                <textarea id="content" name="content" rows="3" cols="">お問い合わせ内容</textarea>
            </div>
            <div>
                <input type="submit" value="送信する">
            </div>
        </form>
    </div>
</html>

普通にフォームで受け取った内容をpostで送るだけ。ここは見たまま。

確認画面

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
    <div th:object="${mailForm}">
        <form action="/complete" method="post">
            <div><span th:text="*{name}"></span></div>
            <div><span th:text="*{mail}"></span></div>
            <div><span th:text="*{sex}"></span></div>
            <div><span th:utext="${mailForm.content} ? ${#strings.replace(mailForm.content, T(java.lang.System).getProperty('line.separator'), '&lt;br /&gt;')}"></span><div>
            <div>
                <input type="hidden" th:field="*{name}" value="*{name}">
                <input type="hidden" th:field="*{mail}" value="*{mail}">
                <input type="hidden" th:field="*{sex}" value="*{sex}">
                <input type="hidden" th:field="*{content}" value="*{content}"/>
                <input type="submit" value="上記内容で送信する">
            </div>
          </form>
    </div>
</html>

こっちが、割と作ってるときに詰まりました。理由として

  • th:text=で変数を入力するときには、objectを設定しなければならない。今回は上部階層のdivタグで設定したけど、"${contactForm.name}"みたいにも書ける。
  • completeのServiceに値を受け渡すためにhiddenで値をもう一度受け渡し直さなければならない。このことに気づかず、ずっとNULLのメールを送りまくってた。
  • 改行情報をHTMLで表示する際に、改行タグに変換しなければならなかった。これは、ぐぐったらthymeleaf側で頑張れそうだったので、表側で処理。

完了画面

完了しました。

もはやhtmlですらないけど、画面表示よりも、メールが送られているが大事なのでこれで良い。

テストしてみる

送信できました。 とりあえず今回はここまで。

今後の課題

  1. バリデーションの設定
  2. フロント実装時、bootstrapを使ってみる

参考にしたもの

Spring Bootでメール送信する方法 | ホームページ制作のサカエン(墨田区) SpringBoot + JPA + Thymeleafで簡単なCRUDを作る①~HelloWorldまで~
Spring Boot でメール送信する Web アプリケーションを作る ( その15 )( Thymeleaf を利用して HTML メールを送信する2 ) - かんがるーさんの日記

iOSの証明書で詰まった話

事象

iOSのAppからウェブサーバー上にあるAPIを叩きにいくとエラーがでる。

とりあえずエラーの原因を探る

Xcode起動で、

  1. ツールバー [window] => [Devices and Simulators]
  2. Devicesを選択 => デバッグに使用しているデバイスを右パラムConnectedから選択
  3. 画面下部の△マークみたいなのをクリック

これで本体の操作ログを出力できる。

エラーログ

APIをたたきに行くと下記のエラーコードを出しているっぽい

Error Domain=NSURLErrorDomain Code=-1012

これ、なんぞやと思って調べてみたらこんな感じ。 CFNetworkErrors.cfurlErrorUserCancelledAuthentication

解決方法

ん?認証エラー?
ってことで担当の人に聞きに行ってみたら、移行先の証明書ファイルがないのが原因っぽいってことで、新しい証明書を発行してもらって下記の実施。

  1. 発行された証明書ファイルを、Resourceなどのフォルダに格納。
  2. プロジェクトのxcodeprojを選択 => Build Phases => Copy Bundle Resources 内に該当の証明書ファイルを追加。

これで接続できました。

さらっと書いてるけど、3時間くらい読めないObjective-Cを詠んだ末のこれだったので、泣きました。

参考にしたもの

iOS Can't perform HTTP GET request -Error Domain=NSURLErrorDomain Code=-1012 - Stack Overflow
CFNetworkErrors.cfurlErrorUserCancelledAuthentication - CFNetworkErrors | Apple Developer Documentation