Java実行環境構築方法(Tomcat@Linux)



#1.初期導入
Linuxで利用できるjavaとしてopensourceのopenjdkやadoptjdkが存在。さらにtomcat環境構築までを整理する
基本的な流れとしては、
- javaパッケージインストール
- java切り替え
- プロファイルにJAVA_HOME等のパス定義

```ruby:1.javaインストール
#パッケージインストール
###RHEL/CentOS
sudo yum -y install java-11-openjdk java-11-openjdk-devel

###Amazon Linux2
sudo amazon-linux-extras install java-openjdk11 java-11-openjdk-devel
```

```ruby:2.OSデフォルトのjava切り替え方法

#java切り替え
[root@XXX ~]$ alternatives --config java

4 プログラムがあり 'java' を提供します。

  選択       コマンド
-----------------------------------------------
*+ 1           java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.222.b10-0.amzn2.0.1.x86_64/jre/bin/java)
   2           java-1.7.0-openjdk.x86_64 (/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.231-2.6.19.1.amzn2.0.1.x86_64/jre/bin/java)
   3           /usr/lib/jvm/adoptopenjdk-11-openj9/bin/java
   4           java-11-openjdk.x86_64 (/usr/lib/jvm/java-11-openjdk-11.0.5.10-0.amzn2.x86_64/bin/java)

Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:4


#java本体確認
[root@XXX ~]# java -version
openjdk version "11.0.5" 2019-10-15 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.5+10-LTS)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.5+10-LTS, mixed mode, sharing)

```

上記でデフォルトのjavaの切り替えができるが仕組み的には、、、

```ruby:java切り替えの仕組み
#デフォルトのjavaコマンドのありかはこちら。
[root@XXX ~]# which java
/usr/bin/java

#lsするとシンボリックリンクになっている
[root@XXX ~]# ls -l /usr/bin/java
lrwxrwxrwx 1 root root 22 11月  6 01:19 /usr/bin/java -> /etc/alternatives/java

#更にリンク先をlsするとjava切り替えで切り替えたjavaへのリンクになっている。そのためデフォルトのjavaコマンドが上記の切り替え方法で切り替わる
[root@XXX ~]# ls -l /etc/alternatives/java
lrwxrwxrwx 1 root root 77 11月  6 01:19 /etc/alternatives/java -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.222.b10-0.amzn2.0.1.x86_64/jre/bin/java

```

```ruby:3.プロファイル切り替え
cat >> ~/.bash_profile <<EOF
export JAVA_HOME=$(dirname $(dirname $(readlink $(readlink $(which java)))))
export PATH=\$PATH:\$JAVA_HOME/bin
EOF
```

tomcatのモジュールのインストールを実施する。rpmではなく、tarボールv9.0.30を導入。

```ruby:4.tomcatインストール&解凍
curl -O https://www-eu.apache.org/dist/tomcat/tomcat-9/v9.0.30/bin/apache-tomcat-9.0.30.tar.gz
tar zxvf apache-tomcat-*.tar.gz -C /usr/libexec/
chown -R tomcat. /usr/libexec/apache-tomcat-*
ln -s /usr/libexec/apache-tomcat-* /usr/libexec/tomcat9
useradd -d /usr/libexec/tomcat9 tomcat

```

```ruby:5.起動用Systemd設定実施
##ユニットファイル作成
cat << EOF > /etc/systemd/system/tomcat9.service
[Unit]
Description=Apache Tomcat 9
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/libexec/tomcat9/bin/startup.sh
ExecStop=/usr/libexec/tomcat9/bin/shutdown.sh
RemainAfterExit=yes
User=tomcat
Group=tomcat

[Install]
WantedBy=multi-user.target
EOF
```

```ruby:6.tomcat向け環境変数定義
cat << EOF > /usr/libexec/tomcat9/bin/setenv.sh
#!/bin/sh
JAVA_OPTS="-server -Xms512M -Xmx512M"
export JAVA_OPTS
EOF
```

ちなみにtomcatではsetenv.shにCATALINA_OPTS,JAVA_OPTSいずれを敷くことができるが両者の違いは以下。結論的には、CATALINA_OPTS一本化で行くのがtomcatとしては推奨らしい。

```ruby:
https://stackoverflow.com/questions/11222365/catalina-opts-vs-java-opts-what-is-the-difference
>>>
So why are there two different variables? And what's the difference?

Firstly, anything specified in EITHER variable is passed, identically, to the command that starts up Tomcat - the "start" or "run" command - but only values set in JAVA_OPTS are passed to the "stop" command. That probably doesn't make any difference to how Tomcat runs in practise as it only effects the end of a run, not the start.
→stop処理時もJAVA_OPTSは引数を付ける。

The second difference is more subtle. Other applications may also use JAVA_OPTS, but only Tomcat will use CATALINA_OPTS. So if you're setting environment variables for use only by Tomcat, you'll be best advised to use CATALINA_OPTS, whereas if you're setting environment variables to be used by other java applications as well, such as by JBoss, you should put your settings in JAVA_OPTS.
→JAVA_OPTSはtomcat以外の他のアプリケーションサーバも参照する可能性あり。CATALINA_OPTSはtomcatしか利用しない。

```

```ruby:7.自動起動
systemctl enable tomcat9 --now
```

