アイキャッチ画像の位置をタイトルの下に変更する方法

WordPress

WordPressの記事にアイキャッチ画像を設定している人は多いかと思います。

多いというよりも、もはや設定するのは常識ですね。

記事の見栄えも良くなるので、読者の興味を引きやすいです。


僕もWordPressでブログを立ち上げて記事を投稿していくなかで、”そろそろアイキャッチ設定するかなー”と思い、アイキャッチ画像をアップロードしたのですが、アイキャッチ画像がタイトルの上に表示されました。

アイキャッチ画像のデフォルト位置

好みかもしれませんが、”アイキャッチ画像はタイトルの下でしょ”って思いませんかね?

なんとなく、タイトルの上に画像だと記事の収まりが悪いといいますか。。。


では修正しよう!と思っても、この位置を変更するのは、WordPressに慣れていない人や、PHP初心者の方には難しい部分があります。


今回は、WordPress・PHP初心者の方もアイキャッチ画像位置の変更がおこなえるように、変更方法を説明していきます。



アイキャッチ画像とは

アイキャッチ画像とは、その名の通りアイ(ユーザの目線を)キャッチ(引き付ける)画像です。


ユーザが検索結果から様々な記事をみていく中で、”この記事を読んでみよう”と興味を持ってもらう必要があります。

 

そういった目的の中では、文字よりも画像の方が効果が大きいです。

アイキャッチ画像の設定は必須と思った方がよく、よりユーザ集客に効果的な画像を設定することが重要になります。


アイキャッチ画像位置を変更する

アイキャッチ画像の位置を修正するには、記事を構成するPHPファイルを修正する必要があります。


PHPファイルはWordPressのダッシュボードから修正可能ですが、今回は以下の流れでPHPファイルの修正をおこないます。


  1. SSHでサーバに接続して修正ファイルをバックアップ
  2. WordPressでPHPファイルを修正する

SSHでサーバに接続して修正ファイルをバックアップ 

PHPファイルを修正する際、バックアップを行うことを推奨します。

もし、修正を間違えるとWebページ自体が表示されなくなる可能性があります。


この場合、PHPファイルをバックアップしていれば元に戻すことは可能ですが、バックアップしていなければ元に戻すことができなくなる可能性があります。


という訳で、バックアップをおこないます。

僕のブログのWordPressは、ロリポップレンタルサーバ上で動作しているのですが、SSHが無料で使えます。


なので、WinScpを使用してSSHでサーバに接続します。

  • WordPress:WordPress5.2
  • テーマ:Sparkling

SSHでサーバに接続し、テーマ(Sparkling)のcontent-single.phpを確認します。

content-single.phpの格納場所

バックアップするファイルは以下になります。

  • フォルダ:/wp-content/themes/sparkling/template-parts
  • ファイル:content-single.php

パスをみて気が付くかもしれませんが、バックアップするのはテーマ(Sparkling)の中のPHPファイルになります。

このファイルを作業しているパソコンにダウンロードしておきましょう。


これで、バックアップ完了です。

アイキャッチ画像の位置変更作業で元に戻す必要が出てきた場合は、バックアップしたファイルに戻してください。

アイキャッチ画像位置を変更する

それではアイキャッチ画像の位置を変更してみます。


content-single.phpを直接してもよいのですが、今回はWordPressのダッシュボードから修正をおこないます


今回は、以下のように変更をおこないます。

  • アイキャッチ画像をタイトルの下にする

content-single.phpの修正画面をWordPressのダッシュボードで開きます。

まずは、テーマの更新ウィンドウをひらきます。

テーマエディタのひらきかた

テーマエディタが開いたら、右メニューでcontent-single.phpを選択します。

ダッシュボードでcontent-singleをひらく

アイキャッチ画像は、以下のコードで表示しています。

6行目から12行目の部分です。

<article id="post-<?php the_ID(); >" <?php post_class(); ?>
    <?php
    $featured_image_args = array(
        'class' =&amp;amp;gt; 'single-featured',
    );
    if ( is_page_template('page-fullwidth.php') ) {
        the_post_thumbnail(
       '    sparkling-featured-fullwidth', $featured_image_args);
    } else {
        the_post_thumbnail(
            'sparkling-featured', $featured_image_args);
    }
    >


the_post_thumbnailでアイキャッチ画像を表示しています。

このコードをタイトルの下に移動すればよいです。

正確には、メタ情報(作成日時、作成者、など)の下に移動します。


変更後のcontent-single.phpは以下になります。(一部抜粋)

<div class="post-inner-content">
<header class="entry-header page-header">
<h1 class="entry-title "><?php the_title(); ?></h1>
<div class="entry-meta">
<?php sparkling_posted_on(); ?>
<?php
    $categories_list = 
        get_the_category_list(esc_html__( ', ', 'sparkling' ) );
    if ( $categories_list && sparkling_categorized_blog() ) :
    ?>
    <span class="cat-links"><i class="fa fa-folder-open"></i>
    <?php printf( esc_html__(
        ' %1$s', 'sparkling'), $categories_list ); ?>
    </span>
    <?php endif; // End if categories ?>
    <?php if ( get_edit_post_link() ) : ?>
    <?php
        edit_post_link(
            sprintf(
            /* translators: %s: Name of current post */
            esc_html__( 'Edit %s', 'sparkling' ),
            the_title(
                '<span class="screen-reader-text">"', '"</span>', false )
            ),
            '<i class="fa fa-edit"></i><span class="edit-link">',
            '</span>'
        );
 ?>
