JavaScriptをJavaで呼び出してみる

#はじめに
今回は、Javaアプリケーション内でJavaScriptを使う方法を実践してみます。
JSPの中でJavaScriptを実践知る方法とJavaファイルの中で実践する方法の二つがあります。

###開発環境
eclipse
tomcat
java



#JSPファイルでJSを実行

IndexServlet.java
index.jsp
main.js
を作成していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764409/97f43cef-b23f-1a52-702a-bfa27938b610.png)

このような階層となっています。

```servlet.IndexServlet.java
package servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class IndexServlet
 */
@WebServlet("/IndexServlet")
public class IndexServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public IndexServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}
```

サーブレットはノータッチでOKです。（あくまでもJSPでJSを実行することが目的なので）

```index.jsp
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<style>
.box1 {
    width: 200px;
    height: 200px;
    background-color: #ccffcc;
}
.box2 {
  width: 200px;
  height: 200px;
  background-color: #ddd;
}
</style>
<body>
	<h1>JSPでのJS実行確認</h1>
	<div class="box1">box1</div>

	<div class="box2">box2</div>

	<form action="IndexServlet" method="post">
      ユーザID：<input type="text" name="user_id" id="user_id">
      パスワード：<input type="password" name="pass" id="pass">
      <input type="submit" value="ログイン" id="btn">
  	</form>
  <input type="button" value="パスワードをみる" id="passshow">
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="main.js"></script>
</body>
</html>
```

・クリックすると色が変わるボックス
・マウスホバーで色が変わるボックス
・ログインフォームのバリデーション
の三つを実装していきます。

```main.js
/* ---------クリックした時の処理---------*/
$('.box1').on('click', (e) => {
	$(e.target).css({'background-color': 'skyblue' });
});
/*  ------マウスをホバーした時の処理----------*/
const onMouseenter = (e) => {
  $(e.target).css({
    'background-color': '#ff9999',
  });
};
const onMouseleave = (e) => {
  $(e.target).css({
    'background-color': '#dddddd',
  });
};
$('.box2')
  .on('mouseenter', onMouseenter)
  .on('mouseleave', onMouseleave);
/*-------- パスワードを見れるようにする--------------*/
$('#passshow').on('click', () => {
  $('#pass').attr('type', 'text');
});
/*----------ログイン時にバリデーションを設定する(空欄だった場合弾く)----------- */
$('#btn').on('click', (e) => {
  const id = $('#user_id').val();
  const pass = $('#pass').val();
  if(!id){
    e.preventDefault();
    console.log(id);
    alert('IDが空欄です');
  }
  if(!pass){
    e.preventDefault();
    console.log(pass);
    alert('パスワードが空欄です');
  }
})
```

以上のようにJSを実装することができた。
（HTMLの時と全く同じように実装することができた。）

#JavaファイルでJSを実行する

次に、JavaファイルのなかでJSを実行する方法の一つを紹介する。
解説は全てコード内にあるのでみていただければ。。。

下記のコードは、オラクルのJavaドキュメントガイドの下記のページを解説した物になります。
https://docs.oracle.com/javase/jp/8/docs/technotes/guides/scripting/prog_guide/api.html

```test.java
import java.io.File;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class test {

	public static void main(String[] args) throws Exception{
		//ScripteEnginManagerインスタンスを作成
		ScriptEngineManager factory = new ScriptEngineManager();
		//ScripteEngineManagerインスタンスのgetEngineByNameメソッドでJSのスクリプトエンジンを指定
		ScriptEngine engine = factory.getEngineByName("JavaScript");

		//JSエンジンの活用---------------------------------
		//コンソールに表示・スクリプトをJS文として評価
		engine.eval("print('Hello World')");

	//文字ファイルを読み込むためのクラスjava.io.FileReaderを使うことでJSファイルごと実行できる
		//同じパッケージ同じ階層にある時
		File file1 = new File("src/test.js");
		engine.eval(new java.io.FileReader(file1));
		//srcと同じ階層のresourcesフォルダにある時
		File file2 = new File("resources/test.js");
		engine.eval(new java.io.FileReader(file2));

		//put（キー名, ソースコード）でキー名にソースコードを保存できる
		engine.put("file", file1);
		//getAbsolutePathで絶対パスを取得する・スクリプトをJS文として評価
		engine.eval("print(file.getAbsolutePath())");

		//変数に関数などを代入可能
		String script1 = "function helle(name) { print('Hello' + name);}";
		//変数名で呼び出し(engineに保存されている)・スクリプトをJS文として評価
		engine.eval(script1);
		//engineに保存されている関数やメソッドを呼び出す。→関数などの実行ができる　＊invocable 呼び出し可能という意味
		Invocable inv1 = (Invocable) engine;
		//今回は関数なのでinvokeFunction("呼び出される関数名", "引数")で実行できる
		inv1.invokeFunction("helle", "太郎");

		//"obj"というオブジェクトを作成して、"obj"オブジェクトのメソッドも定義
		String script2 = "var obj = new Object(); "
				+ "obj.goodbye = function(name){print('Goodbye' + name + 'さん');}";
		//engineに保存・スクリプトをJS文として評価
		engine.eval(script2);
		//engineを呼び出し可能にする
		Invocable inv2 = (Invocable) engine;
		//呼び出したいメソッドを持つオブジェクトを取得する（扱えるようにする）
		Object obj1 = engine.get("obj");
		//今回はメソッドなので、invokeMethod(オブジェクト名, "メソッド名", "引数")で実行
		inv2.invokeMethod(obj1, "goodbye", "次郎");

	//Runnableインターフェースのメソッドとしてスクリプト関数を扱うことができる・グローバルに使えるようになる
		//引数の無い関数生成
		String script3 = "function run() { print('java.lang.Runnableインターフェースの呼び出し'); }";
		//スクリプトをJS文として評価・呼び出し可能状態にする
		engine.eval(script3);
		Invocable inv3 = (Invocable) engine;
		//Runnable（インターフェース）を取得し、スクリプト関数（inv3）をメソッドr1として実装
		Runnable r1 = inv3.getInterface(Runnable.class);
		//Threadオブジェクト（Runnableインターフェースが実装されている）にメソッドr1を渡すし作成
		Thread th1 = new Thread(r1);
		//実行開始
		th1.start();


		//引数の無いメソッド生成
		String script4 = "var obj = new Object();"
				+ "obj.run = function() {print('Runnableメソッドの呼び出し');}";
		//スクリプトとして評価
		engine.eval(script4);
		//objをオブジェクトとして扱えるようにする
		Object obj2 = engine.get("obj");
		//呼び出し可能にする
		Invocable inv4 = (Invocable) engine;
		//Runnable（インターフェース）を取得し、スクリプト関数（inv4）をメソッドr2として実装
		Runnable r2 = inv4.getInterface(obj2, Runnable.class);
		//Threadオブジェクト（Runnableインターフェースが実装されている）にメソッドr1を渡し作成
	    Thread th2 = new Thread(r2);
	    th2.start();

	}
}

```

#最後に
今回紹介したようにJavaとJSを組み合わせることができれば、より動的なページが作れそうですね。