[신세계I&C KDT][Servlet/JSP] #33 서블릿 Scope, JSP (EL, JSTL) (0522, 0523, 0524)

박현아·2024년 5월 22일
0

신세계아이앤씨 KDT

목록 보기
37/42

REST API

1. 서블릿 요청 처리

1) request.getParameter("name")

2) request.getParameterValues(String name) : String[]

예> checkbox
check된 값만 서버에 전달이 된다

3) request.getParameterNames() : Enumeration< String>

이름을 먼저 조회하고 나중에 값을 얻을 수 있다

cf) java.util.Iterator vs java.util.Enumeration

  • Iterator 사용 방법
while (ite.hasNext()){
	ite.next();
}
  • Enumeration 사용 방법
Enumeration<String> enu = request.getParameterNames();
		
while(enu.hasMoreElements()) {
	String name = enu.nextElement();
	String value = request.getParameter(name);
	System.out.println(name +" "+ value);
}

2. 서블릿의 Scope (Lifecycle)

1) 개요

  • 자바의 변수에서 사용했던 scope와 비슷
  • 예>
    로컬 변수 : 메서드 호출 ~ 메서드 종료
    인스턴스 변수 : 객체 생성 ~ 객체 소멸
    클래스 변수 (static) : 프로그램 실행 ~ 종료

2) 서블릿에서 사용하는 3가지 scope

2-1) Request scope

  • HttpServletRequest

(1) 데이터 저장 기능도 포함

setAttribute(String name, Object o) 로 저장
getAttribute(String name) 로 조회
removeAttribute(String name) 로 삭제
getAttributeNames() 로 name부터 조회

(2) 저장된 데이터의 life cycle

  • 요청 & 응답이 끝나면 사라진다
  • 예>
1번 요청 (/SetServlet)

웹브라우저 ------------------> 
        doGet(HttpServletRequest req,...){
                request.setAttribute("request", "홍길동");
                String request_scope = (String)request.getAttribute("request");
        }

2번 요청 (/GetServlet)

웹브라우저 ------------------>
        doGet(HttpServletRequest req,...){
        		String request_scope = (String)request.getAttribute("request"); // null 반환
        }

2-2) Session scope

  • HttpSession

(1) 데이터 저장 기능도 포함

setAttribute(String name, Object o) 로 저장
getAttribute(String name) 로 조회
removeAttribute(String name) 로 삭제
getAttributeNames() 로 name부터 조회

(2) HttpSession 얻는 방법 (로그인 기능 처리)

  • HttpSession session = request.getSession();
  • HttpSession session = request.getSession(true);
    ==>세션이 있으면 현재 세션 반환, 없으면 생성해서 반환
  • HttpSession session = request.getSession(false);
    ==>세션이 있으면 현재 세션 반환, 없으면 null 반환

(3) 저장된 데이터의 life cycle

  • 실행한 웹브라우저와 scope가 같다
  • 요청한 웹브라우저 전체를 닫지 않으면 session에 저장된 정보는 계속 유지됨
  • tomcat이 요청하는 웹브라우저의 정보를 알고 있다 (JSESSIONID 값을 이용)
                         id전송
			 JSESSIONID=5B5C1DC28B5133BE0E7B19931C4EC058
웹브라우저(크롬) ---------------------> Tomcat (요청한 크롬 웹브라우저 id 저장함)

	                 id전송
			 JSESSIONID=12F7E322D0401F556A4A27F4B0610037
웹브라우저(엣지) ---------------------> Tomcat (요청한 엣지 웹브라우저 id 저장함)

(4) time-out 설정

  • 이론적으로는 요청한 웹브라우저가 close 되지 않으면 서버에 저장된 세션 (HttpSession)은 제거되지 않는다. 하지만 보안 이슈 때문에 브라우저를 닫지 않아도 일정 시간이 지나면 자동으로 세션을 삭제시킨다
  • tomcat의 기본 time-out은 30분이다 (servers > web.xml에 있음)

(5) 명시적으로 time-out 설정 가능

  • 1- web.xml에서 설정 (단위는 분)
    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>
  • 2- 자바 코드로 설정 (단위는 초)
    session.setMaxInactiveInterval(60*60); // 3600초, 1시간