#2.Tomcat各種設定
###アプリケーションマネージャー
${CATALINA_HOME}/conf/tomcat-user.xmlで下記を設定すると、http://<IPアドレス>:8080/へのアクセスで
アプリケーションマネージャ描画後に各種機能にアクセス可能。

```ruby:${CATALINA_HOME}/conf/tomcat-user.xml
<tomcat-users>
 <role rolename="manager-gui"/>
 <user username="tomcat" password="tomcat" roles="manager-gui"/>
</tomcat-users>
```

###セッションタイムアウト/セッションセキュリティ
${CATALINA_HOME}\conf\web.xmlで設定を行う。単位は分。設定後、tomcatの再起動は必須。

```ruby:${CATALINA_HOME}/conf/web.xml
    <session-config>
        <session-timeout>5</session-timeout>
  	<cookie-config>
    	   <httponly>true</httponly>
    	   <secure>true</secure>
	</cookie-config>
    </session-config>
```

- session-timeout
同一のセッションIDを何分保持するかどうかの定義

- httponly
httponly属性を指定すると、HTTPテキスト内のスクリプトからCookieをアクセスできなくなる。 これにより、ウェブサイトにクロスサイト・スクリプティングの脆弱性があっても、その脆弱性によってCookieを盗まれるという事態を防止できる。

- secure
TLSもしくはSSLを用いている場合、secure属性を指定する。
secure属性を指定すると、TLSもしくはSSLで保護された通信が用いられている場合のみ、Cookieがブラウザから送出されるようになる。
あくまでブラウザからアクセスする先がSSL/TLSであればOKのため、ロードバランサーでSSLオフロードして,web/appサーバはhttpの場合でもいる場合、この設定をtrueにしてもセッションIDを利用する形にすることは可能。

※httponlyやsecureモードを指定した場合はレスポンスヘッダに以下のように返ってくる。
<font color="DarkOrange"><strong>Set-Cookie: JSESSIONID=D8E49AB64414F71E00807D8991585FB6; Path=/hoge; Secure; HttpOnly</strong></font>


###アクセスログ
Tomcat では、アクセスログは拡張機能のひとつとして実装されているため、logging.properties ではなく server.xml に設定がある。patternの各種定義の意味はこちらマニュアルに詳しく載っているが基本的にカスタマイズは十分にできそう。
https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html

```ruby:設定ファイル:${CATALINA_HOME}/conf/server.xml
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
```

```ruby:${CATALINA_HOME}/logs/localhost_access_log.yyyy-mm-dd.txt(上記で出力されるアクセスログ)
127.0.0.1 - - [01/Jan/2020:01:07:20 +0900] "GET /hoge2/SessionTest HTTP/1.0" 404 864
127.0.0.1 - - [01/Jan/2020:01:07:21 +0900] "GET /favicon.ico HTTP/1.0" 200 21630
127.0.0.1 - - [01/Jan/2020:01:07:26 +0900] "GET /hoge/SessionTest HTTP/1.0" 200 35
```

###コネクションプール




###スレッドプール






#3.テスト用アプリ作成
###アプリ配置

```ruby:アプリ配置
#hogeはアプリ名なので任意の値で良い。hoge=サーブレット部分
mkdir -p /usr/libexec/tomcat9/webapps/hoge/WEB-INF/classes
chown tomcat:tomcat -R /usr/libexec/tomcat9/webapps/hoge/
vi /usr/libexec/tomcat9/webapps/hoge/WEB-INF/classes/HelloWorld.java
##################
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloWorld extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<body>");
        out.println("<h1>Hello World!</h1>");
        out.println("</body>");
        out.println("</html>");
    }
}
##################

cd /usr/libexec/tomcat9/webapps/hoge/WEB-INF/classes
javac -classpath /usr/libexec/tomcat9/lib/servlet-api.jar HelloWorld.java
```

##URL定義

<strong>web.xmlに以下を定義</strong>
- servlet-class：サーブレットのクラスファイルの名前を指定。
- servlet-name：各サーブレットを一意に識別する任意の名前。
- url-pattern：サーブレットにアクセスする際のURLを指定。

servletタグ内では，サーブレットの実体を列挙。servlet-mappingタグ内では，URLを列挙。
そして、両者をひも付けているのがservlet-nameという構成。

例えば以下定義することで、http://<サーバ>:8080/hoge/HWPageに対してアクセスすると事前に配置したwebアプリへアクセスすることが可能。

```ruby:5.URL定義
vi /usr/libexec/tomcat9/webapps/hoge/WEB-INF/web.xml
##################
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0"
  metadata-complete="true">

  <servlet>
    <servlet-name>HelloWorldName</servlet-name>
    <servlet-class>HelloWorld</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>HelloWorldName</servlet-name>
    <url-pattern>/HWPage</url-pattern>
  </servlet-mapping>

</web-app>
##################
```


<strong>参考</strong>
https://www.ipentec.com/document/java-servlet-post-http-servlet-show-table
https://commons.apache.org/proper/commons-dbcp/configuration.html
https://www.techscore.com/tech/Java/JavaEE/JDBC/6-2/
https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/302.html
https://tomcat.apache.org/tomcat-9.0-doc/config/executor.html

- java11 Manual
https://docs.oracle.com/en/java/javase/11/index.html