<?php endif; ?>
</div><!-- .entry-meta -->
</header><!-- .entry-header -->
<?php
    $featured_image_args = array(
        'class' => 'single-featured',
    );
    if ( is_page_template( 'page-fullwidth.php' ) ) {
        the_post_thumbnail(
            'sparkling-featured-fullwidth', $featured_image_args);
    } else {
        the_post_thumbnail(
           'sparkling-featured', $featured_image_args);
    }
?>
<div class="entry-content">

34行目から43行目までがアイキャッチ画像の表示部分です。

その直前がメタ情報、直後がコンテンツ本体です。


最後に、ファイルを更新ボタンを押下すれば更新完了です。

content-single.phpの更新方法

変更後のアイキャッチ画像位置を確認

ここまでの作業でアイキャッチ画像の位置は変更されています。


既にアイキャッチ画像が設定されている記事を確認してみてください。

アイキャッチ画像がタイトルの下(正確にはメタ情報の下)になっていれば、更新完了です。

アイキャッチ画像位置の変更後

固定ページのアイキャッチ画像位置を変更する


「content-single.php」の修正をおこなうと投稿ページのアイキャッチ画像位置はタイトル下になるのですが、固定ページのアイキャッチ画像位置は変更されません。
変わらず、タイトルの上にアイキャッチ画像が表示されます。


固定ページのアイキャッチ画像位置を修正するには、「content-page.php」を修正する必要があります。
「content-single.php」の時と同じようにテーマエディタと「content-page.php」をひらきます。

content-page.phpをテーマエディタでひらく

<h1>~</h1>を囲んでいる<head>~</head>の上にサムネイル表示処理が記載されていると思います。
以下のように。

<?php
if ( is_page_template( 'page-fullwidth.php' ) ) {
    the_post_thumbnail(
        'sparkling-featured-fullwidth', array(
            'class' => 'single-featured',
        )
    );
} else {
    the_post_thumbnail(
        'sparkling-featured', array(
            'class' => 'single-featured',
        )
    );
}
?>

<div class="post-inner-content">
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
    <header class="entry-header page-header">
        <h1 class="entry-title"><?php the_title(); ?></h1>
    </header><!-- .entry-header -->

これは以下のように修正します。
<head>~</head>の下に、サムネイル画像表示処理を記載するように変更します。

    <header class="entry-header page-header">
        <h1 class="entry-title"><?php the_title(); ?></h1>
    </header><!-- .entry-header -->
<?php
if ( is_page_template( 'page-fullwidth.php' ) ) {
    the_post_thumbnail(
        'sparkling-featured-fullwidth', array(
            'class' => 'single-featured',
        )
    );
} else {
    the_post_thumbnail(
        'sparkling-featured', array(
            'class' => 'single-featured',
        )
    );
}
?>

上記のように対応することで、固定ページもタイトルの位置にアイキャッチ画像が表示されるようになります。


月毎・カテゴリ毎・タグ毎ページのアイキャッチ画像位置を変更する


ここまでの説明でPHPファイルを修正しとしても、月毎・カテゴリ毎・タグ毎といった、集約ページのアイキャッチ画像位置は修正されていません。
集約ページのアイキャッチ画像位置を修正するには、「content.php」を修正する必要があります。

content.phpを修正

集約ページは、選択した月やカテゴリ・タグが<h1>~</h1>で使用されます。
タイトルは<h2>~</h2>となります。


なので、サムネイル画像を<h2>~</h2>の下に移動します。


変更前は以下のPHPファイルになります。
<h2>~</h2>の上にサムネイル画像表示処理が記載されています。

        <?php
        if ( is_page_template( 'page-fullwidth.php' ) ) {
            the_post_thumbnail(
                'sparkling-featured-fullwidth', array(
                    'class' => 'single-featured',
                )
            );
        } else {
            the_post_thumbnail(
                'sparkling-featured', array(
                    'class' => 'single-featured',
                )
            );
        }
        ?>
    </a>
<div class="post-inner-content">
    <header class="entry-header page-header">
        <h2 class="entry-title"><a href="<?php the_permalink(); ?>" rel="bookmark"><?php the_title(); ?></a></h2>

サムネイル画像表示処理を、<h2>~</h2>の下に変更します。

<div class="post-inner-content">
    <header class="entry-header page-header">

        <h2 class="entry-title"><a href="<?php the_permalink(); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
        <?php
        if ( is_page_template( 'page-fullwidth.php' ) ) {
            the_post_thumbnail(
                'sparkling-featured-fullwidth', array(
                    'class' => 'single-featured',
                )
            );
        } else {
            the_post_thumbnail(
                'sparkling-featured', array(
                    'class' => 'single-featured',
                )
            );
        }
        ?>

上記のように対応することで、集約ページもタイトルの位置にアイキャッチ画像が表示されるようになります。


まとめ

いかがでしたでしょうか?

アイキャッチ画像位置の変更できたかと思います。

まとめ
  • アイキャッチ画像は、デフォルトでタイトルの上に表示される。
  • アイキャッチ画像の位置を変更するには、PHPファイルを修正する必要あり。

僕のWordPressのテーマはSparklingですが、他テーマも基本的な変更方法は同じです。

アイキャッチ画像の活用にお役に立てればと思います。


それではまた!



