環境

・SpringToolSuite4

・OpenJDK8

・Tomcat9

・debian 9.8 64bit

・Spring Boot 2.1.6

 

あると便利なツール

・DBeaver (グラフィカルDBClient)

 

学習に使用している書籍

  • Spring徹底入門
    ※Springのバージョンの関係で多々苦労するが、良い書籍だと思う。
    ※1〜3章>14章の順番で進めた方が理解しやすいかも
    ※翔泳社のHPから15章(バッチ)がダウンロードできる
  • Spring Boot 2 プログラミング入門
    ※Spring徹底入門に比べると内容は非常に浅い。
     但し、とっかかりやすくSpring徹底入門のように躓くことはなかった
    ※この本を一通り読んでからSpring徹底入門を読んだ方がよかったかも。
     

補足

・書籍(Spring徹底入門)とバージョンを合わせても書籍通りに設定しただけでは動作しない (Chapter4)。

 ⇢ どうせ動作しないならと、最新版でなんとか動作させることを試みた(なんとか動作させることができたのでgithubにあげておく)

 https://github.com/dctk/spring_mvc_template

・多々躓いたけど、ようやく Spring徹底入門が一通り終わった。

 

 

ショートカットキー(STS4)

・CTRL+SHIFT+F :コード整形

 

用語

  • Bean
    DIコンテナに登録するコンポーネント
    Bean定義の実装
  • Bean定義の方法
    DIコンテナに対応する設定ファイル/クラス
    .xml:設定ファイルベース
  • ルックアップ
    DIコンテナからBeanを取得すること
  • DIコンテナ関連のアノテーション
    @Configuration : Bean定義(Java Configクラス)につける
    @ComponentScan(スキャン対象のパッケージ名):Bean定義(Java Configクラス)につける
    @Bean:Bean定義のメソッドにつける
    @Primary:同じ型が複数ある場合、これをつけが方が選択される
    @Scope:Beanのスコープを指定する(デフォルト:prootype)
    @Component:Beanクラスにつける
    @Autowired:
  • 関連:@Qualifier("メソッド名" or 独自で作成したアノテーション名) - 同じ型が複数ある場合に挿入するクラスを明記する
    DIコンテナが管理するインスタンスはデフォルトでシングルトン
  • インスタンスのスコープ
    singleton
    prototype:毎回インスタンスを生成する
    session:HTTPSession単位でインスタンスを生成する (WebApp)
    request:リクエスト単位でインスタンスを生成する(WebApp)
    globalSession:GlobalSession単位でインスタンスを生成する(WebApp)
    application:サーブレットのコンテキスト単位でインスタンスを生成する(WebApp)
    その他:独自でスコープを定義できる

 

jarファイルの作成

  1. プロジェクト上で右クリック>Run As>Maven Install

 

MavenのJDKバージョンを指定する(pom.xml)

参考サイト:https://qiita.com/takahitonara/items/769c8775183b13c631c5

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	
	...

	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
		...
	</build>
</project>

 

 Webモジュールのバージョンを変更する

 プロジェクト右クリック>Properties>Project Facets>Dynamic Web Module [任意のバージョンを指定]

 

application.propertiesの共通設定一覧

 

JPA+Postgres定型句

  • application.properties
    • ##jpa
      spring.jpa.database=POSTGRESQL
      # コンソールログにログを出力する場合は「true」を指定する
      spring.jpa.show-sql=true
      # エンティティからテーブルを自動生成する場合は「create」を指定する
      spring.jpa.hibernate.ddl-auto=create
      
      ## PostgreSQL
      spring.datasource.url=jdbc:postgresql://localhost:5432/DB名
      spring.datasource.username=ユーザ名
      spring.datasource.password=パスワード
  • pom.xml
    • <dependency>
      	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
      <dependency>
      	<groupId>org.postgresql</groupId>
      	<artifactId>postgresql</artifactId>
      </dependency>
       

エラメッセージ表示定型句(要:th:objectの中)

  • 一括表示
    • <div th:each="error: ${#fields.detailedErrors()}" th:text="${error.message}" />	​
       
  • 個別表示
    • <div th:if="${#fields.hasErrors('名前')}" th:errors="*{名前}" />
  • エラー時のスタイル設定
    • <input ... th:errorclass="クラス名" />

 

