プログラマーの調べ物

プログラマーが調べ物をするときに役に立つサイトを作ります。

Web開発環境を準備する

必要なツール

  • Node.js
  • Gulp

Gulpがやってくれること

GulpはSassやJSの圧縮などの作業を行ってくれる「タスクランナー」と呼ばれるツールのことです。 タスクランナーにはGulpの他に、GruntやBroccoliなどがあります。

Gulpがやってくれる作業は以下のようなものです。

  • ファイル保存時の自動コンパイル
  • ファイル保存時のブラウザの自動リロード
  • コンパイルされたファイルのdistフォルダへの出力

package.json

package.jsonというファイルにはnodeでインストールできるモジュールが入っています。

{
  "name": "src",
  "version": "1.0.0",
  "description": "",
  "main": "gulpfile.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "browser-sync": "^2.11.1",
    "gulp": "^3.9.0",
    "gulp-autoprefixer": "^3.1.0",
    "gulp-changed": "^1.3.0",
    "gulp-concat": "^2.6.0",
    "gulp-csso": "^1.0.1",
    "gulp-imagemin": "^2.4.0",
    "gulp-load-plugins": "^1.2.0",
    "gulp-rename": "^1.2.2",
    "gulp-sass": "^2.1.1",
    "gulp-sourcemaps": "^1.6.0",
    "gulp-uglify": "^1.5.1",
    "gulp-watch": "^4.3.9"
  }
}

gulpfile.js

Gulpの動作はgulpfile.jsに定義されています。

基本となるgulpfile.jsは以下のようなものです。

var gulp          = require('gulp');
var $             = require('gulp-load-plugins')();
var browserSync   = require('browser-sync');


var paths = {
  "htmlSrc" : "./*.html",
  "scssSrc" : "./src/scss/**/*.scss",
  "jsSrc"   : "./src/js/*.js",
  "jsLib"   : "./src/js/lib/*.js",
  "imgSrc"  : "./src/images/**",
  "rootDir" : "./dist/",
  "imgDir"  : "./dist/images/",
  "jsDir"  : "./dist/js/"
}


gulp.task('bs', function() {
  browserSync.init({
    server: {
      baseDir: "./"
    },
    notify  : true,
    xip     : false
  });
});

gulp.task('scss', function() {
  return gulp.src(paths.scssSrc)
    .pipe($.sourcemaps.init())
      .pipe($.sass()).on('error', $.sass.logError)
      .pipe($.autoprefixer({
        browsers: ['last 2 versions']
      }))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest(paths.rootDir + 'css'))
    .pipe($.rename({
      suffix: '.min'
    }))
    .pipe($.csso())
    .pipe(gulp.dest(paths.rootDir + 'css'))
    .pipe(browserSync.reload({
      stream: true,
      once  : true
    }));
});

gulp.task('bs-reload', function() {
   browserSync.reload();
});

gulp.task('image', function() {
  return gulp.src(paths.imgSrc)
    .pipe($.changed(paths.imgDir))
    .pipe($.imagemin({
      optimizationLevel: 3
    }))
    .pipe(gulp.dest(paths.imgDir));
});

gulp.task('js', function() {
  return gulp.src([paths.jsLib, paths.jsSrc])
    .pipe($.uglify({preserveComments: 'license'}))
    .pipe($.concat('main.min.js', {newLine: '\n'})
    )
    .pipe(gulp.dest(paths.jsDir));
});

gulp.task('default', ['image', 'js', 'bs', 'scss', 'bs-reload'], function() {
  $.watch([paths.htmlSrc],function(e) {
    gulp.start("bs-reload")
  });
  $.watch([paths.scssSrc],function(e) {
    gulp.start("scss")
  });
  $.watch([paths.imgSrc],function(e) {
    gulp.start("image")
  });
  $.watch([paths.jsSrc],function(e) {
    gulp.start("js")
  });
});

このgulpfile.jsがあるディレクトリで、gulpを実行すると、gulpfile.jsの内容が実行されます。

