본문 바로가기

Servlet & JSP

Servlet에서 init()으로 객체를 받는 방법

과제를 풀던 도중 문제가 발생했다. 과제의 내용은 이렇다.

 

  • 이전에 실습한 로그인 서블릿에 init-param 을 추가하여 변경
  • 서블릿 초기 정보로 web.xml 에 adminID로 "admin", adminPwd 로 "12345"를 미리 지정한다.
  • adminID 는 init() 메서드에서 불러오고, adminPwd 는 doget 에서 불러와서 로그인 프로세스 진행

 

내가 수정한 web.xml은 아래와 같다

<?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_4_0.xsd" id="WebApp_ID" version="4.0">

- 중략 -

  <servlet>
  	<servlet-name>query</servlet-name>
  	<servlet-class>com.edu.test.QueryServlet</servlet-class>
  	
  	<init-param>
  		<param-name>adminID</param-name>
  		<param-value>admin</param-value>
  	</init-param>
  	
  	<init-param>
  		<param-name>adminPwd</param-name>
  		<param-value>12345</param-value>
  	</init-param>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>query</servlet-name>
  	<url-pattern>/query</url-pattern>
  </servlet-mapping>

- 중략 -
</web-app>

 

 

서블릿 작업을 수행하기 위해 아래와 같이 코드를 수정했다.

package com.edu.test;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class QueryServlet extends HttpServlet{
	
	String adminID; //, adminPwd;
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		adminID = config.getInitParameter("adminID");
		//adminPwd = config.getInitParameter("adminPwd");
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//req.setCharacterEncoding("UTF-8");
		String reqId = req.getParameter("id");
		String reqPasswd = req.getParameter("pwd");
        
		//String adminID = this.getInitParameter("adminID");
		String adminPwd = this.getInitParameter("adminPwd");
		
		resp.setContentType("text/html; charset=UTF-8");
		PrintWriter out = resp.getWriter();
		
		if(reqId.equals(adminID) && reqPasswd.equals(adminPwd)) {
			out.print("로그인 성공입니다");
		}
		else {
			out.print("로그인 실패입니다");
		}
		out.close();
	}
}

 

이전에는 init()에서만 id,pw를 받거나 doGet()에서만 id, pw를 받았을 때는 문제없이 작동이 잘 되었기 때문에

각 함수의 id와 pw를 받는 부분만 주석처리하여 작동하면 간단하게 잘 될 것이다.

 

아래의 html에서 실행시켜보자

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="query" method="get">
		ID: <input type="text" name="id"><br>
		PW: <input type="password" name="pwd"><br>
		<input type="submit" value="send">
	</form>
</body>
</html>

???

당연히 잘 작동할 것이라고 생각했는데 오류가 발생했다.

오류를 자세히 읽어보자

Cannot invoke "javax.servlet.ServletConfig.getInitParameter(String)"

config 객체에서 가지고 있는 get 문자열 함수가 호출이 안된단다

because the return value of "javax.servlet.GenericServlet.getServletConfig()" is null

GenericServlet에서 가지고있는 객체가 없기 때문에?

 

서블릿의 실행 순서를 보자

처음 해보는 Servlet & JSP 웹프로그래밍 / 출판 Ruby paper

최초요청시에 객체를 생성해서 init()으로 넘겨서 service()가 실행된다.

아니 그럼 config 객체가 무조건 생기는거 아냐? 근데 왜 객체가 없대?

 

모르겠어서 교수님께 카톡을 드렸다.

그러니까 교수님 말씀은 재정의한 init()에서 super.init(config)로 HttpServlet에 객체를 넘겨주어야 한다고 하신다.

 

일단은 이해가 안됐지만 스스로 좀 더 공부해보고 다시 물어보기로 했다.

 

오라클에서 JAVA 클래스에 대해 잘 정리해 놓았으니 읽어보기로 했다.

 

docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html

 

HttpServlet (Java(TM) EE 7 Specification APIs)

Called by the server (via the service method) to allow a servlet to handle a PUT request. The PUT operation allows a client to place a file on the server and is similar to sending a file by FTP. When overriding this method, leave intact any content headers

docs.oracle.com

docs.oracle.com/javaee/7/api/javax/servlet/GenericServlet.html

 

GenericServlet (Java(TM) EE 7 Specification APIs)

Defines a generic, protocol-independent servlet. To write an HTTP servlet for use on the Web, extend HttpServlet instead. GenericServlet implements the Servlet and ServletConfig interfaces. GenericServlet may be directly extended by a servlet, although it'

docs.oracle.com

Init()의 역할이 뭘까?

즉, 서블릿 컨테이너가 서블릿(객체)이 서비스에 배치되어 있다는 것을 알려주기 등록하기 위한 메소드이다.

 

그런데 우리가 궁금해하는 요점은 @override한 init() 과 doGet()에서 각각에서는 객체의 init-Param값을 받으나 왜 섞어쓰니깐 안되냐는 것이다.

 

모르겠다 추후 수정

21.05.04

1. @override한 init()만을 사용할 때는 처음 객체가 @override한 init()으로 들어가서 사용된 후 메소드가 작업이 끝나면서 받아온 객체 정보가 사라지게 된다.

 

2. doGet()으로 사용할 때는 HttpServlet에서 init() 메소드를 사용하기 때문에 그림처처럼 순서대로 등록된다.

 

따라서 둘을 섞어서 쓸 때는 객체를 처음 받아오는 함수가 @override된 init()이기 때문에 위 그림처럼 객체가 순서대로 등록이 되지 않는다. 

 

고로 super.init()에 config 객체를 넘겨서 서비스 중인 객체를 등록하면 정상 동작 된다!!