Validationエラー時のメッセージをカスタマイズする方法 

 

MessageSource

  • messages.propertisの作成(../resources/messages.properties)
    mymessage="hello world"​


  • messages.propertisの補足(ロケール毎に分けて作成できる)
    例:日本語
    messages_ja.properties

 

トラブルシューティング

  • CHKJ3000E:WAR Validation Failed ... が発生する
・対処方法1

web.xml>右クリック>validate をクリックしてみる

・対象方法2

Project>Cleanを試してみる

・対処方法3

web.xmlを作り直してみる


上記の何れかで解決すると思う

原因不明

 

  • Pivotal tc Server Integration for Eclipseが存在しない

参考サイト:https://qiita.com/9pid/items/949d195d16651abf4905

1. Help>Dashboard>IDE EXTENTIONS>Pivotal tc Server Developer Edition>[Check]>Install

※Dashboardがなければ「Eclipse Marketplace」から「Pivotal」と検索して対象のパッケージをインストールする

 

  • .おかしくなったらとりえず実行してみること

 ・プロジェクトのクリーン

 ・Maven clean

 ・Maven update

 

  • 文字化け(filterを追加しても文字化けが治らなかった場合の対処)
JSPを以下のようにしたらEclipse上でも文字化けが発生しなくなった


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
	</head>
<body>
</body>
</html>

 

  • @taglib〜でエラーが出るときの対処
    • 依存ライブラリが不足している
<!--
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

※バージョン入れないとエラーがでる
 ⇢最新のバージョンはMaven Repository参照
-->
<dependency>
	<groupId>taglibs</groupId>
	<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>


<!--
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
-->
<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>jstl</artifactId>
</dependency>

 

  • form:errorsでエラーが表示されない
    • <form:form ...>の中に書かないとエラーメッセージは表示されない

 

トラブルシューティング(書籍:Spring徹底入門関連)

 

  • WebMvcConfigurerAdapterがSpring5では非推奨となっている(p151)
// 代わりにWebMvcConfigurerインターフェースを実装する
public class WebMvcConfig implements WebMvcConfigurer {

}

 

  • Cannot change version of project facet Dynamic Web Module to 3.0 (p707)

https://crunchify.com/how-to-fix-cannot-change-version-of-project-facet-dynamic-web-module-to-3-0-error-in-eclipse/

<workspace>/.settings/org.eclipse.wst.common.project.facet.core.xml

の

<installed facet="jst.web" version="2.3"/>

⇡の「version」を変更する

 

  • 書籍の通りにやってもNot Foundになる
    暫定対処:web.xmlの以下をコメントアウトする
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 3.0//EN"
 "http://java.sun.com/dtd/web-app_3.0.dtd" >

 

  • 12.2.1:thymeleaf-spring4を書籍通りにpom.xmlに追加するとエラーが出る
    対処:バージョンを指定する(org.thymeleaf thymeleaf-spring4 3.0.11.RELEASE)

 

  • 12.2.2:書籍通りに記述するとエラーがでる
    書籍:ServletContextTemplateResolver
    変更:SpringResourceTemplateResolver​

    ※バージョンの違い(ServletContextTemplateResolverのコンストラクタに引数が追加されている)が原因ぽい

 

  • p590
    Spring Boot 2を使う場合は p591の方法を使うこと。
    動作しなくて調べて自前でp590を修正して動作させたが(1時間程かかった)、
    次のページにSpring Boot 2でも動作する方法が書かれていた。

 

  • 13.2.1 + 13.3.3をテストしてみる

             1. postgresqlのインストール

sudo apt install postgresql-9.6

              2. DBの作成

$>su postgres
$>psql
postgres=# create database spring

              3. ユーザの作成/パスワードの設定

postgres=# createuser myuser with login;
postgres=# alter role myuser with password 'myuser11';

              4.postgresqlへの ログイン方法の変更(peerをmd5に変更)

