JAVA/JAVA개발자 양성과정

[Servlet/JSP] 페이지 이동 삼총사 - Forwarding, Redirect, Include

728x90
반응형

👩‍💻 자바 개발자 양성과정 26, 27일차

  1. Servlet에서 데이터 검사해서 이전페이지로 되돌리기(Redirect/Forword)
  2. 프로젝트 path가져오기
  3. request.getContextPath() 
  4. Forwarding, Redirect, Include
  5. 쿠키/세션

 


 

26일차 9/28

오늘 너무 어려워서 약간.. 멘붕이다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ😨


import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;


public class BufferedReaderTest {
	public static void main(String[] args) {
		BufferedReader br = null;
		PrintWriter pw = null;
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream("C:/io/data1.txt"), "utf-8"));
			pw = new PrintWriter("C:/io/data1_copy.txt");

			String str = null;
			//파일에 더이상 읽어들일 데이터가 없을때 null을 냄
			while ((str = br.readLine()) != null) {
				pw.println(str);
				pw.flush();
			}
			System.out.println("복사완료임!");

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (br != null)
					br.close();
				if (pw != null)
					pw.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
}

 

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

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/getData")
public class GetDataServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// 1. 요청 파라미터를 구한다.
		String name = request.getParameter("name").trim();
		String age = request.getParameter("age").trim();

		// 3. 이름이나 나이가 작성되지 않은 경우 이전페이지로 돌아간다.
		// 4. "/servletWebApp" = request.getContextPath()
		if (name.equals("") || age.equals("")) {
			response.sendRedirect(request.getContextPath() + "/getData.html");
		} else {
			// 2. 컨텐트 타입을 설정한다.
			response.setContentType("text/html; charset=utf-8");

			PrintWriter pw = response.getWriter();
			pw.println("<html><body>");
			pw.println("이름은" + name + "나이는" + age + "주소:" + request.getContextPath());
			pw.println("</html></body>");
		}
	}
}
response.sendRedirect(request.getContextPath() + "/getData.html");

리다이렉트 방식

리다이렉트 방식은 주소가 바뀐다.


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

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(value = "/postData")
public class PostDataServlet extends HttpServlet {
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// post로 받아온 데이터는 받자마자 인코딩을 바꿔줘야 한다.
		// get으로 받아온 데이터는 출력할때 인코딩을 바꿔주기만 하면 된다.
		request.setCharacterEncoding("utf-8");
		String name = request.getParameter("name");
		String email = request.getParameter("email");

		if (name.equals("") || email.equals("")) {
			// http://localhost:8080/servletWebApp/postData.html로 이동하지 않고
			// http://localhost:8080/servletWebApp/postData로 이동함
			RequestDispatcher dispatch = request.getRequestDispatcher("/postData.html");
			dispatch.forward(request, response);
		} else {

			response.setContentType("text/html; charset=utf-8");
			PrintWriter pw = response.getWriter();
			pw.println("<html><body>");
			pw.println("이름" + name + "이메일" + email);
			pw.println("</html></body>");
			pw.close();
		}
	}
}
RequestDispatcher dispatch = request.getRequestDispatcher("/postData.html");
dispatch.forward(request, response);

 

 

포워딩 방식

4번처럼 서버에서 페이지가 이동하기 때문에, 주소가 바뀌지 않는다.

 

 

 



27일차 9/29

🎡 Forwarding 상황 이해하기 - 요청/응답을 다른 파일에서 하기

forward.html ForwardServlet.java ➡ NextForwardServlet.java

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Get 방식</title>
</head>
<body>
	<form action="/servletWebApp/forward" method="get">

		이름 : <input type="text" name="name"><br>
		나이 : <input type="text" name="age"><br>
		<button type="submit">전송</button>
		<button type="reset">취소</button>

	</form>
</body>
</html>

주소를 자세히보자. forword.html

🔽

 

forward.html ➡ ForwardServlet.java ➡ NextForwardServlet.java

import java.io.IOException;

import javax.security.auth.message.callback.PrivateKeyCallback.Request;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/forward")
public class ForwardServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
   
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		//디스패치(포워딩) 방식으로 nextForwardServlet으로 제어를 이동한다.
		RequestDispatcher dispatcher = request.getRequestDispatcher("/nextForward"); 🎁
		dispatcher.forward(request, response);
	}

}

🎁 RequestDispatcher dispatcher = request.getRequestDispatcher("/nextForward");
dispatcher.forward(request, response);

