본문 바로가기

Programming/JSP & Servlet

[JSP/SERVLET] 서블릿(Servlet)을 활용한 form 데이터 주고받기

 


Servlet 을 활용한 form 데이터 주고 받기


 

 

1. 서블릿(Servlet)


서블릿(Servlet)은 서버에서 생성하고 서버에서 실행하는 웹용 클래스다.

프로그래밍 명령 등의 로직과 알고리즘이 공개되는 것이 부담스럽거나, 자료이동을 감출 때 사용한다.

서블릿에 동작을 일임하듯 이름불러 사용하거나, 서블릿의 호출 이름을 변경하여 사용이 가능하다.

 

Servlet 의 특징

1. 동적 웹 어플리케이션 컴포넌트

2. .java 확장자다.

3. 클라이언트의 요청에 동적으로 작동하며 응답은 html을 이용

4. java thread 이용 (빠른 동작 실행)

5. HttpServlet을 상속받아야 서블릿 클래스가 됨

 

 

이전 포스트에서의 데이터 전송 과정은 모두 jsp 로 구성됐다.

정보입력 페이지(login.jsp)  → 정보처리 페이지(login_do.jsp)  → 처리결과 페이지(login_ok.jsp)

 

이제는 정보를 처리하는 페이지를 Servlet 으로 관리하여 데이터와 주소, 로직을 감출 것이다.

 

 

 

2. Servlet 생성


 

이클립스 내 웹다이나믹 프로젝트를 생성 → Java Resources → 우클릭 후 New → Servlet

 

 

Servlet 을 담을 패키지 이름과, Servlet 의 이름을 작성한다.

Servlet 은 웹용 클래스다. 이름의 첫글자를 대문자로 지정하자.

 

 

Next 를 누르면 Servlet 의 이름을 맵핑할 수 있다.

너무 길기도 하고, 이름이 노출되면 보안에 취약하기에 경로를 간단하게 매핑하는 것이다.

 

 

/example.do 라는 이름으로 매핑했다.

이제 페이지를 이동하거나 주소를 전달할 때 Servlet 의 이름이 아닌 매핑한 example.do 로 작성해면 된다.

 

 

 

3. Servlet 을 활용한 form 데이터 주고받기


3-1. 정보입력 페이지(091_UseServlet.jsp)

<form method="post" action="../LoginServlet"> <!-- 한단계 위 폴더 -->
    <label for="userid"> 아이디 : </label>
    <input type="text" name="userid" id="userid"><br>
    <label for="userpwd"> 암 &nbsp; 호 : </label>
    <input type="password" name="pwd" id="userpwd"><br>
    <input type="submit" value="로그인">
</form>

method="post"

form 의 데이터를 노출되지 않는 "post" 방식으로 보낸다. 

 

action="../LoginServlet"

form의 submit 버튼을 눌렀을 경우, form 안의 모든 데이터들이 LoginServlet 으로 이동하도록 경로를 설정한다.

 

 

현재 Servlet 파일은 src/main/java 에 있고, 091_UseServlet.jsp 는 src/main/webapp/CH02 폴더 안에 있다.

현재 페이지를 기준으로(091_UseServlet.jsp) 상위 폴더에 Servlet 이 있는 java 폴더가 있기 때문에, ../ 명령으로 한 단계 위 폴더에 접근하도록 작성한다.

 

 

 

해당 페이지를 실행하면 프로젝트 내의 webapp 폴더를 기준으로 한 jsp 파일 이름과 경로가 그대로 뜬다.

 

이를 감추기 위해서 이후에는

1. 시작이 되는 하나의 파일(index.jsp)에 이동할 주소를
2. 매핑한 서블릿의 이름과 쿼리스트링으로 전달하는 command 변수로 지정한 뒤(example.do?command=main)
3. 이동할 서블릿을 ActionFactory 에서 지정하고
4. 해당 서블릿으로 이동시켜 데이터를 동작시킬 것이다.

 

무슨 말인지 지금은 몰라도 된다. 그냥 Servlet 을 통해 페이지 이름 등을 감출 수 있구나. 라고 이해하자.


