[Java] Servlet, Cookie, Session, JSP, JSP scripting tag, EL

JH·2023년 4월 18일

Java

목록 보기
13/21

1. TIL

A. Servlet

servlet : 하나의 컨테이너이고 controller의 역할, view의 역할도 할 수 있음

포워딩 방식으로 처리된 url은 첫번째 연결된 url로 검색됨

1. MVC + dynamicWeb

DTO, package, import는 생략함

html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>customer</title>
</head>
<body>
	<h2>Add</h2>
	
	<form action="customer" method="POST">
		id : <input type="text" name="id" > <br />
		pw : <input type="password" name="pw" > <br />
		grade :	<input type="text" name="grade" > <br />
		
		<input type="submit" value="가입">
	</form>
</body>
</html>

Controller

@WebServlet("/customer")
public class CustomerController extends HttpServlet {
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String id = request.getParameter("id");
		String pw = request.getParameter("pw");
		String grade = request.getParameter("grade");
		
		Customer newCustomer = new Customer(id, pw, grade);
		
//		회원 검증 로직
		boolean result = CustomerDAO.checkCustomer(newCustomer);
		System.out.println(result);
		if(result) {
			// 실패 (아이디가 이미 존재)
			response.sendRedirect("fail");
//			response.sendRedirect("fail.html"); // html로 정적 표현으로도 사용 가능
		}else {
			// 성공 (아이디가 없으므로 회원가입)
			CustomerDAO.addCustomer(newCustomer);
			request.getRequestDispatcher("success").forward(request, response);
		}
	}	
}

DAO

// service + dao + db
public class CustomerDAO {
	private static CustomerDAO instance = new CustomerDAO();
	public static CustomerDAO getInstance() {
		return instance;
	}
	
	public static ArrayList<Customer> userData = new ArrayList<Customer>();
	
	static {
		userData.add(new Customer("it1", "it1", "S"));
		userData.add(new Customer("it2", "it2", "A"));
		userData.add(new Customer("it3", "it3", "B"));
		userData.add(new Customer("it4", "it4", "C"));
		userData.add(new Customer("it5", "it5", "D"));
	}
	
	public static ArrayList<Customer> getAllData() {
		return userData;
	}
	
	// 고객을 실제로 추가 하는 메소드
	public static void addCustomer(Customer newCustomer) {
		userData.add(newCustomer);
	}
	
	// 고객이 있는지 없는지 확인하는 메소드 
	public static boolean checkCustomer(Customer newCustomer) {
		for (Customer customer : getAllData()) {
			if(customer.getId().equals(newCustomer.getId())) {
				return true;
			}
		}
		return false;
	}
}

SuccesView

@WebServlet("/success")
public class SuccessView extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter out = response.getWriter();
        
		out.println("환영합니다 " + request.getParameter("id") + "님");	
	}
}

FailView (fail.html을 만들어 대체할 수 있음)

@WebServlet("/fail")
public class FailView extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		
		PrintWriter out = response.getWriter();
		out.println("가입 실패 : 동일한 id 존재");
	}
}

2. Variable

context : 서블릿 컨테이너가 관리하는 모든 영역

//@WebServlet("/var")
// 어노테이션으로 url패턴, 인코딩 지정 (서블릿 변수)
@WebServlet(urlPatterns = {"/var"}, 
			initParams = {@WebInitParam(name="charset", value="UTF-8")})
public class VariableTest extends HttpServlet {
	private static final long serialVersionUID = 1L;
//		int i = 0; 
	// 전체 시스템 (서블릿 객체)에서 공유하는 변수 : 컨텍스트 변수, 서블릿 변수, 전역 변수
	// 서블릿은 쓰레딩을 알아서 해줌
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		int i = 0; // 로컬 변수 : 각각의 작업 단위에서 사용되어지는 변수
		
		// getInitParameter() : 초기 설정된 값을 불러오는 메소드
        // context, config를 통해서도 인코딩 설정을 할 수 있음
        // getServletConfig().getInitParameter(), getServletContext()
		String charset = getInitParameter("charset");
		
		String userId = request.getParameter("userId");
		
		response.setContentType("text/html;charset="+charset);
		PrintWriter out = response.getWriter();
		
		while(i++ < 100) {
			out.println(userId + " : " + i + "<br/>");
			out.flush();
			
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		out.close();
	}
}