Google Fonts + 日本語 を使いたい!プラグインを使って、Webフォントを導入。

WordPress

以前、会社のプロジェクトでWebアプリケーションを開発した際、お客さんから言われたことがあります。


フォントはWebフォントにしといてね。よろしくー。


当時の僕は、”Webフォントってなんだろう?”と思いながらも、”了解しましたー!”と調子よく返事して、会社に戻ってからWebフォントについて調べて、アプリケーションに反映しました。


ブログを書いていたらふと当時のことを思い出しまして、”WordPressにWebフォントってどうやって入れるんだろう?”という疑問も出てきました。


今回は、WordPressにWebフォントを導入する手順を紹介していきます。


Webフォントとは

まず、Webフォントとは何でしょう?


まず、通常のフォント指定で作成されたHTMLは、そのHTMLを表示しているマシンにインストールされているフォントで表示します。

Webフォントの基本

パソコンやスマートフォンで表示する際に使用するフォントは、あくまで各クライアントにインストールされているフォントでおこないます。


この方法では、クライアントの状態(フォントがインストールされていない、など)によっては、指定したフォントで表示されない場合があります。

意図したフォントで表示されない

Webフォントは、この問題を解決しています。

インターネット上からフォントをクライアント端末にダウンロードするので、クライアントの状態に依存しないことになります。


GoogleFonts + 日本語とは

Webフォントは比較的新しい技術です。

そのため、日本語に対応しているWebフォントが少ないのが現状です。

しかも、日本語に対応していないWebフォントを使用すると、画面表示が遅くなってしまう恐れがあります。


そこで使用するのがGoogleFonts + 日本語 です。


GoogleFonts + 日本語は、その名の通り日本語に対応しているため、画面表示速度の心配をする必要がありません。


プラグインを使用してGoogleFonts + 日本語を導入

それでは実際にフォントをGoogleFonts + 日本語に変更しましょう。


スタイルシートを直接修正する方法でも変更可能ですが、折角ですのでWordPressプラグインを使用します。

使用するプラグインはEasy Google Fonts です。

Easy Google Fontsは、無料で使えるWebフォントを簡単に導入できるプラグインです。


WordPressのブロック毎にも指定できるので、ブロックによってフォントを変更したい時も便利です。


通常のWordPressプラグインと同様に、プラグインを検索してインストールをおこないます。

Easy Google Fontsのインストール

インストールが完了したら有効化します。

Easy Google Fontsの有効化

外観 → テーマを選択し、使用中テーマのカスタマイズボタンを押下します。

テーマのカスタマイズ

左メニューでTypographyを選択します。

Typographyの選択

Default Typography のボタンが表示されているので、ボタンを押下します。

Default Typographyの選択

変更ウィンドウが表示されます。

まずは ParagraphsのフォントをWebフォントに変更します。

Paragraphsは、ビューエディターの段落になります。

HTML構文としては、<p>~</p>タグで囲まれている部分となります。


では実際に、フォントをWebフォントに変更してみましょう。

今回はさわらびゴシックに変更してみます。

変更方法は簡単で、「FontFamily」を「SawarabiGothic」に変更するのみです。

ParagraphsのフォントをWebフォントに変更

変更すると、右に表示されているサンプル記事が変更したWebフォントになります。

変更前と変更後のフォントは以下のように変わります。

変更前は以下です。

デフォルトテーマの表示

さわらびゴシックへの変更後は以下です。

さわらびゴシックの表示

ちょっと解り辛いですが、文書部分のフォントのみがさわらびゴシックに変更されています。

見出し部分のフォントは変更されていません。

文書ブロックについてのみフォントがWebフォントに変更されたという事がわかります。


最後に上部の公開ボタンを押下すれば、公開中記事についても変更したフォントが反映されます。

フォントの公開

ここまでの内容で指定したブロックにWebフォントを適用することができます。


説明では段落ブロックのみにWebフォントを適用しましたが、フォントは統一した方が見栄えは良いです。

そのため、よほどの理由がない限りは、全ての修正対象ブロックのフォントを同じWebフォントに変更しておいた方がよいでしょう。

紹介したEasy Google Fontsは、フォントだけでなく文字間隔の変更や文字装飾も可能です。

使いこなして、ブログデザインを納得いくものにカスタマイズしていきましょう。

Easy Google Fontsに設定を追加する

Easy Google Fontsでデフォルトで準備されていないブロック についても、 修正対象に追加することでWebフォントを指定できるようになります。

例えばリストです。

Easy Google Fonts にはリスト(<ul><li>)の修正コントローラがありません。

そのため、デフォルトではリストについてWebフォントが指定できません。


以下のようにフォントがそろわない形になってしまいます。

フォントが不揃いの場合

ブロックの追加は、Easy Google Fontsのプラグイン編集からおこないます。


まずは、WordPressダッシュボード左メニューからプラグインを選択し、Easy Google Fontsのsettingを押下します。 

Easy Google Fontsの編集

Easy Google Fonts の設定画面がひらきます。

この画面で、リストのHTMLタグであるul li を追加していきます。

Control Nameは任意の名称でいいです。

自身がメンテナンスしやすい名前にしておけばよいと思います。

Add CSS Selectors にul・li といったHTMLタグを入力します。


入力が完了し、Manage Font Controlsに入力した内容が表示されていれば完了です。

Easy Google Fontsの入力完了後画面