해당 부분에 ("/nextForward")와 맵핑된 부분으로 포워딩된다.

🔽

forward.html ➡ ForwardServlet.java ➡ NextForwardServlet.java

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

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/nextForward")
public class NextForwardServlet extends HttpServlet {
    
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		//1.컨텐트 타입을 설정한다.
		response.setContentType("text/html; charset=utf-8");
		
		//2. 요청 파라미터를 구한다.
		String name = request.getParameter("name");
		String age = request.getParameter("age");
		
		//3. 문자기반 출력 스트림을 통해서 클라이언트에 응답한다.
		PrintWriter pw = response.getWriter();
		pw.println("<html><body>");
		pw.println("이름"+name+"나이"+age);
		pw.println("</body></html>");
		pw.close();
	}

}

해당 파일에서 클라이언트 출력이 된다.

 

포워딩은 주소가 그대로 forward.html이고, 파라미터 정보가 유지되어 넘어온다.

 

forward.html ➡ ForwardServlet.java ➡ NextForwardServlet.java

해당 과정에서 파라미터가 끝까지 포워딩되어서 출력되는 것이 보인다.

브라우저 주소 또한 변함없다.


(⭐ Redirect와 가장 큰 차이점)

🎡 Forwarding 이해하기 - 요청 과정끼리 특정 속성값을 전달하기 

forward.html ➡ ForwardServlet.java ➡ NextForwardServlet.java

import java.io.IOException;

import javax.security.auth.message.callback.PrivateKeyCallback.Request;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/forward")
public class ForwardServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
   
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		
		//request 영역에 userEmail이라는 속성으로 사용자 이메일 정보를 저장한다.
		request.setAttribute("userEmail", "java@gmail.com"); 🎁
		
		//디스패치(포워딩) 방식으로 nextForwardServlet으로 제어를 이동한다.
		RequestDispatcher dispatcher = request.getRequestDispatcher("/nextForward");
		dispatcher.forward(request, response);
	}

}

🎁 request.setAttribute("userEmail", "java@gmail.com"); - 속성값을 셋팅한다.

ForwardServlet.java에서 속성값을 전달하면 끝까지 포워딩되어 정상적으로 출력된다.

 

 

 

forward.html ➡ ForwardServlet.java ➡ NextForwardServlet.java

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

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/nextForward")
public class NextForwardServlet extends HttpServlet {
    
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		//1.컨텐트 타입을 설정한다.
		response.setContentType("text/html; charset=utf-8");
		
		//2. 요청 파라미터를 구한다.
		String name = request.getParameter("name");
		String age = request.getParameter("age");
		
		//3. request 영역에 userEmail이라는 속성으로 사용자 이메일 정보를 불러온다.
		String userEmail = (String) request.getAttribute("userEmail"); 🎁
		
		//3. 문자기반 출력 스트림을 통해서 클라이언트에 응답한다.
		PrintWriter pw = response.getWriter();
		pw.println("<html><body>");
		pw.println("이름" + name + "나이" + age + "이메일" + userEmail);
		pw.println("</body></html>");
		pw.close();
	}

}

🎁 String userEmail = (String) request.getAttribute("userEmail"); - 속성값을 get한다.

 

포워딩의 경우 중간에 속성값으로 준 이메일이 출력된다.

 

진행경로 ➡ forward.html ForwardServlet.java NextForwardServlet.java 브라우저
작동 1.폼 입력 1. "userEmail"은 "java@gmail.com"라는 속성값 설정
2. NextForwardServlet.java 포워딩
1. 파라미터와 속성이 값을 브라우저로 돌려줌(response) name
age
userEmail
정보 name - 파라미터
age - 파라미터
name - 파라미터
age - 파라미터
userEmail - 속성
name - 파라미터
age - 파라미터
userEmail - 속성

🎡 Redirect 이해하기 - 요청 과정끼리 특정 속성값을 전달하기 

 

redirect.htmlRedirectServlet.java ➡ NextRedirectServlet.java

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Get 방식</title>
</head>
<body>
	<form action="/servletWebApp/redirect" method="get">

		이름 : <input type="text" name="name"><br>
		나이 : <input type="text" name="age"><br>
		<button type="submit">전송</button>
		<button type="reset">취소</button>

	</form>
</body>
</html>

주소를 자세히 보자 redirect.html

 

 

redirect.html ➡ RedirectServlet.java ➡ NextRedirectServlet.java

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// request 영역에 userEmail이라는 속성으로 사용자 이메일 정보를 저장한다.
		request.setAttribute("userEmail", "java@gmail.com");

		response.sendRedirect(request.getContextPath() + "/nextRedirect"); 🎁
	}

}