Spring BootでBasic認証を導入するpom.xml定義

Spring Bootで Basic認証を導入するのは非常に簡単でした。

pom.xmlに以下の定義を追加します。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

なんとこれだけで、basic認証が実現できます。

f:id:sho322:20161218061434p:plain

パスワードは起動時のログに設定されますが、明示的に指定するにはapplication.propertiesに記載します。

security.user.name=demo
security.user.password=demo
security.basic.enabled=false

security.basic.enabledはデフォルトで有効になるBasic認証を有効にするか無効にするかを設定します。 基本はtrueですが、falseにするとBasic認証を向こうにすることができます。

Spring Bootでデータベースにアクセスしてみる。

Spring BootではSpring JDBCが簡単に使えます。 DBアクセスが必要なアプリケーションも非常に簡単に作ることができます。 正直、拍子抜けするくらいに。

pom.xmlに以下を追記します。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

次に、DBのデータを突っ込むBeanクラスを作りましょう。

package com.example;

import java.io.Serializable;

public class Message implements Serializable {
    private String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
    
}

そして、JDBCとの接続クラスを作ります。

package com.example;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("messages")
public class MessageController {
    
    @Autowired
    JdbcTemplate jdbcTemplate;
    
    final List<Message> messages = new CopyOnWriteArrayList<>();
    
    @RequestMapping(method = RequestMethod.GET)
    public List<Message> getMessages() {
        return jdbcTemplate.query("SELECT text FROM messages ORDER BY id", (rs, i) -> {
            Message m = new Message();
            m.setText(rs.getString("text"));
            return m;
        });
    }
    
    @RequestMapping(method = RequestMethod.POST)
    public Message postMessages(@RequestBody Message message) {
        jdbcTemplate.update("INSERT INTO messages(text) VALUES (?)",message.getText());
        return message;
    }
    
}

これでソースの準備は完了です。

Spring Bootはデフォルトの挙動として、クラスパス直下にschema.sqlが存在すると、起動時にSQOファイルを実行します。 /src/main/resources以下にdbというソースフォルダを作りましょう。

普通のフォルダではなく、ソースフォルダを作ります。 そのdbソースフォルダの下に、schema.sqlファイルを作成します。

schema.sql

CREATE TABLE messages (
    id INT PRIMARY KEY AUTO_INCREMENT,
    text VARCHAR(255)
);

同じdbフォルダに、data.sqlを作ります。
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-database-initialization.html

公式ドキュメントによると、起動時にdata.sqlに定義されているデータを挿入してくれます。

data.sql

INSERT INTO MESSAGES (text) VALUES('sample');

これでJavaを実行します。

http://localhost:8080/messages

にリクエストを飛ばすと、

json [{"text":"sample"}]

というJSONが返ってきます。

Spring BootでテンプレートエンジンThymeleafを使って画面表示

テンプレートエンジンとしてThymeleafを使ってみます。

まず、pom.xmlに以下のように依存性を追加します。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

次に、Controllerを作成します。

package com.example;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class HelloController {
    
    @RequestMapping("/hello")
    public String Hello(Model model) {
        model.addAttribute("hello", "Hello Thymeleaf World!");
        return "hello";
    }
}

このControllerで返す「Hello Thymeleaf World」を表示させるテンプレートファイルを作成します。 場所は、

/src/main/resource/templates/hello.htmlに作成します。 Spring Bootの自動設定では、TemplateResloverがビュー名につけるプレフィックスとサフィックスのデフォルト値は、それぞれ"classpath:/templates/"と".html"になるためです。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="utf-8"></meta>
  <title>example</title>
</head>
<body>
<p>
  <span th:text="${hello}"></span>
</p>
</body>
</html>

これで、http://localhost:8080/helloにリクエストをとばすと、

Hello Thymeleaf World!

と表示されます。

全てのJSPでタグライブラリを自動設定する

JSPのタグライブラリをいちいち全てのJSPファイルに書き込むのが面倒な人もいると思います。 全部に書く場合は書き漏れも心配です。

