JSP/Servlet | 서블릿과 JSP/HTML | redirect을 이용하여 결과를 표시

포워드의 경우, URL 주소 표시 줄에 표시되는 주소는 변경되지 않기 때문에 /mygaeapp로 표시가 그대로인 상태로 hello.jsp의 내용이 표시되게 된다. 뭐, 그래도 크게 문제는 없지만, 리로드를 하게 되면 서블릿의 doGet 표시되어 버린다.

hello.jsp에 제대로 주소를 돌려 보내기 위하여는 포워드가 아닌 “리다이렉트(redirect)“을 이용해야 한다. 그러나 리다이렉트을 사용하는 경우에는 포워드와는 또 다른 형태로 값을 전달하는 방법으로 해야한다.

아래에 이전에 포워드를 사용한 예제를 리다이렉트을 이용하는 형태로 다시 수정하였다.

<%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Sample jsp</title>
<style>
h1{
    font-size: 16pt;
    background: #AAFFAA;
    padding: 5px;
}
</style>
</head>
<body>
    <h1>Hello App Engine!</h1>
    <p>Result: <%=session.getAttribute("result") %></p>
    <hr>
    <p id="msg">정수 입력:</p>
    <form method="post" action="/mygaeapp">
    <table>
        <tr>
            <td>입력</td>
            <td><input type="text" id="input" name="text1" value="<%=session.getAttribute("input") %>"></td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" value="전송"></td>
        </tr>
    </table>
    </form>
</body>
</html>

MyGaeAppServlet.java

package com.devkuma.mygaeapp;

import java.io.*;

import javax.servlet.http.*;

@SuppressWarnings("serial")
public class MyGaeAppServlet4 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/plain");
        request.setCharacterEncoding("utf8");
        response.setCharacterEncoding("utf8");
        PrintWriter out = response.getWriter();
        out.println("Hello, world!");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html");
        request.setCharacterEncoding("utf8");
        response.setCharacterEncoding("utf8");
        String param = request.getParameter("text1");
        PrintWriter out = response.getWriter();
        int result = 0;
        try {
            int n = Integer.parseInt(param);
            for (int i = 1; i <= n; i++) {
                result += i;
            }
        } catch (NumberFormatException e) {
            out.println(e);
        }
        HttpSession session = request.getSession();
        session.setAttribute("input", param);
        session.setAttribute("result", result);
        response.sendRedirect("/hello.jsp");
    }
}

이것을 동작을 시켜보자. 폼을 전송하면 다시 폼의 표시로 돌아와서, 합계가 계산되어 표시된다. 이때, URL 주소는 제대로 hello.jsp로 돌아와 있다. 이것으로 리로드해도 문제 없다.

리다이렉트은 포워드와 달리 더 쉽게 사용할 수 있다. 다음과 같은 메소드를 호출뿐이다.

"HttpServletRequest".sendRedirect(리다이렉트 주소);

포워드에 비해 매우 간단하다. 리다이렉트 주소를 인수로 지정하면 된다. 그러나! 리디렉션을 사용하는 경우, 이동된 곳에서 “HttpServletRequest의 setAttribute를 사용하여 값 전달받기"를 할 수 없다.

HttpServletRequest는 요청을 관리하는 것이다. 포워드는 서버에 표시되는 내용이 변경되기 때문에 요청이 중단될 것은 없다. 그런데 리다이렉트은 HTTP 헤더 정보를 사용하여 브라우저에 지정된 페이지로 이동하는 것이다. 즉, 브라우저가 받은 헤더 정보를 바탕으로 다른 페이지로 이동하는 단계에서 요청이 중단이 된다. 따라서 HttpServletRequest는 거기에서 사라지고 새로운 HttpServletRequest가 다시 제공이 되는 것이다. 그래서 Request의 setAttribue에 값을 보관해도 값을 얻을 수 없다.

그럼 어떻게 해야 하나? 이런 경우를 위해 있는 것이 “세션"이다. 세션은 JSP에서도 조금 사용했었다. 세션은 서버와 클라이언트 간의 지속적인 연결을 유지하기 위한 구조였다.

이 세션은 HttpSession라는 클래스로 준비되어 있다. 이는 request에서 꺼내 올 수 있다.

HttpSession session = request.getSession();

요청에 있는 HttpServletRequest 인스턴스의 “getSession"을 호출하는 것으로, 현재의 세션을 관리하는 HttpSession 인스턴스를 얻을 수 있다. 그리고 이 인스턴스의 “setAttribute"를 호출하여 세션에 값을 저장할 수 있다.

session.setAttribute("input", param);
session.setAttribute("result", result);

이 후에는 JSP 측에서 값을 얻어 오는 부분을 요청에서 세션을 변경하면 된다. 다음과 같은 식이다. JSP는 HttpSession은 “session"라는 암묵적 객체로 사용할 수 있다.

<% = session.getAttribute ( "result") %>
<% = session.getAttribute ( "input") %>

세션는 요청이 지나도 그대로 유지되기 때문에, 리다이렉트가 된 JSP에서도 제대로 값을 꺼내 올 수 있다. 이것으로 안심하고 페이지 이동이 가능해졌다.