🎁 response.sendRedirect(request.getContextPath() + "/nextRedirect"); 

request.getContextPath() : 프로젝트 Path만 가져온다.

 

 

redirect.html ➡ RedirectServlet.java ➡ NextRedirectServlet.java

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

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/nextRedirect")
public class NextRedirectServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

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

		String userEmail = (String) request.getAttribute("userEmail");
		
		// 3. 문자기반 출력 스트림을 통해서 클라이언트에 응답한다.
		response.setContentType("text/html; charset=utf-8"); 
		PrintWriter pw = response.getWriter();
		pw.println("<html><body>");
		pw.println("이름" + name + "나이" + age + "이메일" + userEmail);
		pw.println("</body></html>");
		pw.close();
	}

}

리다이렉트는 주소가 nextRedirect 로 바뀌고, 파라미터 정보를 못가져왔다. 

 

진행경로 ➡ redirect.html RedirectServlet.java NextRedirectServlet.java 브라우저
작동 1.폼 입력 1. "userEmail"은 "java@gmail.com"라는 속성값 설정
2. NextRedirectServlet.java 포워딩
1. 파라미터와 속성이 값을 브라우저로 돌려줌(response) null
정보 name - 파라미터
age - 파라미터
name - 파라미터
age - 파라미터
userEmail - 속성
null

 


🎡 Include 이해하기

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Get 방식</title>
</head>
<body>
	<form action="/servletWebApp/include" method="get">

		이름 : <input type="text" name="name"><br>
		나이 : <input type="text" name="age"><br>
		<button type="submit">전송</button>
		<button type="reset">취소</button>

	</form>
</body>
</html>
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/include")
public class IncludeServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// 1. 컨텐트 타입을 설정한다.
		response.setContentType("text/html; charset=utf-8");

		PrintWriter pw = response.getWriter();
		pw.print("<h1>call before nextIncludeServlect</h1>");

		// 디스패치(포워딩) 방식으로 nextForwardServlet으로 제어를 이동한다.
		RequestDispatcher dispatcher = request.getRequestDispatcher("/nextInclude");
		dispatcher.include(request, response);
		
		pw.print("<h1>call after nextIncludeServlect</h1>");
		pw.close();
	}

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

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class NextIncludeServlet
 */
@WebServlet("/nextInclude")
public class NextIncludeServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

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

		
		// 1. 컨텐트 타입을 설정한다.
		response.setContentType("text/html; charset=utf-8");

		PrintWriter pw = response.getWriter();
		pw.println("이름" + name + "나이" + age);
	}

}


쿠키

- 사용자 정보를 웹 브라우저가 실행되는 클라이언트 PC 에 저장한다. (파일)

- (name, value) 쌍으로 이루어진 정보

- 저장 정보 용량 제한 - 보안 취약

- 도메인당 쿠키가 생성된다.

- 서블릿에서 javax.servlet.http.Cookie제공한다.

 

쿠키 생성 과정

1. 브라우저로 사이트에 접속한다.

2. 서버는 정보를 저장한 쿠키를 생성한다.

3. 생성한 쿠키를 브라우저로 전송한다.

4. 브라우저는 서버로부터 받은 쿠키를 파일에 저장한다.

5. 재접속 시, 서버는 브라우저에게 쿠키를 요청하고, 브라우저는 서버로 쿠키를 보낸다.

6. 서버는 쿠키를 이용해서 작업한다.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Cookie</title>
</head>
<body>
	<!-- 쿠키일때는 아래코드 -->
	<form action="/servletWebApp/login" method="post"> 

	<!-- 세션일때는 아래코드 -->
	<!-- <form action="/servletWebApp/loginHandler" method="post">-->
		아이디 : <input type="text" name="id"><br> 비밀번호 : <input
			type="password" name="pwd"><br>
		<button type="submit">로그인</button>
		<button type="reset">취소</button>
	</form>
	<script>
	</script>
