HTMLではformタグで入力を扱います。 formタグの属性は以下の通りです。
<form>〜</form>の間に input, select, textareaなどのタグを 置くことでいろいろな形式で入力することができます。
[ファイル配置] ${CATALINA_HOME}/webapps/basic/input/echo.jsp
${CATALINA_HOME}/webapps/basic/input/echo.jsp |
<%@page contentType="text/html; charset=utf-8" %> <html> <head> <title>Echo Servlet</title> </head> <body> <h2>EchoServletの入力</h2> <form action="../input/EchoServlet"> <input type="text" name="message"> <input type="submit"> </form> </body> </html> |
[ブラウザでアクセスするURL] http://localhost:8080/basic/input/echo.jsp
[ファイル配置] ${CATALINA_HOME}/webapps/basic/WEB-INF/src/input/EchoServlet.java
${CATALINA_HOME}/webapps/basic/WEB-INF/src/input/EchoServlet.java |
package input; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; @WebServlet(name="input.EchoServlet",urlPatterns={"/input/EchoServlet"}) public class EchoServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String msg = request.getParameter("message"); response.setContentType("text/plain; charset=utf-8"); PrintWriter out= response.getWriter(); out.println("mesasge=" + msg); } } |
EchoServlet.javaのコンパイル |
$ cd u:/Users/nitta/Documents/tomcat8/webapps/basic/WEB-INF |
http://localhost:8080/basic/input/EchoServlet?message=goodmorning にアクセスをしてみましょう。 ただしくEchoServletで処理されてmessage="与えたデータ"が表示されると思います。
Getの場合は、サーバに送るべき文字列を
?属性=値&属性=値&...属性=値という形式でパスの最後に付加して送っています。 このときに、データは次の「URLエンコード」とよばれる方法で 符号化されます。
受け取ったサーバの側では、URLエンコードされた文字列をデコードします。 このときに、エンコードと異なるcharactersetを想定してデコードを行うと 文字化けをしてしまいます。
上の例では、echo.jspの中で utf-8 を指定しているので 入力文字列はクライアント側では utf-8 というcharacterset で表現されています。 これがURLエンコードされてサーバに送られてきますが、 サーバ側では送られてきたデータをデコードして、自分が内部表現として 使うcharactersetへと変換しなくてはいけません。 このときに元のデータのcharactersetが utf-8 であることを 知らなければ、間違ったcharactersetを想定して変換してしまい (たとえば元の文字列がEUC-JPであると勘違いをして変換したら) 文字化けをしてしまうことになるわけです。
(注意) 手元のPCの日本語環境や使用しているブラウザ、サーバ側のtomcatのバージョンの組み合わせによっては、文字化けしない場合もあります。
ServletRequest#setCharacterEncoding()メソッドは、 リクエスト(入力)のcharactersetを指定するメソッドです。 メソッドの引数としてcharactersetを指定します。 このメソッドでcharactersetを指定しない場合の 初期値は "ISO8859-1" なので、漢字を使うと文字化けしたわけです。
setCharacterEncoding()メソッドはgetParameter()メソッドよりも前に 呼び出す必要があることに注意をして下さい。
[ファイル配置] ${CATALINA_HOME}/webapps/basic/input/echo2.jsp
echo.jspからecho2.jspへの書き換え |
*** basic/input/echo.jsp Thu Jul 28 13:26:00 2011 --- basic/input/echo2.jsp Thu Jul 28 14:47:38 2011 *************** *** 6,12 **** <body> <h2>EchoServletの入力</h2> ! <form action="../input/EchoServlet"> <input type="text" name="message"> <input type="submit"> </form> --- 6,12 ---- <body> <h2>EchoServletの入力</h2> ! <form action="../input/EchoServlet2"> <input type="text" name="message"> <input type="submit"> </form> |
[ファイル配置] ${CATALINA_HOME}/webapps/basic/WEB-INF/src/input/EchoServlet2.java
EchoServlet2.javaからEchoServlet2.javaへの書き換え |
*** basic/WEB-INF/src/input/EchoServlet.java Thu Jul 28 13:19:45 2011 --- basic/WEB-INF/src/input/EchoServlet2.java Thu Jul 28 14:22:14 2011 *************** *** 5,15 **** import javax.servlet.http.*; import javax.servlet.annotation.*; ! @WebServlet(name="input.EchoServlet",urlPatterns={"/input/EchoServlet"}) ! public class EchoServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String msg = request.getParameter("message"); response.setContentType("text/plain; charset=utf-8"); PrintWriter out= response.getWriter(); --- 5,16 ---- import javax.servlet.http.*; import javax.servlet.annotation.*; ! @WebServlet(name="input.EchoServlet2",urlPatterns={"/input/EchoServlet2"}) ! public class EchoServlet2 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + request.setCharacterEncoding("utf-8"); String msg = request.getParameter("message"); response.setContentType("text/plain; charset=utf-8"); PrintWriter out= response.getWriter(); |
EchoServlet2.javaのコンパイル |
$ cd C:/User/nitta/Documents/tomcat8/webapps/basic/WEB-INF |
[ブラウザでアクセスするURL] http://localhost:8080/basic/input/echo2.jsp
Tomcat5以降では 「GETで送られきたURL文字列のデコードには必ずISO8859-1が使われて setCharacterEncoding()の呼び出しによる設定を無視する」 ようになりました。 POSTで送られてきた文字列は昔のバージョンのように setCharacterEncodingの影響を受けますが。 setCharacterEncoding()が効力を持つようにserver.xmlを編集して、 tomcatを再起動して下さい。
[ファイル配置] ${CATALINA_HOME}/conf/server.xml
server.xmlの書き換え |
*** servlet/server.xml.org Mon Sep 15 18:21:53 2014 --- servlet/server.xml Mon Sep 15 18:21:53 2014 *************** *** 67,73 **** --> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" ! redirectPort="8443" /> <!-- A "Connector" using the shared thread pool--> <!-- <Connector executor="tomcatThreadPool" --- 67,73 ---- --> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" ! redirectPort="8443" useBodyEncodingForURI="true" /> <!-- A "Connector" using the shared thread pool--> <!-- <Connector executor="tomcatThreadPool" |
上記のURLエンコードによる文字化けはGetでデータを送る場合にだけ起こります。 Postのときは、送るべきデータをURLに含めて送信することはしないからです。
HTTPプロトコルで、 WWWクライアントがWWWサーバに送る要求(リクエスト)には次の種類があります。 通常のサーブレットであればdoGet()とdoPost()だけを実装すればよいでしょう。
リクエストメソッド | サーブレット側のメソッド | 説明 |
---|---|---|
GET | doGet() | コンテンツを取得する |
POST | doPost() | データを送信する。 |
HEAD | doHead() | コンテンツのヘッダ部を取得する。 |
PUT | doPut() | コンテンツを作成、更新する。 |
DELETE | doDelete() | コンテンツを削除する。 |
OPTIONS | doOptions() | 利用可能なオプションの一覧を得る。 |
TRACE | doTrace() | ループバックを起動する。 |
POSTメソッドが送られるのは、 「form文のmethod属性として"POST"が指定された」 場合だけです。
GETメソッドが送られるのは、 「ブラウザのアドレスバーに直接URLを打ち込んだ」場合、 「ブラウザ上リンクをクリックした場合」、 「form文のmethod属性として"GET"が指定された」場合、 「form文のmethod属性の指定が省略された」場合などです。
つまり、かなり多くの場合においてGETメソッドが送られることになります。