int i를 서블릿 변수로 지정하고 서버를 실행
그리고 여러 개의 브라우저로 접속하면 servlet이 쓰레드를 알아서 지정해주는 걸 알 수 있음


B. state (쿠키, 세션)

http 프로토콜 기본 특징 : 상태를 유지 않음 이를 해결하려고 쿠키와 세션을 사용함

클라이언트의 브라우저에 저장됨
Cookie 객체를 만들어 저장하는 방식으로 사용됨

2. Session

서버에 저장됨
request.getSession()을 통해 1번의 조회로 1개의 세션을 만듦

세션의 경우 서비스가 지속되는 이상 세션 객체는 계속해서 존재 → 무효화 처리 해야함

3. Ex🔥

시나리오
login.html -> id 전달
-> controller(/check) : id null?! -> 쿠키,세션 생성 / 저장

-> service(/save) : 추가 쿠키 생성 / 저장, check로 부터 넘어온 세션을 이용해서 추가 정보 저장 (재활용)

-> 1) view(/view) : 쿠키 획득

-> 2) view(/sessionFinal) : 세션 획득
-> view(invalid) : 해당 세션 객체 무효화
-> login.html 이동

html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
	<h1>STATE</h1>
	<form action="check" method="POST">
		id : <input type="text" name="id"> <br/>
		<input type="submit" value="로그인">
	</form>
</body>
</html>

Controller

@WebServlet("/check")
public class IdCheck extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String id = request.getParameter("id");
		
		// step 01 : cookie
		if(id != null) {
			// cookie 객체 생성
			Cookie cookie1 = new Cookie("cookieId", id);
			
			// cookie 시간 설정 : 클라이언트에 저장되어 존재하는 시간 (초)
			cookie1.setMaxAge(60 * 60 * 24);	// 1일
			
			// 클라이언트에 저장
			response.addCookie(cookie1);
			
			// 이동
			response.sendRedirect("save");
		}
		
		// step02 : session, 무조건 하나의 요청에 하나의 세선이 만들어짐
		HttpSession session1 = request.getSession();
		session1.setAttribute("sessionId", id);
		
		response.sendRedirect("save");
	}
}

Service

@WebServlet("/save")
public class StateSave extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// step01 : cookie, 추가 쿠키 생성, 저장
		Cookie cookie2 = new Cookie("cookieGrade", "junior");
		cookie2.setMaxAge(60 * 60 * 24 * 365);	// 1년
		response.addCookie(cookie2);
		
		// step02 : session, 세션을 다시 얻음
		HttpSession session1 = request.getSession();
		System.out.println(session1.getAttribute("sessionId"));
		session1.setAttribute("sessionGrade", "junior");
		
		response.sendRedirect("sessionFinal");
	}
}

/view (쿠키 결과 확인 view)

개발자 도구의 Application 에서 쿠키 확인

@WebServlet("/view")
public class StateView extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Cookie[] cookies = request.getCookies();
		
		for(Cookie cookie : cookies) { // 출력으로 직접 확인
			if ("junior".equals(cookie.getValue())) {
				System.out.println(cookie.getName());
				System.out.println(cookie.getValue());
				System.out.println(cookie.getMaxAge()); // -1 default
			}
		}
	}
}

/sessionFinal (세션 결과 확인)

@WebServlet("/sessionFinal")
public class SessionFinal extends HttpServlet {
	private static final long serialVersionUID = 1L;
       

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=UTF-8");
		
		PrintWriter out = response.getWriter();
		HttpSession session1 = request.getSession();
		
		out.println(session1.getAttribute("sessionId") + "<br/>");
		out.println(session1.getAttribute("sessionGrade") + "<br/>");
		out.println("<button onclick='location.href = \"invalid\"'>logout</button>");
		
		session1.setMaxInactiveInterval(60 * 60 * 10); // 10분
	}
}

/invalid (세션 무효화, 리다이렉트)

@WebServlet("/invalid")
public class SessionInvalidation extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		HttpSession session = request.getSession();
		System.out.println(session.getAttribute("sessionId"));
		
		// 세션 객체 무효화
		session.invalidate();
		session = null;
		
		response.sendRedirect("login.html");
	}
}


C. JSP (Java Server Page)