(6) 명시적으로 세션 데이터 삭제

  • 세션 엔트리 삭제
    예> 장바구니에 저장된 요소 삭제하는 경우
	session.removeAttribute("key");
  • 세션 전체 삭제 (HttpSession)
    예> 로그아웃 할 때
	session.invalidate()

2-3) Application scope

  • ServletContext

(1) 데이터 저장 기능도 포함

setAttribute(String name, Object o) 로 저장
getAttribute(String name) 로 조회
removeAttribute(String name) 로 삭제
getAttributeNames() 로 name부터 조회

(2) 저장된 데이터의 life cycle

  • Tomcat과 scope가 같다 (정확히는 Web Module에 올라간, 실행 중인 Context와 scope가 동일)

(3) HttpServlet 얻는 방법

  • HttpServlet (ServletConfig) 에서 제공되기 때문에 doGet 메서드 내에서 getServletContext() 사용하면 됨
  • 예>
    doGet( , ) {
        ServletContext application = getServletContext();
        application.setAttribute("application", "유관순");
	}

3. JSP (Java Server Page)

1) 특징

  • 동적 컴포넌트 (서버에서 실행되어 동적으로 결과를 만듦)
  • *.jsp 확장자를 가짐
  • 서블릿은 요청하면 doGet/doPost 같은 서비스가 실행됨
  • JSP는 요청하면 세 단계를 거쳐서 실행됨
    변환 단계 (.jsp -> .java : 서블릿과 매우 유사한 코드)
    -> 컴파일 단계 (*.java -> *.class)
    -> 실행 단계 (*.class -> 결과 반환 : html로)

2) JSP 구성 요소

2-1) html

2-2) JSP 태그

(1) directive 태그

1- page directive 태그
: JSP에게 정보를 알려줄 때 (contentType, import 등)
: 여러 번 사용 가능
<%@ page 속성명="속성값" 속성명="속성값" ... %>
: 예>

  <%@ page contentType="text/html; charset=utf-8" %> 
		==> 서블릿의 response.setContentType("text/html;charset=utf-8") 기능
  <%@ page import="java.util.ArrayList" %>
		==> 서블릿의 import java.util.ArrayList;

2- include directive 태그
: 화면을 재사용할 때
<%@ include file="속성값" %>
3- taglib directive 태그
<%@ taglib prefix="속성값" uri="속성값" %>

(2) declaration 태그

  • 인스턴스 변수 / 메서드 만들 때 (거의 사용 X)
  • <%! 자바 코드 (인스턴스변수 | 메서드) %>
    : 예>
<%! 
int num = 10; // 인스턴스 변수
public void a(){ // 인스턴스 메서드
	System.out.println(num);
} 
%>

(3) scriptlet 태그

  • 서비스 메서드 (doGet/doPost) 내에서의 코드 (매우 많이 사용됨)
  • <% 자바 코드 %>
  • 여러 번 사용 가능
  • 변환하면 항상 _jspService(HttpServletRequest request, HttpServletResponse response) 가 자동 생성됨
  • 항상 자동으로 선언되는 변수
    • HttpSession session;
      ServletContext application;
      ServletConfig config;
      JspWriter out; // PrintWrtier 동일 기능
        <%
        // 내장변수 (내장객체) 라고 부른다
        request.메서드
        response.메서드
        session.메서드
        application.메서드
        config.메서드
        out.print("값");
        %>
  • 예>
<%
int num = 10;
int[] arr = {10,20};
for(int k : arr) {
	System.out.println(k);
}
%>

<%
String userid = request.getParameter("userid");
HttpSession session = request.getSession();
request.setCharacterEncoding("utf-8");
%>

(4) expression 태그

  • <%= 변수 (값) %>
  • <% out.print("값"); %> 과 동일한 기능

2-3) EL 태그 (Expression Language) ★

(1) 문법

  • ${ 표현식(값) | key }
    => servlet에서 scope에 저장할 때 사용된 key 값

(2) 기능 및 특징

  • 브라우저에서 출력됨

  • 리터럴값:리터럴값이브라우저에출력{리터럴값} : 리터럴값이 브라우저에 출력{리터럴값+1} : 산술 연산 가능
    리터럴값>1:비교연산가능{리터럴값 > 1} : 비교 연산 가능{리터럴값 >1 && 리터럴값 <20} : 논리 연산 가능

  • ${ key } ★
    서블릿에서 scope에 저장할 때 지정한 key값으로 자동으로 key에 해당하는 데이터를 얻고 웹브라우저에 출력함
    - 서블릿 작업
    request.setAttribute("userid", "홍길동");
    - JSP 작업
    가. <% %> 이용

		<%
		String userid =
		(String)request.getAttribute("userid");
		out.print(userid);
		%>