sudo nano /etc/postgresql/9.6/main/pg_hba.conf
local   all   all   md5
#local  all   all   peer

              5.postgresqlの 再起動

sudo systemctl restart postgresql

              6.Messageクラスの修正(idの追加)

public int getId() {
	return id;
}

public void setId(int id) {
	this.id = id;
}

              7.MessageMapperクラスの修正(idの追加)

@Select("select id,text from messages order by id")
List<Message> findAll();

              8.schema.sqlの修正(IF NOT EXISTSの追加)

CREATE TABLE IF NOT EXISTS messages(
  id SERIAL PRIMARY KEY,
  text VARCHAR(255)
);

              9.application.propertiesに以下を追加(毎回スキーマを実行してもらうようにする)

spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/spring
spring.datasource.username=myuser
spring.datasource.password=myuser
spring.datasource.initialization-mode=always

              10.テストコード
                    ※これだと毎回データを削除する必要があるけど、とりえあずは気にしないことにする

@Test
public void messageTest() {
    String uri = "http://localhost:" + port + "/message";
    Message message = new Message();
    message.setText("My Message");

    // post
    {
        ResponseEntity<Message> response = restTemplate.postForEntity(uri, message, Message.class);
        assertThat(message.getText(), is(response.getBody().getText()));
    }

    // get
    {
        ResponseEntity<List<Message>> response = restTemplate.exchange(uri, HttpMethod.GET, null,
                new ParameterizedTypeReference<List<Message>>() {
                });

        List<Message> messages = response.getBody();
        Message result = messages.get(messages.size() - 1);
        assertThat(result.getText(), is(message.getText()));
    }
}

 

  • 13.4.1 application.propertiesのの変更
    書籍:security,user....
    変更:spring.security.user...

    書籍:spring.security.user.role
    変更:spring.security.user.roles

 

  •  13.4.2の変更
    参考:https://www.baeldung.com/spring-boot-security-autoconfiguration
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.crypto.factory.PasswordEncoderFactories;
    import org.springframework.security.crypto.password.PasswordEncoder;
    
    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
    	@Override
    	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    		// 本来はPasswordEncoderを直接作成するのは宜しくないらしい
    		final PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
    
    		final String defaultUserPassword = passwordEncoder.encode("user");
    		final String defaultAdminPassword = passwordEncoder.encode("admin");
    
    		auth.inMemoryAuthentication().withUser("user").password(defaultUserPassword).roles("USER").and()
    				.withUser("admin").password(defaultAdminPassword).roles("USER", "ADMIN");
    	}
    
    	// - このメソッドを削除するとデフォルトのフォーム認証ページが表示される
    	@Override
    	protected void configure(HttpSecurity http) throws Exception {
    		// basic認証
    		// http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
    
    		// form認証
    		// - "loginPage"を設定した場合、formページは別途自分で作成する必要があるぽい
    		// - 設定しない場合はデフォルトのform認証用ページが使われる
    		http.authorizeRequests().anyRequest().authenticated().and().formLogin().loginPage("/login").permitAll().and()
    				.logout().permitAll();
    	}
    }​

 

  •  13.6.1の変更
    書籍:endpoints...
    修正:management.endpoints...

    書籍:endpoints.enable=...
    修正:management.endpoints.enabled-by-default=...

    書籍:endpoints.info.enabled=...
    修正:management.endpoint.info.enabled=...


  • 13.6 補足
    参考:https://qiita.com/suke_masa/items/acfdf52019538fd8ccc6

    SpringBoot2では「http://localhost:8080/actuator/health」のようにアクセスする
    ※「actuator/」が必要

    • 標準では「actuator/health」「actuator/info」しか公開されていない
      • enable=trueにしてあっても「公開」されていなければアクセスできない
    • application.propertiesで「management.endpoints.web.exposure.include=*」を追加(公開)すると全部?使えるようになる
      • 「*」の部分を「info,env」のようにすると個別に公開できる

 

  • p644補足
    本の通りにプロジェクトを作ったのならorg.thymeleaf.extrasの依存関係追加は不要

 

 

 

  •   14.2.8
    書籍:xxxRepository.findOne
    修正:xxxRepository.findById