次に、入力したHTMLタグに対してデフォルトタグで実施したようにWebフォントを指定します。

外観→カスタマイズから、左メニューのTypographyを選択します。

ブログスタマイズ画面の左メニュー

そうすると「Theme Typography」というメニューが新たに表示されています。

先ほどのプラグイン編集でデフォト以外のHTMLタグを追加したので、このメニューが表示されるようになりました。

Theme Typograpyのメニュー表示

Theme Typograpyを押下すると、先ほど追加した2つの編集設定が表示されています。


あとは Default Typograpy の設定で実施した内容と同じように、Font Familyの内容を変更すれば完了です。

Theme Typograpyの追加要素表示

まとめ

このように、Webフォントを使用することのメリットと、Webフォントの反映方法がお解り頂けたかと思います。

まとめ
  • Webフォントを指定すれば、フォントがクライアントによって変わってしまうリスクがなくなる。
  • WordPressのWebフォント指定は、プラグインであるEasy Google Fontsを使った方がいい。
  • Easy Google Fontsで、全てのHTMLタグにWebフォントが適用されるようにしよう。

それではまた!



SpringBatchを始めよう!開発環境からサンプル実行まで

SpringFrameWork

皆さんは、Javaのバッチ処理をどのように構築しているでしょうか?

僕は、社内で用意しているライブラリを使用してバッチ処理をコーディングすることが多いです。

しかし、Web画面はSpringMVCをよく使っています。


SpringBatchの存在は前々から知から知っていたのですが、社内ライブラリを使ったバッチの参考処理が数多くあるので、なかなかSpringBatchに手を出せずにいました。

しかも、画面はSpringMVCを使っているのに、なぜバッチはSpringBatchを使わないのかという疑問を日々感じていました


今回は、SpringBatchを使うための開発環境構築とサンプルの実行までを解説していきます。

これからSpringBatchを使おうと思っている人の参考になればと思います。


SpringBatchとは

SpringBatchとは、バッチのJavaアプリケーションフレームワークです。

Springがもつ概念として「DI」「AOP」「トランザクション管理」がありますが、SpringBatchも同様の概念で構築されています。


まあ、ピンとくるようなこないような。。。ですが、まずは環境を作って動かしましょう!


環境情報

WindowsマシンにSpringBatchの開発環境を構築します。

今回は、STS(Spring Tools Suite)を使用します。

  • OS:Windows7
  • STS:Eclipse spring-tool-suite-4-4.2.1

STSの構築

STS(Spring Tools Suite)は、Spring用のIDEとなります。

今回は、EclipseベースのIDEを使用します。

Spring Tools 4 for Eclipseのダウンロード

Springのサイトから「Spring Tools 4 for Eclipse」をダウンロードします。

Spring Tools 4

Spring Tools 4 for Eclipseのダウンロード画面

ダウンロードが成功すると、以下のZIPファイルがダウンロードフォルダに保存されます。

  • spring-tool-suite-4-4.2.1.RELEASE-e4.11.0-win32.win32.x86_64.zip

SpringToolSuite4の設定

ダウンロードしたZIPファイルを解凍し、「SpringToolSuite4.exe」をダブルクリックしてSpringToolSuiteを起動します。

SpringToolSuite4の場所

通常のEclipseと同様にワークスペースの設定ウィンドウがひらきます。

ワークスペースフォルダを設定して「Launch」ボタンを押下します。

ワークスペースの設定


ウィンドウが起動すると気が付くと思いますが、英語版のままです。

日本語化するためには、まずは以下サイトから日本語化プラグインをダウンロードします。

MargeDoc Project

日本語化ツールのダウンロード


ダウンロードが成功すると、以下のZIPファイルがダウンロードフォルダに保存されます。

  • pleiades-win.zip

ZIPファイルを解凍して「setup.exe」をダブルクリックすると、日本語化のプラグインインストールが開始されます。

日本語化プラグインのsetup.exe

setup.exeをクリックすると、日本語化プラグインの設定ウィンドウが表示されます。

「日本語化するアプリケーション」で「SpringToolSuite4.exe」を選択します。

「eclipsec.exe」ではありません。

「日本語化するアプリケーション」を選択すれば、他2つのパスは自動的に設定されます。

パスが設定されていることを確認したら、「日本語化する」ボタンを押下します。

日本語化プラグインの設定ウィンドウ

完了ウィンドウが表示されれば成功です。

日本語化かの完了ウィンドウ

再度、 SpringToolSuiteを起動します。

念のためクリーン起動(SpringToolSuite4.exe -clean.cmd)で起動します。

日本語化が完了した画面

メニューが日本語で表示されていれば、日本語化は成功です。

プロジェクトの作成から実行まで

プロジェクトの作成

まずはプロジェクトの作成をおこないます。

ファイル → 新規 → プロジェクト を選択します。

プロジェクトの作成

新規プロジェクトウィンドウで、Spring Boot → Spring 入門コンテンツのインポート を選択して、「次へ」を押下します。

新規プロジェクトウィンドウ

インポートするテンプレートで「Batch Processing」を選択して「完了」ボタンを押下します。

コンテンツのインポート

パッケージエクスプローラーにプロジェクトが表示されたら、プロジェクトの作成完了です。

SpringBathプロジェクト作成完了

プロジェクトが2つできていますが、以下の2種類になります。

  • 完成版プロジェクト:gs-batch-processing-complete
  • テンプレートプロジェクト:gs-batch-processing-initial