そのような人はweb.xmlに定義を追加しましょう。

<jsp-config>
    <jsp-property-group>
        <url-pattern>*.jsp</url-pattern>
        <page-encoding>UTF-8</page-encoding>
        <include-prelude>/WEB-INF/include.jsp</include-prelude>
    </jsp-property-group>
</jsp-config>

この定義を追加して、/WEB-INF/include.jspを作ります。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

そうすると、最初にinclude.jspで定義した内容が読み込まれて設定されます。

http://otndnld.oracle.co.jp/document/products/wls/docs103/webapp/web_xml.html#wp1071166

jsp-config 要素は、Web アプリケーション内の JSP ファイルのグローバル コンフィグレーション情報を提供するために使用します。 2つの下位要素 taglib および jsp-property-group があります。

jsp-property-groupとは、複数のファイルをグループ化して、それらのファイルにグローバル プロパティ情報を提供できるようにするためのものです。 このように記述されたすべてのファイルは JSP ファイルと見なされます。

include-preludeというのは、JSPの先頭にインクルードするファイルのURIを指定します。JSPの先頭にincludeディレクティブを指定するのと同じ動作になります。

http://software.fujitsu.com/jp/manual/manualfiles/M090097/B1WS0331/03Z200/B0331-02-07-05-17.html

JSPのページエンコーディングを設定して文字化けを解消する

こんな感じで、文字化けが発生してしまった。

f:id:sho322:20161210182115p:plain

最初はこんな感じで書いていました。 これを変更していきます。」

<html>
<body>
    <h2>Hello World!</h2>
    <ul>
        <li><a href="<c:url value='/echo' />">エコーアプリケーションへ</a></li>
    </ul>
</body>
</html>

上のJSPを以下のように変更しました。

<%@page pageEncoding="UTF-8"%>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Hello JSP!</title>
</head>
<body>
    <h2>Hello World!</h2>
    <ul>
        <li><a href="<c:url value='/echo' />">エコーアプリケーションへ</a></li>
    </ul>
</body>
</html>

すると、このように文字化けを解消することができました。

f:id:sho322:20161210182131p:plain

参考>

http://www.atmarkit.co.jp/ait/articles/0412/25/news006.html

https://ja.netbeans.org/docs/techinfo/javasourceencoding.html

MacにDockerをインストールする

HomebrewでDockerをインストールします。

インストールコマンド

以下のコマンドでDockerをインストールします。

$ brew cask install virtualbox
$ brew install docker
$ brew install docker-machine
$ brew cask install docker-toolbox

インストールの確認をします。

$ virtualbox --help
Oracle VM VirtualBox Manager 5.1.8

$ docker -v
Docker version 1.12.3, build 6b644ec

$ docker-machine -v
docker-machine version 0.8.2, build e18a919

仮想マシンを作成する

$ docker-machine create --driver virtualbox sample-docker

$ docker-machine ls
NAME            ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER    ERRORS
sample-docker   -        virtualbox   Running   tcp://192.168.99.100:2376           v1.12.3   

仮想マシンsshで接続

以下のコマンドでDockerに接続できます。

$ docker-machine ssh sample-docker

Docker HubからOSのイメージをダウンロードします。

$ docker pull centos:7

イメージの確認をします。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              7                   0584b3d2cf6d        4 weeks ago         196.5 MB

イメージを基にコンテナを作成

$ docker create -it --name centos7 centos:7

コンテナの確認は以下です。

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
9fae2f4431f8        centos:7            "/bin/bash"         39 seconds ago      Created                                 centos7

起動中のコンテナにアタッチします。

$ docker start 9fae2f4431f8
$ docker attach 9fae2f4431f8
[root@9fae2f4431f8 /]#

コンテナの生成と起動を同時に行うのは

docker run [option] イメージ名[:タグ名] [引数]

です。

--nameでコンテナ名を指定します。

色々インストールして、環境を作っていきます。

# yum -y install mysqld