8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

TomcatのWebListener、HttpServlet、jspのあれこれ

Last updated at Posted at 2015-12-06

設定ファイル

もうアノテーションで全部指定できるから、個人的な開発ではほぼ不要かな。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>tomcatTest20150719</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <listener>
    <listener-class>com.example.ListenerSample</listener-class>
  </listener>
  <context-param>
    <param-name>hoge</param-name>
    <param-value>HOGE</param-value>
  </context-param>
  <!-- フィルター -->
  <filter>
    <filter-name>FilterSample</filter-name>
    <filter-class>com.example.FilterSample</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>FilterSample</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

webリスナー。起動時、終了時

tomcatが起動した時とかwarファイルを更新した時とかにcontextInitializedが一度だけ、終了時にはcontextDestroyedが一度だけ。

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
@javax.servlet.annotation.WebListener
public class WebListener implements ServletContextListener {
	@Override
	public void contextDestroyed(ServletContextEvent paramServletContextEvent) {}
	@Override
	public void contextInitialized(ServletContextEvent paramServletContextEvent) {
		paramServletContextEvent.getServletContext().setAttribute("hoge", "ok");
	}
}

コンテキストに共通のインスタンスを作成する方法

コンテキスト全体で共通のインスタンスを持たせたい時がある。例えばアプリ全体で共通のカウンターが欲しい時、共通のIntegerオブジェクトが必要になる。staticでシングルトンを使うとjvm共通になって別のwebアプリと被ってしまうから出来ない。
そんな時はServletContext.setAttribute(String,Object);を使う。これならwebアプリでそれぞれインスタンスを持てる。
もちろん、webアプリを再起動させた時はクリアされるから、ServletContextListenerクラスのcontextDestroyedメソッドの中でonSaveとかの処理をする。contextDestroyedメソッドの中で時間のかかる処理をしていると、webアプリの再起動がその分遅くなるから注意。必要ならServletContextListenerクラスのcontextInitializedメソッドで初期化を行っても良い。

以下のクラスを作る。特に何かを継承したりしなくてもよい。

CustomWebListenerManager.java
import java.io.File;
import java.util.Locale;
import java.util.ResourceBundle;

import javax.servlet.ServletContext;

public class CustomWebListenerManager {
	private static final String getTag(ServletContext sc) {
		String tag = String.format(Locale.US, "%s-%x", CustomWebListenerManager.class.getName(), System.identityHashCode(sc));
		return tag;
	}

	public static CustomWebListenerManager getInstance(ServletContext sc) {
		String tag = getTag(sc);
		Object attribute = sc.getAttribute(tag);
		if (attribute != null) {
			return (CustomWebListenerManager) attribute;
		}
		CustomWebListenerManager instance = new CustomWebListenerManager(sc);
		sc.setAttribute(tag, instance);
		return instance;
	}

	public final String storagePath;

	private CustomWebListenerManager(ServletContext sc) {
		//好きな処理を書く
	}
}

そして実際にインスタンスを取得する時はこうする

HogeGet.java
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;

@WebServlet({ "/hogeGet" })
public class FriendServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
		String path = CustomWebListenerManager.getInstance(request.getServletContext()).storagePath;
		System.err.println(path);
	}
}

フィルター

リクエスト内容を弄くるフィルター
import javax.servlet.Filter;
public class FilterSample implements Filter {
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		chain.doFilter(request, response);
	}
}

サーブレット

@WebServlet({ "/url1","/url/sub2"})
public class AnyServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setAttribute("tweets", any object);
		//サーブレットで色々なデータをsetAttributeして、jspで表示する
		request.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(request, response);
		//サーブレットを用意するのが面倒な時はこれでよい
		responce.getWriter().write("hoge");
	}
}

上記コード内の様にjspを指定した場合、そのjspを配置する場所は以下のとおり
imgTemp-2015-12-06-17-55-14.png

jspファイル

プログラムの中でprintln("<html>");ってやるのがめんどいのでphpっぽく書く方法。基本的にはサーブレットの中でsetAttributeした物をgetAttributeして色々使う。getAttributeの結果はObjectなのでキャストしないといけない。

hoge.jsp
<%@ page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=utf-8"	pageEncoding="utf-8"%>
<% String title=(String)request.getAttribute("title");
  //複数行書ける
%>
<%!
  // メソッドはここに書く
  String getHoge(){
    return "hoge";
  }
%>
<!DOCTYPE html>
<meta charset="utf-8">
<title><%=title%></title>

つまり、<%なんとか%>で囲った部分でjavaの処理が書けるという事。ループとか条件分岐もこれで囲う。クラスに対してgetterがしっかり実装されている時は${hoge.kage}というより短い書き方が出来る。

jspファイルをincludeする

jspファイルをinclude出来る。注意点として、paramで指定できるvalueは文字列型のみ。オブジェクト駄目。パラメーターが色々あるjspファイルをincludeする時はparamタグの量が凄いことになる。jspの中でも<%request.setAttribute("key", object);%>って出来るけど、グローバル変数的な感じでinclude先限定じゃなくなるから扱いが大変。attributeのキーが被ってもeclipse警告してくれないし。child.jsp側ではrequest.getParameter("")で文字列を受け取る。俺の環境のEclipseでは自動補完のままjsp:paramタグを作ると、name valueでなくvalue nameの順番で属性値が入力されてしまい、それに気が付かずにnameに変数を入れて怒られる。
valueの項目に、例えば文字結合とかでダブルクオーテーションを使う時は、二重にエスケープする必要がある。複雑な値は<%String val=xxxx;%> で別途変数に入れてからvalue属性として指定したほうがいいね

parent.jsp
<jsp:include page="include/child.jsp" >
	<jsp:param name="userId" value="<%=userId%>"/>
	<jsp:param name="userId2" value="<%=userId2%>"/>
	<jsp:param name="userId3" value="<%=(\"./\"+user.getUserId()) %>"/>
</jsp:include>

jspファイルの中で使える変数

jspファイルの中ではrequest変数とかが宣言ナシで使えるけど、宣言ナシで使える変数の一覧。使いみちがあるのはrequest、responce、session、application、config、out くらいかな

xxx_jsp.java
javax.servlet.http.HttpServletRequest request;
javax.servlet.http.HttpServletResponse response;
javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = pageContext.getSession();
javax.servlet.ServletContext application=pageContext.getServletContext();
javax.servlet.ServletConfig config=pageContext.getServletConfig();
javax.servlet.jsp.JspWriter out = pageContext.getOut();
java.lang.Object page = this;
8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?