나. %{key} 이용

		${userid} // 훨씬 간단함
  • DTO 사용
    - 서블릿
    request.setAttribute("user", new User("홍길동", 20));
    • JSP
    	<%
		   User user = (User)request.getAttribute("user");
		   String username = user.getUsername();
		   int age = user.getAge();
		%>
        
		이름: <%= username %>
		나이: <%= user.getAge() %>
		
		이름: ${user.username}
		나이:  ${user.age}
  • List 사용
    - 서블릿
    	List<User> list = Arrays.asList(new User("홍길동1", 20),
					    new User("홍길동2", 30));
		
	    request.setAttribute("userList", list);
  • JSP
		<%
		List<User> list = (List<User>)request.getAttribute("userList");

		/* User user1 = list.get(0);
		User user2 = list.get(1); */
		%>
         
		user1 이름 : <%= list.get(0).getUsername() %>
		user1 나이 : <%= list.get(0).getAge() %>
		user2 이름 : <%= list.get(1).getUsername() %>
		user2 나이 : <%= list.get(1).getAge() %>

		${userList}
		user1 이름 : ${userList[0].username}
		user1 나이 : ${userList[0].age}
		user2 이름 : ${userList[1].username}
		user2 나이 : ${userList[1].age}

(4) 명시적인 scope 지정 가능

request scope : ${requestScope.userid}
session scope : ${sessionScope.userid}
application scope : ${applicationScope.userid}

2-4) JSTL 태그 (Jsp Standard Tag Library) ★

(1) 개요

  • 여러 커스텀 태그를 추려서 표준 (standard)로 제공. 이 표준화된 커스텀 태그를 JSTL이라고 부른다

  • 다양한 기능 제공 (반복, 조건,...)

  • 정확히는 JSTL은 spec임

  • EL과 같이 사용됨

  • JSP에서 커스텀 태그를 사용

  • 커스텀 태그 작성 방법
    java 클래스 + 태그 정의서 (TLD 파일)
    => .class + .tld
    (*.jar)

(2) JSTL spec의 구현체 (Apache에서 제공)

  • jakarta.apache.org에서 다운로드
    https://tomcat.apache.org/taglibs/standard/
  • 최신 버전 : standard 1.2
    사용하는 버전 : standard 1.1 (이유는 샘플 제공하기 때문에, standard-examples.war)
  • 압축 풀고 lib 폴더의 2개 jar 파일을 생성된 웹 프로젝트 WEB-INF/lib 폴더에 붙영넣기 한다

(3) 사용 방법

1- lib 폴더에서 2개의 jar 파일 복사
2- 서블릿 만들고 scope에 저장
=> scope에 저장된 데이터를 EL + JSTL 이용해서 핸들링함
3- JSP 파일에 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 붙여넣어야 사용 가능!!

4. 화면 재사용

1) include directive 태그 이용 (정적인 방법)

<body>
	내용
	<hr>
	<%@ include file="copyright.jsp" %>
</body>

2) jsp:include 액션 태그 이용 (동적인 방법)

<body>
	내용
	<hr>
	<jsp:include page="copyright.jsp" flush="true">
</body>

5. 서블릿에서 JSP로 위임 ★

1) 개요

  • 서블릿
    대부분이 자바 코드 + 약간의 html (번거로움)
    비즈니스 로직 처리를 잘 함
  • JSP
    대부분이 html + 약간의 자바 코드
    자바 코드 작업은 <% %> 태그 사용해야됨
    화면 처리를 잘 함

2) 구조

				 요청
웹브라우저  ---------------->  서블릿
								|
                                |  위임 처리 (요청)
                                |
          <-----------------   JSP
          		 응답

3) 위임 처리 방법 두 가지

(1) 리다이렉트 (Redirect)

  • HttpServletResponse 이용
  • 문법
public void doGet (HttpServletRequest request, HttpServletResponse response) {
	response.sendRedirect("타겟");
}
  • 작동 방식
           1- 요청 (/xxx)
