Servlet

Servletの特徴:Singleton且つMultithread

スレッドセーフではないため、インスタンス変数が使用禁止

処理順番

Listener → Filter → Wrapper → Servlet

Servletクラス関係図

Servletのライフサイクル

Servletサンプル

WEB-INF/web.xml

<servlet>

<description>This is demo.</description>

<description-name>DEMO</description-name>

<servlet-name>MyServlet</servlet-name>

<servlet-class>com.test.servlet.MyServlet</servlet-class>

<load-on-startup>0</load-on-startup> <!-- 0:優先級最大 -->

<init-param>

<param-name>param1</param-name>

<param-value>abc</param-value>

</init-param>

</servlet>

<servlet-mapping>

<servlet-name>MyServlet</servlet-name>

<url-pattern>/login</url-pattern>

</servlet-mapping>

import javax.sql.DataSource;

public class MyServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

private DataSource testDS;

private ServletContext context;

private ServletConfig config;

public MyServlet() {

super();

}

public void init() throws ServletException {

System.out.println("Init");

}

public void init(ServletConfig config) throws ServletException {

this.config = config;

context = config.getServletContext();

super.init(config);

context.log(new Date().toString() + ":起動");

version = getInitParameter("version"); // 初期値取得

Context ctx = null;

try {

//★JNDIをキャッシュする

ctx = new InitialContext();

testDS = (DataSource)ctx.lookup("jdbc/testDS");

}

catch(NamingException ne) {

ne.printStackTrace();

}

catch(Exception e) {

e.printStackTrace();

}

}

public void destroy() {

context.log(new Date().toString() + ":停止");

super.destroy();

}

protected void doGet(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

ServletContext context = getServletContext();

String xxx = context.getInitParameter("xxx"); // <context-param>で定義

// 初期値をすべて取得

Enumeration<String> inits = request.getInitParameterNames();

while(inits.hasMoreElements()) {

name = (String) enumeration.nextElement();

value = config.getInitParameter(name);

...

}

response.setContentType("text/html;charset=UTF-8");

// InputStream in = request.getInputStream(); // JSON文字列を取得

// ObjectInputStream objInStream = new ObjectInputStream(in);

// Object obj = objInStream.readObject();

...

String name = request.getParameter("name");

// チェックボックス・複数選択リストボックス

String[] names = request.getParameterValues("names");

HttpSession session = request.getSession();

session.setAttribute("name",name);

request.setAttribute("name", name);

//↓★アウトプットを圧縮する

OutputStream out = null;

String encoding = request.getHeader("Accept-Encoding");

if (encoding != null && encoding.indexOf("gzip") != -1) {

response.setHeader("Content-Encoding" , "gzip");

out = new GZIPOutputStream(response.getOutputStream());

} else if (encoding != null && encoding.indexOf("compress") != -1) {

response.setHeader("Content-Encoding" , "compress");

out = new ZIPOutputStream(response.getOutputStream());

} else {

out = response.getOutputStream();

}

//↑★アウトプットを圧縮する

request.getRequestDispatcher("show.jsp").forward(request, response);

return;

}

protected void doPost(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

public DataSource getTestDS() {

return testDS;

}

}

・RequestのServletInputStream getInputStream() 二進数データ ファイル保存

・RequestのBufferedReader getReader() 文字列データ 文字処理

★Servlet3.0の新機能

>新規Annotation

@WebServlet 非同期モードあり

@WebFilter(filterName="",urlPattern={"/"});

@WebListener

@WebInitParam

@MultipartConfig ファイルアップロード

@ServletSecurity ユーザ認証

name <servlet-name>

urlPatterns <url-pattern>,

loadOnStartup <load-on-startup>

initParam <init-param>

name <param-name>

value <param-value>

>web-fragment.xml web.xmlを複数に分割

>動的アプリケーション拡張 getServletRegistrationなど

>JSPモジュール化(jarファイル化)

AsyncServlet.java

★ServletOutputStream とPrintWriter

・ServletOutputStream 二進数

・PrintWriter 文字ストリームなので、変換が必要のため、効率が悪い

request.getRequestDispatcher("/header.html").include(request, response);

response.getOutputStream().println("<h1>XXX</h1>");

request.getRequestDispatcher("/footer.html").include(request, response);

★ステータスコードについて

response.sendError("503"); ×

response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); 〇 定数を使うこと

HTTPのステータスコードを参照

★ServletConfigとServletContext

ServletConfig 各々Servletに対して

<servlet>

...

<init-param>

<param-name>name</param-name>

<param-value>XXX</param-value>

</init-param>

</servlet>

ServletConfig config = getServletConfig(); // GenericServletから

String value = config.getInitParameter("name"); // 複数:getInitParameterNames

ServletContext すべてServletに対して

<context-param>

<param-name>name</param-name>

<param-value>XXX</param-value>

</context-param>

ServletContext context = getServletConfig().getServletContext();

或いは

ServletContext context = getServletContext();

String value = context.getInitParameter("name"); // 複数:getInitParameterNames

サンプル

@Override

public void init() throws ServletException {

ServletContext context = getServletContext();

context.setAttribute("times", 0);

}

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

ServletContext context = getServletContext();

int times = (Integer) context.getAttribute("times");

times++;

context.setAttribute("times", times);

}

★HttpServletRequestについて

request.getRemoteAddr();

request.getRemoteHost();

request.getQueryString()

request.getContextPath()

request.getMethod()

request.getRequestURL() // http://localhost:8080/project/xxx

request.getRequestURI() // /project/xxx

request.getRequestURI().substring(request.getContextPath().length()) // /xxx

Enumeration<String> enumeration = request.getHeaderNames();

while(enumeration.hasMoreElements()) {

String name = enumeration.nextElement();

String value = request.getHeader(name);

...

}

request.getHeader("user-agent"); // ブラウザ情報

Enumeration<String> langs = request.getHeaders("accept-language"); // 複数の値

while(langs.hasMoreElements()) {

String lang = langs.nextElement();

...

}

パラメータ取得

String username = request.getParameter("username");

// Checkbox

String[] hobbies = request.getParameterValues("hobby");

System.out.println( Arrays.toString(hobbies) );

//方法1

Enumeration<String> names = request.getParameterNames();

while(names.hasMoreElements()){

String name = names.nextElement();

System.out.println(name + ":"

+ Arrays.toString(request.getParameterValues(name)));

}

//方法2

Map<String, String[]> paramterMap = request.getParameterMap();

Set<String> keys = paramterMap.keySet();

for(String key : keys){

System.out.println(key + ":" + Arrays.toString(paramterMap.get(key)));

}

★HttpServletRequestWrapper & HttpServletResponseWrapper

DEMO

★Dynamic Servlet/Filter Registration

public class MyServletContextListener implements ServletContextListener {

@Override

public void contextInitialized(ServletContextEvent sce) {

ServletContext sc = sce.getServletContext();

// Register Servlet

ServletRegistration sr = sc.addServlet("DynamicServlet",

"com.sample.DynamicServlet");

sr.setInitParameter("xxx", "yyy");

sr.addMapping("/dynamic");

// Register Filter

FilterRegistration fr = sc.addFilter("DynamicFilter",

"com.sample.DynamicFilter");

fr.setInitParameter("xxx", "yyy");

fr.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST),

true, "DynamicServlet");

}

}