3-2. 정보처리 페이지(LoginServlet.java)

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L; // 아직 쓸일 거의 없음

    public LoginServlet() {
        super();
    }
	
    /* form 에서 method="get" 으로 호출할 때 실행되는 곳 */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        String userid = request.getParameter("userid");
        String pwd = request.getParameter("pwd");

        if(userid.equals("scott") && pwd.equals("tiger")) {
            request.setAttribute("name", "홍길동"); // name에 해당하는 값 "홍길동"
            request.setAttribute("userid", userid); // userid에 해당하는 값 "scott"
            RequestDispatcher rd = request.getRequestDispatcher("CH02/092_UseServlet_ok.jsp");
            rd.forward(request, response);
        }else {
            response.sendRedirect("CH02/091_UseServlet.jsp");
        }
    }
	
    /* form 에서 method="post" 으로 호출할 때 실행되는 곳 */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response); // post 로 호출해도 doGet 이 실행되도록 할 때 사용하는 코드
    }

}

 

Servlet 생성

예시를 위한 사진, 이미 생성한 파일이라 오류뜨는 것.

 

로그인 처리를 도울 Servlet 은 Java Resources/src/main/java/ 안에 com.himedia.servlet 패키지를 만들어 생성했다.

 

 

src/main/java 경로에 있으며 패키지명을 통해 폴더를 세부적으로 나누어 파일을 구분하기 쉽도록 작성했다.

실제로는 src/main/java 와 같은 위치로 본다.

 

request, response UTF-8 인코딩

request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");

 

URL 인코딩 방식이 한글을 지원하지 않기 때문에 작성한다.

request.getParameter 로 값을 전달받거나, response.sendRedirect 로 이동할 페이지를 전송할 때 한글이 섞여있을 경우를 대비한다.

 

getParameter

String userid = request.getParameter("userid");
String pwd = request.getParameter("pwd");

 

form 으로 부터 전달받은 userid 와 pwd 를 해당 파일안에서 편히 사용하도록 변수에 넣어준 것이다.

 

값 일치 여부에 따른 데이터 이동

if(userid.equals("scott") && pwd.equals("tiger")) {
    request.setAttribute("name", "홍길동"); // name에 해당하는 값 "홍길동"
    request.setAttribute("userid", userid); // userid에 해당하는 값 "scott"
    RequestDispatcher rd = request.getRequestDispatcher("CH02/092_UseServlet_ok.jsp");
    rd.forward(request, response);
}else {
    response.sendRedirect("CH02/091_UseServlet.jsp"); // CH02 폴더에 091_UseServlet.jsp 로 이동
}

 

현재 데이터베이스를 따로 생성하지 않았기 때문에 서버에 저장된 데이터가 없다. 어떤 아이디와 비밀번호가 로그인 수락의 기준인지 모르는 것이다. 그래서 임의로 userid는 scott, pwd는 tiger여야 로그인인 된 것으로 처리하도록 했다.

 

결과출력 화면에 userid 와 user의 이름이 뜨게 할 것이다.

 

로그인 처리가 성공적(true)이라면, name 이름에 "홍길동"을(임의의 값), userid 에는 form 에서 받아온 userid 를 넣어줬다. 그 후 응답처리와 데이터 전달 객체를 RequestDispatcher 객체를 통해 "CH02" 폴더 안에 있는 "092_UserServlet_ok.jsp" 로 forward 하도록 했다.

 

로그인 처리에 실패(false)했다면, "CH02/091_UseServlet.jsp" 로 돌아가 다시 로그인하도록 만들었다.

 

request.getRequestDispatcher("CH02/092_UseServlet_ok.jsp").forward(request, response);

 

forward 문은 위와 같이 한줄로 작성할 수 있다.

 


3-3. 처리결과 페이지(092_UseServlet_ok.jsp)

<h1><%=request.getAttribute("name") %>(<%=request.getAttribute("userid") %>)님이 로그인하셨습니다.</h1>
<h2>저희 사이트에 방문해주셔서 감사합니다!</h2>

▶getAttribute

request 객체에 setAttribute 로 넣어 forward 로 전달한 값을 출력했다.

Attribute 에 값을 넣을 때 저장한 이름을 그대로 작성하면 된다.

( "name" 이란 이름으로 저장했으니 큰따옴표도 똑같이 붙여 "name" 으로 출력한다. )

 

 

RequestDispatcher 객체를 통해 forward로 전달한 데이터는 주소창에 노출되지 않는다. 결과화면에서 주소창에 노출되는 것은 submit 버튼의 action 주소인 서블릿 이름이며, 이마저도 mapping 을 통해 간략화 & 보안에 유리하도록 만들 수 있다.