プロジェクトの構成設定

完成版プロジェクトである「gs-batch-processing-complete」の構成設定をおこないます。

以下の手順でメインクラスを設定するのみです。

プロジェクトを右クリックで選択してメニューをひらき、実行 → 実行の構成 を選択します。

プロジェクトの実行の構成選択

実行構成ウィンドウがひらいたら、左メニューで「Javaアプリケーション」→ 「新規構成」を選択します。

右ペーンの「メイン・クラス」で検索ボタンを押下し「Application – Hello」クラスを選択します。

選択すると、「メイン・クラス」に「hello.Appication」が表示されるので、「実行」ボタンを押下します。


Application-helloのメイン・クラス設定

プロジェクトの実行

プロジェクトの構成で「実行」ボタンを押下したタイミングで、ビルドとプログラム実行がおこなわれます。

Spring Tool Suiteのコンソールに以下文字列が表示されたら、プログラム実行の成功です。



  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.4.RELEASE)

2019-05-06 01:57:42.101  INFO 9804 --- [           main] hello.Application                        : Starting Application on Ntomo-PC with PID 9804 (C:\SpringTools\workspace\gs-batch-processing-complete\target\classes started by Ntomo in C:\SpringTools\workspace\gs-batch-processing-complete)
2019-05-06 01:57:42.145  INFO 9804 --- [           main] hello.Application                        : No active profile set, falling back to default profiles: default
2019-05-06 01:57:45.698  INFO 9804 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2019-05-06 01:57:45.709  WARN 9804 --- [           main] com.zaxxer.hikari.util.DriverDataSource  : Registered driver with driverClassName=org.hsqldb.jdbcDriver was not found, trying direct instantiation.
2019-05-06 01:57:46.901  INFO 9804 --- [           main] com.zaxxer.hikari.pool.PoolBase          : HikariPool-1 - Driver does not support get/set network timeout for connections. (feature not supported)
2019-05-06 01:57:46.947  INFO 9804 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2019-05-06 01:57:49.255  INFO 9804 --- [           main] o.s.b.c.r.s.JobRepositoryFactoryBean     : No database type set, using meta data indicating: HSQL
2019-05-06 01:57:50.046  INFO 9804 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : No TaskExecutor has been set, defaulting to synchronous executor.
2019-05-06 01:57:50.574  INFO 9804 --- [           main] hello.Application                        : Started Application in 11.109 seconds (JVM running for 13.556)
2019-05-06 01:57:50.577  INFO 9804 --- [           main] o.s.b.a.b.JobLauncherCommandLineRunner   : Running default command line with: []
2019-05-06 01:57:50.754  INFO 9804 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [FlowJob: [name=importUserJob]] launched with the following parameters: [{run.id=1}]
2019-05-06 01:57:50.827  INFO 9804 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [step1]
2019-05-06 01:57:50.988  INFO 9804 --- [           main] hello.PersonItemProcessor                : Converting (firstName: Jill, lastName: Doe) into (firstName: JILL, lastName: DOE)
2019-05-06 01:57:50.989  INFO 9804 --- [           main] hello.PersonItemProcessor                : Converting (firstName: Joe, lastName: Doe) into (firstName: JOE, lastName: DOE)
2019-05-06 01:57:50.990  INFO 9804 --- [           main] hello.PersonItemProcessor                : Converting (firstName: Justin, lastName: Doe) into (firstName: JUSTIN, lastName: DOE)
2019-05-06 01:57:50.991  INFO 9804 --- [           main] hello.PersonItemProcessor                : Converting (firstName: Jane, lastName: Doe) into (firstName: JANE, lastName: DOE)
2019-05-06 01:57:50.991  INFO 9804 --- [           main] hello.PersonItemProcessor                : Converting (firstName: John, lastName: Doe) into (firstName: JOHN, lastName: DOE)
2019-05-06 01:57:51.023  INFO 9804 --- [           main] hello.JobCompletionNotificationListener  : !!! JOB FINISHED! Time to verify the results
2019-05-06 01:57:51.033  INFO 9804 --- [           main] hello.JobCompletionNotificationListener  : Found <firstName: JILL, lastName: DOE> in the database.
2019-05-06 01:57:51.035  INFO 9804 --- [           main] hello.JobCompletionNotificationListener  : Found <firstName: JOE, lastName: DOE> in the database.
2019-05-06 01:57:51.036  INFO 9804 --- [           main] hello.JobCompletionNotificationListener  : Found <firstName: JUSTIN, lastName: DOE> in the database.
2019-05-06 01:57:51.036  INFO 9804 --- [           main] hello.JobCompletionNotificationListener  : Found <firstName: JANE, lastName: DOE> in the database.
2019-05-06 01:57:51.037  INFO 9804 --- [           main] hello.JobCompletionNotificationListener  : Found <firstName: JOHN, lastName: DOE> in the database.
2019-05-06 01:57:51.043  INFO 9804 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [FlowJob: [name=importUserJob]] completed with the following parameters: [{run.id=1}] and the following status: [COMPLETED]
2019-05-06 01:57:51.085  INFO 9804 --- [       Thread-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2019-05-06 01:57:51.101  INFO 9804 --- [       Thread-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

「gs-batch-processing-complete」は、「resources」に格納されている「sample-data.csv」を標準出力するサンプルです。

そのため、”JILL””JOE”といった名前が標準出力されています

まとめ

いかがでしたでしょう?

まずはSpringBatchの開発環境が構築できたかと思います。

次回から、構築した環境を使用して様々なアプリケーションの構築を行っていきたいと思います。

 

それではまた!




Javaの文字列連結は速度を考慮して、「+」ではなく「StringBuffer」を使うべき

Java

今回は、一般的に言われているJavaの文字列連結について紹介します。


僕は都内でSIerをやっているのですが、新人時代のJava研修で教わったことがあります。


 

文字列連結する場合は「+」演算子を使わずに「StringBuffer」を使え!

 


Java研修の時は”へー。そーなんだ。”くらいでしか考えていませんでした。

理由は性能(スピード)だと教えてもらったかと思いますが、ちゃんと理解できず。。。です。

「百聞を一見し如かず」ということで、実際に検証してみようと思います。


環境情報

実際にJavaのプログラムを作って、僕のローカルマシンで動かす形で検証します。

ローカルマシンのスペックは以下になります。

  • OS:Windows7 Professional
  • CPU:Inter Pentium 2.3GHz
  • メモリ:4.00 GB
  • Java:1.7.0_02

あんまりいいパソコン使ってないんですよね。

でもまあ、検証するには十分な環境かと思います。

「+」演算子で文字列をする

まずは、「+」演算子で文字列を連結した場合のプログラムを作ります。

実際に作成したプログラムは以下となります。

“add+数字”の文字列追加を5万回繰り返すプログラムです。

全て、「+」演算子で文字列を連結しています。

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

public class PlusConnect {
     public static void main(String[] args){
        System.out.print("start\r\n");

        //-- 日付フォーマット作成 --//
        SimpleDateFormat fmt = 
            new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
        String str = "";

        //-- 文字列の連携を指定回数だけ実行 --//
        for (int lc = 0; lc &amp;amp;lt; 50000; lc++) {
            str = str + "add" + Integer.toString(lc);

            //-- 一定の間隔でログ出力 --//
            if (lc % 10000 == 0) {
                Date now = new Date();
                System.out.print(fmt.format(now) + 
                ":" + Integer.toString(lc) + 
                "回目のループ終了\r\n");
            }
        }

        //-- 文字列長を表示して終了 --//
        System.out.print(
            "文字列長=" + Integer.toString(str.length()));
        System.out.print("end\r\n");
     }
}

上記プログラムの実行結果は以下になります。

hoge>java -Xms256M -Xmx256m PlusConnect
start
2019/04/28 21:43:53.487:0回目のループ終了
2019/04/28 21:43:55.066:10000回目のループ終了
2019/04/28 21:43:59.256:20000回目のループ終了
2019/04/28 21:44:05.239:30000回目のループ終了
2019/04/28 21:44:12.774:40000回目のループ終了
文字列長=388890
end

コメントが解り辛くて申し訳ないです。

「0回目のループ終了」が開始日時で、「40000回目のループ終了」が終了日時です。

約19秒経過していることがわかります。


「StringBuffer」で文字列を連結する

次に、「StringBuffer」で文字列を連結した場合のプログラムを作ります。

実際に作成したプログラムは以下となります。

「StringBuffer」の「append」を使用して文字列を連結するプログラムです。

「+」演算子と同様に、文字列追加を5万回繰り返すプログラムです。

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

public class BufferConnect {
    public static void main(String[] args){
        System.out.print("start\r\n");

        //-- 日付フォーマット作成 --//
        SimpleDateFormat fmt = 
            new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
        StringBuffer buf = new  StringBuffer();

        //-- 文字列の連携を指定回数だけ実行 --//
       	for (int lc = 0; lc <= 50000; lc++) {
            buf = buf.append("add");
            buf = buf.append(Integer.toString(lc));

            //-- 一定の間隔でログ出力 --//
            if (lc % 10000 == 0) {
                Date now = new Date();
                System.out.print(fmt.format(now) + ":" + 
                    Integer.toString(lc) + "回目のループ終了\r\n");
            }
        }

        //-- 文字列長を表示して終了 --//
        System.out.print("文字列長=" + 
            Integer.toString(buf.length()) + "\r\n");
        System.out.print("end\r\n");
    }
}

上記プログラムの実行結果は以下になります。

hoge>java -Xms256M -Xmx256m BufferConnect
start
2019/04/28 21:55:55.539:0回目のループ終了
2019/04/28 21:55:55.620:10000回目のループ終了
2019/04/28 21:55:55.651:20000回目のループ終了
2019/04/28 21:55:55.658:30000回目のループ終了
2019/04/28 21:55:55.664:40000回目のループ終了
文字列長=388890
end

こちらは、1秒もかかっておらず約0.5秒ですね。


結果

性能では以下の結果となりました。


  • 「+」演算子で文字列を連結する=19秒
  • 「StringBuffer」で文字列を連結する=0.5秒

38倍の差です。

あきらかに「StringBuffer」を使用した方が性能がよいということがわかります。

コーディングの手間を考えると+演算子の方が簡単なので、ついつい手を抜いてしまうんですが、ある程度の数の文字列を連結する場合は、StringBuffrerを使用するべきです。


しかし上記は、ループを5万回繰り返すといった極端な検証の結果となります。

単純な文字列結合では、気にする程度の差は出なかったりします。


まとめ

やっぱり、Java研修で教えてもらった内容は間違っていなかったという結論になりました。


まとめ
  • 性能を考えると、確実にStringBufferを使った方がいい。
  • +演算子とStringBufferは、約40倍の差が出る(場合がある)。
  • “ループ内で文字列結合する場合はStringBufferを使う!”と認識しておけば問題なさそう!

という訳で、皆さん、文字列連結する場合は面倒くさがらずにStringBufferを使うようにしましょう!


それではまた!



WordPressでブログを立ち上げてからまずやること。メタとフッターをまずは修正しとこう。

ロゴ

こんにちは。

さくさくTECHブロガーの「さく」です。


今回は、WordPressでブログを始めてから最初に修正しておいた方がいいと僕が思っている部分について、修正方法を紹介しておきます。

僕は、ブログをみてくれた人に“このブログはWordPressで作ってるなー”と思われるのが何となく嫌なんです。

しかも、”テーマはSparklingだなー”とか思われると赤面してしまいます。

なので、できるだけ、WordPressで作ってます感は消していきたい。

 

今回は、最低限の修正必要箇所として『メタ』『フッター』の修正方法を紹介します。

でもまあ、WordPress使っているかなんて、みる人がみたらすぐに解っちゃうんですけどね。

メタを修正する

まずはメタです。

僕のWordPressデーマは「Sparkling」なのですが、サイドバーに以下のメタ情報が表示されます。

使用しているテーマによっては、上図のようなメタが表示されます。

う~ん。。。WordPressで作ってます感がバリバリ出てます。

“WordPress.org”なんてもってのほか!

という訳で、メタ情報を修正することにします。

メタ情報は全て削除することも可能です。

その場合は、テーマの編集から可能ですが、今回は削除ではなく編集をおこないます。

修正するファイルを特定する

メタを修正するにはPHPファイルを修正する必要があります。

まずは修正するPHPファイルを特定します。

本ブログはレンタルサーバ上にWordPressがインストールされており、SSHが使用できる状態になっているので、WinScpでサーバに接続します。

WordPressのルートフォルダ

WordPressの画面を構成する要素は、「wp-includes」に格納されている「default-widgets.php」で定義されています。

default-widgets.phpの格納フォルダ

「default-widgets.php」をひらいてみます。

※ソースコードの可読性を上げるために改行していますので、実際のPHPファイルとは少しレイアウトが異なります。


/**
 * Widget API: Default core widgets
 *
 * @package WordPress
 * @subpackage Widgets
 * @since 2.8.0
 */

/** WP_Widget_Pages class */
require_once(ABSPATH.WPINC.'/widgets/class-wp-widget-pages.php');

/** WP_Widget_Links class */
require_once(ABSPATH.WPINC.'/widgets/class-wp-widget-links.php');

/** WP_Widget_Search class */
require_once(ABSPATH.WPINC.'/widgets/class-wp-widget-search.php');

/** WP_Widget_Archives class */
require_once(ABSPATH.WPINC.'/widgets/class-wp-widget-archives.php');

/** WP_Widget_Media class */
require_once(ABSPATH.WPINC.'/widgets/class-wp-widget-media.php');

/** WP_Widget_Media_Audio class */
require_once(
  ABSPATH.WPINC.'/widgets/class-wp-widget-media-audio.php');

/** WP_Widget_Media_Image class */
require_once(
  ABSPATH.WPINC.'/widgets/class-wp-widget-media-image.php');

/** WP_Widget_Media_Video class */
require_once(
  ABSPATH.WPINC.'/widgets/class-wp-widget-media-video.php');

/** WP_Widget_Media_Gallery class */
require_once(
  ABSPATH.WPINC.'/widgets/class-wp-widget-media-gallery.php');

/** WP_Widget_Meta class */
require_once(ABSPATH.WPINC.'/widgets/class-wp-widget-meta.php');

/** WP_Widget_Calendar class */
require_once(ABSPATH.WPINC.'/widgets/class-wp-widget-calendar.php');

/** WP_Widget_Text class */
require_once(ABSPATH.WPINC.'/widgets/class-wp-widget-text.php');

/** WP_Widget_Categories class */
require_once(
  ABSPATH.WPINC.'/widgets/class-wp-widget-categories.php');

/** WP_Widget_Recent_Posts class */
require_once(
  ABSPATH.WPINC.'/widgets/class-wp-widget-recent-posts.php');

/** WP_Widget_Recent_Comments class */
require_once(
  ABSPATH.WPINC.'/widgets/class-wp-widget-recent-comments.php');

/** WP_Widget_RSS class */
require_once(ABSPATH.WPINC.'/widgets/class-wp-widget-rss.php');

/** WP_Widget_Tag_Cloud class */
require_once(
  ABSPATH.WPINC.'/widgets/class-wp-widget-tag-cloud.php');

/** WP_Nav_Menu_Widget class */
require_once(ABSPATH.WPINC.'/widgets/class-wp-nav-menu-widget.php');

/** WP_Widget_Custom_HTML class */
require_once(
  ABSPATH.WPINC.'/widgets/class-wp-widget-custom-html.php');

「require_once」が並んでいるだけですね。

このPHPファイルは、各ウィジェットを読み込むだけの役割であることがわかります。

肝心のメタですが、22行目の「class-wp-widget-media.php 」に定義されているので、このファイルが修正対象のファイルとなります。

PHPファイルを修正する

修正するファイルが特定できたので、実際に修正をおこないます。

修正するファイルは、「widgets」フォルダの「class-wp-widget-media.php 」になります。

class-wp-widget-media.phpの格納場所

/**
 * Widget API: WP_Widget_Meta class
 *
 * @package WordPress
 * @subpackage Widgets
 * @since 4.4.0
 */

/**
 * Core class used to implement a Meta widget.
 *
 * Displays log in/out, RSS feed links, etc.
 *
 * @since 2.8.0
 *
 * @see WP_Widget
 */
class WP_Widget_Meta extends WP_Widget {

    /**
     * Sets up a new Meta widget instance.
     *
     * @since 2.8.0
     */
    public function __construct() {
        $widget_ops = array(
            'classname' => 'widget_meta',
            'description' => __('Login, RSS, WordPress.org links.'),
            'customize_selective_refresh' => true,
        );
        parent::__construct( 'meta', __( 'Meta' ), $widget_ops );
    }

    /**
     * Outputs the content for the current Meta widget instance.
     *
     * @since 2.8.0
     *
     * @param array $args Display arguments including 
     *                   'before_title', 'after_title',
     *                   'before_widget', and 'after_widget'.
     */
    public function widget( $args, $instance ) {
        $title = ! empty( $instance['title'] ) ? 
                 $instance['title'] : __( 'Meta' );

        $title = apply_filters(
            'widget_title', $title, $instance, $this->id_base );

        echo $args['before_widget'];

        if ( $title ) {
            echo $args['before_title'].$title.$args['after_title'];
        }
        ?>
<ul>
    <?php wp_register(); ?>
<li>
    <?php wp_loginout(); ?>
</li>
<li>
    <a href="<?php echo esc_url(get_bloginfo('rss2_url')); ?>">
    <?php _e('Entries <abbr title="Really Simple Syndication">RSS</abbr>'); ?>
</a>
</li>
<li>
    <a href="<?php echo esc_url(get_bloginfo( 'comments_rss2_url')); ?>">
    <?php _e('Comments <abbr title="Really Simple Syndication">RSS</abbr>'); ?>
    </a>
</li>
    <?php
    /**
     * Filters the "Powered by WordPress" text in the Meta widget.
     *
     * @since 3.6.0
     * @since 4.9.0 Added the `$instance` parameter.
     *
     */
    echo apply_filters(
        'widget_meta_poweredby',
        sprintf(
            '<li><a href="%s" title="%s">%s</a></li>',
            esc_url( __( 'https://wordpress.org/' ) ),
            esc_attr__(
'Powered by WordPress, state-of-the-art semantic personal publishing platform.'),
_x( 'WordPress.org', 'meta widget link text' )
        ),
        $instance
    );
    wp_meta();
    ?>
</ul>
    <?php

    echo $args['after_widget'];
    }

    /**
     * Handles updating settings.
     *
     * @since 2.8.0
     *
     * @param array $old_instance Old settings for this instance.
     * @return array Updated settings to save.
     */
    public function update( $new_instance, $old_instance ) {
        $instance          = $old_instance;
        $instance['title'] = 
            sanitize_text_field( $new_instance['title'] );
        return $instance;
    }

    /**
     * Outputs the settings form for the Meta widget.
     *
     * @since 2.8.0
     *
     * @param array $instance Current settings.
     */
    public function form( $instance ) {
        $instance = 
            wp_parse_args((array) $instance, array('title' => ''));
        ?>
<label for=
    "<?php echo $this->get_field_id( 'title' ); ?>">
    <?php _e( 'Title:' ); ?>
</label>
<input class="widefat" id="
<?php echo $this->get_field_id( 'title' ); ?>"
name="<?php echo $this->get_field_name( 'title' ); ?>" type="text"
value="<?php echo esc_attr( $instance['title'] ); ?>" />
<?php
    }
}

今回は「ログイン」「WordPress.org」の2つを削除します。

とはいっても後から復活させたいことがあるかもしれないので、コメントアウトすることにします。

まずは「ログイン」ですが、対象箇所は「class-wp-widget-media.php 」の57行目になります。

PHPのコメントアウトと同様に「<!– –>」で囲みます。

<!– <li><?php wp_loginout(); ?></li> –>

次に「WordPress.org」ですが、対象は60行目から82行目になります。

「 class-wp-widget-media.php 」内で動的にURLを作っていますね。

まとめコメントアウトしてしまいます。

これで作業完了です。

結果を確認する

それでは、メタ情報が修正されているかを実際の画面で確認してみます。

「ログイン」「WordPress.org」が消えていれば完了です。

修正後のメタ情報

フッターを修正する

次にフッターです。

デフォルトでは、フッターに「WordPress.org」が表示されています。

見落としがちですが、ここもしっかり修正しておきたいです。

WordPrssフッター

フッターのコピーライト表記は、修正は簡単です。

WordPressのダッシュボードから、設定 → 一般設定で「サイトのタイトル」を変更すれば、勝手に変わってくれます。

サイトのタイトル

サイトのタイトルは、ほとんどの人がブログ名に更新しているかと思います。

なので、最後にフッターを確認しておきましょう、という感じです。

まとめ

僕が考える、”まずは修正しておけ!”っていうポイントを解説しました。

まとめ
  • WordPressデフォルト表示が恥ずかしい人は、最低限、メタとフッターは修正しよう。
  • メタはPHPファイルを修正すれば変えることができる。
  • フッターのコピーライトは、サイト名を変更していれば勝手に変わってくれる。

それではまた!