웹브라우저  ------------------>  MainServlet("/xxx") 
								  2- doGet실행
                                   HttpServletRequest request (100번지) 생성
						 		   request(100번지).setAttribute("xxx","홍길동")
                                  3- response.sendRedirect(" a.jsp");
           <--------------
	        4- 응답 (서블릿이 응답)

             5- 재요청(a.jsp)
            ----------------->  a.jsp   HttpServletRequest request 200번지)
            <------------------         request.getAttribute("xxx"); null 반환
	              6- 응답
  • url이 변경됨 (/xxx --> a.jsp)
  • 서블릿에서 request scope에 저장된 데이터는 리다이렉트된 jsp에서 참조 불가 (null 반환)
    따라서 session scope 또는 application scope를 사용해야 됨

(2) 포워드 (Forward)

  • HttpServletRequest 이용
  • 문법
public void doGet (HttpServletRequest request, HttpServletResponse response) {
	RequestDispatcher dis = request.getRequestDispatcher("타겟");
	dis.forward(request, response);
}
  • 작동 방식
								서버
               1- 요청
웹브라우저  ------------------> MainServlet("/xxx") 
							       2- doGet실행
                                 HttpServletRequest request(100번지) 생성
						         request(100번지).setAttribute("xxx","홍길동")
                                     |
				     				 |  3- 포워드 위임 (요청)
                              		request.getRequestDispatcher("a.jsp")
				              		dis.forward(request(100번지), response);
	         <-----------------   a.jsp
  	                     		<%
				 				request(100번지).getAttribute("xxx")
			     				%>
  • forward 방식은 서블릿을 요청할 때 생성했던 request를 jsp로 위임할 때도 재사용한다. 하나의 request로 서블릿과 jsp를 요청하는 방식
  • 서블릿에서 request.setAttribute(key,value)로 저장된 데이터를 JSP에서 request.getAttribute(key) 하면 value를 얻을 수 있다
  • 브라우저 url 변경 안 됨. 서블릿맵핑값으로 계속 유지

6. MyBatis 연동

1) SE 버전 아키텍쳐

						  EmpService(인터페이스)
JComponent04_JTextField <---> EmpServiceImpl <---> EmpDAO <---> MySQL 
(main 메서드)
  • 2개의 jar 파일을 build path로 설정

2) EE 버전 아키텍쳐

				  EmpService(인터페이스)
EmpListServlet <---> EmpServiceImpl <---> EmpDAO <---> MySQL 
	  |
      |
   list.jsp
  • 2개의 jar 파일을 build path로 설정하지 않고 WEB_INF/lib 폴더에 jar 복사한다. 자동으로 build path 됨

7. 세션 관리 (session tracking, 연결 관리)

: 클라이언트 (웹브라우저)와 서버 (tomcat) 연결 관리

1) HTTP 프로토콜 특징

  • connectionLESS
  • stateLESS

2) 방법 두 가지

클라이언트						서버
브라우저						a.jsp (데이터:홍길동)	
						   	   b.jsp 
                           
클라이언트에 저장 : 쿠키			서버에 저장 : 세션
Cookie 이용				      HttpSession 이용

(1) a.jsp가 해야되는 작업 (데이터 저장 역할 - 로그인)

  • HttpSession 얻기
    HttpSession session = request.getSession([true]);
    (세션 있으면 반환, 없으면 생성해서 반환)
    HttpSession session = request.getSession(false);
    (세션 있으면 반환, 없으면 null 반환)
  • 데이터 저장
    session.setAttribute("x","홍길동");

(2) b.jsp가 해야되는 작업 (데이터 사용 역할)

  • HttpSession 얻기
HttpSession session = request.getSession();
  • 데이터 얻기
String n = (String)session.getAttribute("x");
if(n!=null) {
	System.out.println(n.length); -> 에러 발생할 수 있음
} else {
	// a.jsp를 거치도록 처리해야된다 (로그인 작업)
	response.sendRedirect("a.jsp");
}
  • 세션 삭제
    엔트리 삭제 : session.removeAttribute("x"); (저장 영역은 남겨놓는 것)
    세션 자체 삭제 : session.invalidate(); => 다 삭제, 로그아웃시 사용
    time-out 지정 삭제 : session.setMaxInactiveInterval(초);

0개의 댓글