자바 데이터를 브라우저 화면에 출력할 수 있게 제시된 스펙

JSP 자체에도 컨테이너가 있음 하지만 servlet으로 변환됨

컴파일에 대한 부담을 줄이기 위해 자바 코드는 최소화해야함

1. 특징

  • 확장자 : .jsp
  • 위치 : html과 동일한 경로
  • jsp를 최초로 호출할 경우 web server가 servlet으로 자동 변환
  • 정해진 tag들로 개발
  • 이미 자동 생성되는 내장 객체들 존재

2. JSP scripting, EL

scripting tag

  • <%@ page%> : import, 인코딩 등 설정
  • <%! %> : 선언
  • <%= %> : 출력
  • <% %> : java code 실행문
  • <%-- --%> : 주석

EL (Expression Language)

  • ${} : java 데이터 출력

3. Ex) scripting tag, EL

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>	<!-- @page에 import 해야함 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>step01</title>
</head>
<body>
	<!-- HTML 주석 -->
	<%-- JSP 주석 --%>
	
    <h3>scripting tag</h3>
	
	<%! String name = "dev"; %>
	1. <%= name %> <br/>
	
	2. <% out.println(name); %>
	
	<% int age = 28; %> <br/>
	3. <%= age %>
	
	<!-- action tag는 스킵함 -->
	
	<h3>EL</h3>
    
	1. 2 + 3 = ${2 + 3} <br/>
	2. 2 > 3 = ${2 > 3} <br/>
	3. 'a' == 'a' = ${'a' == 'a'} <br/>
	4. 'a' != 'a' = ${'a' != 'a'} <br/>
	5. param = ${param.id}
	
	<hr/>
	
	<%-- java data 출력 --%>
	<% 
		// Scope : 범위
	
		// pageContext : 현재 페이지 내에 저장
		pageContext.setAttribute("pageData", "현재 페이지에서만 사용 가능");
	
		// request
		request.setAttribute("reqData", "요청 객체 데이터");
		
		// session
		session.setAttribute("sessionData", "세션 객체 데이터");
	%>
	
	6. 현재 페이지에서만 출력 가능 데이터 : ${pageScope.pageData} <br/>
	7. 요청 객체 데이터 : ${requestScope.reqData} <br/>
	8. 세션 객체 데이터 : ${sessionScope.sessionData} <br/>
</body>
</html>

쿠키는 객체를 생성해서 값을 얻어야 함, 그러므로 Scope를 사용하지 않음

jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>step02_EL</title>
</head>
<body>
	<h2>Cookie - EL</h2>
	쿠키 데이터 출력 : ${cookie.id.value}
	<!-- 쿠키를 통해 value를 얻으려면 위 처럼 적어야 함, name을 적으면 key를 얻을 수 있음 -->
</body>
</html>

servlet

@WebServlet("/data")
public class DataSave extends HttpServlet {
	private static final long serialVersionUID = 1L;

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

		Cookie cookie = new Cookie("id", "dev");
		cookie.setMaxAge(60 * 60);
		
		response.addCookie(cookie);
		
		response.sendRedirect("step02_EL.jsp");
		
		// 위 방법으로 세션, request객체 등을 보내줄 수 있음
	}
}


2. 에러

코드 저장 후 서버에 로드가 되었지만 코드가 올바르더라도 404가 에러가 발생함

해결: 서버를 재실행 시킴

터미널에서 colima를 실행이 안되는 상황이 발생함

해결 : 구글링 결과 대부분 comlima 셋팅을 초기화시키는 방법으로 나옴


3. 보완 해야 할 것

EL은 자동완성이 되지 않음으로 해당 문법을 잘 알고 있어야함

Context는 정말 애매하게 전체적으로 작용되는 것으로 알고 있음 해당 부분을 더 자세하게 알아야 할 것 같음

MVC → JDBC + MVC → Servlet + MVC
점점 MVC패턴이 무거워 짐으로 데이터의 흐름을 잘 알아야 할 것 같음


4. 느낀점

점점 java에 대한 숙련도가 올라 가는 느낌이 있음

JSP를 사용해보면서 느끼는 건데 StartView는 프론트엔드와 공동으로 작업해야 될지도 모를 것 같다는 생각이 듦

profile
잘해볼게요

0개의 댓글