</body>
</html>
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
	
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		request.setCharacterEncoding("utf-8");
		String id = request.getParameter("id");
		String pwd = request.getParameter("pwd");

		if(id.equals("") || pwd.equals("")) {
			response.sendRedirect(request.getContextPath() + "/loginForm.html");
		}else {
			// DB에서 해당 사용자가 존재하는 사용자인지 확인한다.
			boolean isMember = true;

			// 존재하는 사용자인 경우 쿠키를 생성한다.
			if (isMember) {
				// 쿠키 생성
				Cookie cookie = new Cookie("userId", id);
				cookie.setMaxAge(60 * 60 * 24); // 1일
				response.addCookie(cookie);

				// 리다이렉트를 하는 이유는 cookie를 생성한 이후 브라우저로 전송해줘야 브라우저에 저장하여 쿠키를 사용할 수 있기 때문임
				response.sendRedirect(request.getContextPath() + "/loginSuccess");
			} else {
				// 존재하는 회원이 아닌 경우
				response.sendRedirect(request.getContextPath() + "/loginForm.html");
			}
		}
	}
}

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

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/loginSuccess")
public class LoginSuccessServlet extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		//1.Request 헤더에서 생성한 쿠키 정보를 가져온다.
		Cookie[] cookies = request.getCookies();
		
		String userId = null;
		
		//헤더에서 생성된 쿠키정보가 있는 경우
		if(cookies != null) {
			for (Cookie cookie : cookies) {
				//헤더에 저장된 쿠키에서 회원 ID값을 가져온다.
				if(cookie.getName().equals("userId")) {
					userId = cookie.getValue();
					break;
				}
			}
		}
		
		//(잘못된 접근) 생성된 쿠키가 없거나 쿠키에 저장된 ID값이 없는 경우, 로그인 페이지로 돌아간다.
		if(userId == null || cookies == null) {
			response.sendRedirect(request.getContextPath() + "/loginForm.html");
		}else {
			//정상적인 로그인
			response.setContentType("text/html; charset=utf-8");
			PrintWriter pw = response.getWriter();
			pw.println(userId + "님이 로그인되었습니다");
			pw.println("<a href='"+request.getContextPath() + "/logout'>로그아웃</a>");
			pw.close();
		}
	}
	
}

Session 소개

· 세션은 웹 브라우저 당 하나가 생성된다. (SessionID)

· 세션은 사용자 정보를 서버 메모리에 저장하므로 쿠키에 비해 보안에 강하다.

· 세션은 세션 아이디를 sessioncookie(웹 브라우저 메모리에 생성)로 관리하며 세션 아이디 는 server가 종료되거나, 유효기간이 만료하거나, clientbrowser가 종료되면 삭제된다.

- 서블릿에서 javax.servlet.http.HttpSession제공한다.

 

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Cookie</title>
</head>
<body>
	<!-- 쿠키일때는 아래코드 -->
	<!-- <form action="/servletWebApp/login" method="post"> -->

	<!-- 세션일때는 아래코드 -->
	<form action="/servletWebApp/loginHandler" method="post">
		아이디 : <input type="text" name="id"><br> 비밀번호 : <input
			type="password" name="pwd"><br>
		<button type="submit">로그인</button>
		<button type="reset">취소</button>
	</form>
	<script>
	</script>
</body>
</html>

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@WebServlet("/loginHandler")
public class LoginHandlerServlet extends HttpServlet {
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		String id = request.getParameter("id");
		String pwd = request.getParameter("pwd");
		
		if(id.equals("") || pwd.equals("")) {
			response.sendRedirect(request.getContextPath() + "/loginForm.html");
		}else {
			boolean isMember = true;
			
			if(isMember) {
				//http 세션 객체 생성
				//http세션영역객체에 uesrId라는 속성을 아이디 정보로 바인딩한다.
				HttpSession session = request.getSession();  //true
				session.setAttribute("userId", id);
				System.out.println("LoginHandlerServlet" + session.getId());
				
				response.sendRedirect(request.getContextPath() + "/loginSuccessHandler");
			}else {
				response.sendRedirect(request.getContextPath() + "/loginForm.html");
			}
		}
	}

}

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

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class LoginSuccessHandler
 */
@WebServlet("/loginSuccessHandler")
public class LoginSuccessHandler extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		//1. https 세션을 불러온다.
		HttpSession session = request.getSession();
		
		String userId = (String) session.getAttribute("userId");
		System.out.println("userId" + userId);
		
		if(userId == null){
			response.sendRedirect(request.getContextPath() + "/loginForm.html");
		}else {
			response.setContentType("text/html; charset=utf-8");
			
			PrintWriter pw = response.getWriter();
			pw.write(userId + "님, 안녕하세요.");
			pw.println("<a href='"+request.getContextPath() + "/logoutHandler'>로그아웃</a>");
			pw.close();
		}
		
	}
	
}
728x90
반응형