본문 바로가기
국비학원

[국비지원] KH 정보교육원 85일차

by 도전하는 개발자 2022. 7. 28.

kh day 085

내장객체 이어서 나가자!

5. application 내장 객체
서블릿 과정에서 학습했던 ServletContext 객체를 참조하는 변수이다. 따라서 로그 및 파일 접근, application scope에 저장되는 속성(attribute)설정등을 구현할 수 있다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <title>count</title>

    <style>
        h2 {
            color : blue;
            background-color: azure;
            font-size: 2em;
            text-align: center;
            border: 5px double red;
            box-shadow: 5px 5px 30px aqua;
        }
    </style>
</head>

<body>
    <h1>/JSP/count.jsp</h1>
    <hr>
    
    <!-- Declaration Tag : 필드나 메소드 선언 -->
    <%! int count; %>

    <%  // Scriptlet Tag : 자바코드로 된 실행문장을 작성
        count++;
        System.out.println(">>> count.jsp : count : " + count);

        application.setAttribute("countValue", count);
    %>
    
    <!-- Expression Tag : 값을 생성 및 출력 -->
    <h2>Visitors: <%= count %></h2>

</body>
</html>

count.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <title>countInfo</title>
</head>

<body>
    <h1>/JSP/countInfo.jsp</h1>
    <hr>

    <h1>방문자 수 조회화면</h1>

    <%  // Scriptlet : App.Scope에 바인딩 되어있는 공유속성(방문자 수)을 얻어서 출력
        // application 내장객체의 타입 : ServletContext 객체
        int visitors = (Integer) application.getAttribute("countValue");
    %>

    <p>현재까지 총 방문자 수: <%= visitors %></p>
</body>
</html>

countInfo.jsp

---

6. session 내장 객체
서블릿 과정에서 학습했던 HttpSession 객체를 참조하는 변수이다. 따라서 장바구니 및 로그인 기능을 구현할 수 있다. 단 page 지시어에서 session="false" 값으로 지정하면 session 내장 객체를 사용할 수 없다. session="true" 값이 기본값이기 때문에 일반적으로 그냥 사용 가능하다.

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>로그인 창</title>
</head>
<body>
    <h1>/loginForm.html</h1>
    <hr>

    <form action="JSP/login.jsp" method="post">
        <fieldset>
            <legend>로그인 폼</legend>
            <ul>
                <li>
                    <label for="userid">아이디</label>
                    <input type="text" name="userid">
                </li>

                <li>
                    <label for="passwd">비밀번호</label>
                    <input type="password" name="passwd">
                </li>

                <li>
                    <input type="submit" value="전송">
                </li>
            </ul>
        </fieldset>
    </form>
</body>
</html>

loginForm.html

 

<%@ page language="java" 
    contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
    // Step1. 전송파라미터 획득
    request.setCharacterEncoding("utf8"); // 내장객체 request 사용
    String userid = request.getParameter("userid");
    String passwd = request.getParameter("passwd");

    // step2. 로그인 처리
    // 무조건 성공이라고 가정(아이디와 암호가 정상 수신된 경우에만)
    if( (userid != null && !"".equals(userid)) &&
        (passwd != null && !"".equals(passwd)) ) { // if normal
        ;;
      } else { // if abnormal
        response.sendRedirect("/loginForm.html");
        System.out.println(">>>>>>>>>> Re-directed <<<<<<<<<<");

        return;     // _jspService() 메소드 블록을 즉시 종료 (깨고 나옴)
      } // if-else

    // step3. 로그인에 성공했다면, 다음으로 과연 무엇을 해야하는가?
    // 현재 로그인 한 웹브라우저와 생명주기가 동일한, Session Scope에
    // 로그인 아이디/암호 2개 정보를 올려 놓기로(공유속성으로 만듦)함.
    session.setAttribute("userid", userid);     // session 내장객체 사용
    session.setAttribute("passwd", passwd);     // session 내장객체 사용

%>

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>login</title>
</head>
<body>
    <h1>/JSP/login.jsp</h1>
    <hr>

    <ul>
        <li>1. 안녕하세요, <%= userid %>님</li>
        <li>2. <a href="/JSP/loginInfo.jsp">로그인 정보 보기</a></li>
    </ul>    
</body>
</html>

login.jsp 

 

<%@ page language="java" 
    contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>loginInfo.jsp</title>
</head>
<body>
    <h1>/JSP/loginInfo.jsp</h1>
    <hr>

    <%
        // 현재의 웹브라우저가 로그인에 성공한 브라우저인지 아닌지 판단하고
        // 로그인에 성공한 웹브라우저라면, "로그아웃"이라는 링크를 생성

        // step1. Session Scope에서 성공로그인정보 (userid, passwd)획득
        // 만일 없다면 리다이렉션을 이용해 로그인 창으로 밀어냄 (로그인 안 된 웹브라우저기 때문)

        String userid = (String) session.getAttribute("userid");
        String passwd = (String) session.getAttribute("passwd");

        if( userid != null && passwd != null ) { // 로그인 성공정보가 유효하다면
        										 // 밑은 자바언어가 아니라 html이기 때문에 여기서 자름
    %>

            <h2><a href="/JSP/logout.jsp">로그아웃</a></h2>

    <%
        } else { 		// 성공 로그인 정보가 없다면 (즉, 아직 로그인되지 못한 웹브라우저라면)
            response.sendRedirect("/loginForm.html");
            System.out.println(">>>>>>>>>> Re-directed <<<<<<<<<<");

            return;		// _jspService() 메소드 블록을 즉시 종료 (깨고 나옴)
        } // if-else
    %>
</body>
</html>

loginInfo.jsp

 

<%@ page language="java" 
    contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
    // step1. 해당 브라우저에 할당된 Session Scope 파괴
    session.invalidate();

    // step2. 로그아웃처리 후에, 웹브라우저는 어느 화면으로 이동할까?
    response.sendRedirect("/loginForm.html");  // Re-direct

    // RequestDispatcher dispatcher = request.getRequestDispatcher("/loginForm.html");
    // dispatcher.forward(request, response); // Request Forwarding

%>

logout.jsp

---

7. exception 내장 객체
JSP페이지 내에서 발생된 예외 클래스인 java.lang.Throwable 객체를 참조하는 변수이다. 용도는 JSP 사용시 예외가 발생된 경우에 예외를 처리하는 JSP 페이지를 따로 구현할 목적으로 사용된다. 주의할 점은 반드시 page 지시어에서 isErrorPage="true"인 경우에만 사용 가능하다. 기본값은 false이기 때문에 반드시 true값으로 설정한후에 사용한다.

 

<%@ page 
    language="java" 
    isErrorPage="false"
	errorPage="exceptionHandling.jsp"
    contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%  // Scriptlet Tag
    int n = 4 / 0;
%>

divide.jsp 

 

<%@ page 
    language="java" 
    isErrorPage="true"
    contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!-- 이 JSP는 다른 JSP에서 발생하는 예외를 내장객체인 exception으로 받아서
예외처리하는 역할을 수행한다. (isErrorPage="true" 인 경우) -->

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>exceptionHandling</title>
</head>
<body>
    <h1>/JSP/exceptionHandling.jsp</h1>
    <hr>

    <h1>Lorem ipsum dolor sit amet.</h1>

    <h2><%= exception %></h2>

    <ol>
        <%
            StackTraceElement[] stackTrace = exception.getStackTrace();

            for(StackTraceElement element : stackTrace) {
        %>
                <li>at <%= element %> </li>

        <% } // enhanced for %>
    </ol>
</body>
</html>

exceptionHandling.jsp



---


***JSP 표준 액션 태그

본적인 스크립팅 요소이외에 JSP 스펙(Specification)에서는 표준 액션 태그를 제공한다. 대표적인 스크립팅 요소인 Scriptlet tag안에는 많은 자바코드가 삽입되어 실행된다. JSP를 사용하는 목적이 Presentation Logic을 구현할 목적이기 때문에 많은 자바코드를 포함하고 있는 Scriptlet tag을 제거 및 감소할 목적으로 액션 태그가 제공되는 것이다. 즉 자바코드 대신에 액션 태그만을 가지고 동일한 결과를 얻을 수 있는 것이다. 추가로 액션 태그만을 가지고는 100% 자바코드를 제거할 수는 없으며 나중에 배울 JSTL 또는 EL 기능을 같이 추가하여 사용된다. 다음은 대표적인 표준 액션 태그 목록이다. 



---

1. 자바빈즈(JavaBeans) 개요 및 규약

자바빈즈(JavaBeans)는 JSP에서 사용되는 데이터를 저장 및 관리하기 위한 컴포넌트를 의미한다. 즉 JSP에서 데이터를 관리하는 부분을 별도의 클래스로 작성하는 것이다. 일반적으로 입력 파리미터 값을 저장 및 관리하기 위해서 사용한다. 작성된 자바빈(JavaBeans)은 JSP의 표준 액션 태그를 사용하여 처리할 수 있으며, JSP코드내에서의 Business Logic과 Presentation Logic을 분리하여 재사용성과 유지보수를 향상 시킬수 있다. 

다음은 자바빈(JavaBeans)을 작성할 때 반드시 지켜져야 하는 규약이다. 
1) public 지정자가 아닌 멤버 변수를 갖는다. 일반적으로 private으로 지정해서 사용하고 프라퍼티(property)라고 부른다. 
2) getter 메소드와 setter 메소드를 갖는다. 
3) 인자없는 생성자(기본 생성자)가 반드시 존재해야 한다. 
4) 직렬화 객체이어야 한다. ( implements Serializable ) (선택)

다음은 로그인할 때 사용되는 데이터 저장을 위한 클래스를 자바빈즈(JavaBeans) 규약에 맞추어 작성한것이다. 일반적으로 많이 사용하던 형식의 클래스이다.

 

package org.zerock.myapp.domain;

import java.io.Serializable;

import lombok.Data;

//@ToString
//@Getter
//@Setter
//@NoArgsConstructor

@Data // 이 어노테이션으로 한번에 자바빈즈 클래스에 필요한 모든 것을 만들 수 있다.
public class LoginBean implements Serializable{
	
	private String userid;
	private String passwd;

} // end class

LoginBean.java

---

2. <jsp:useBean /> 액션 태그
자바빈(JavaBeans)을 JSP에서 사용하기 위한 액션 태그이다. 기본적인 문법은 다음과 같다. 
<jsp:useBean id="빈 이름“ class="패키지 포함한 빈클래스명” scope="범위“ />

id 속성값은 생성된 자바빈을 식별하기 위한 빈 이름이며 class 속성값은 자바빈의 실제 클래스명이다. scope 속성값은 생성된 자바빈(JavaBeans)의 LifeCycle을 지정하기 위한 방법으로서 application, session, request, page 값중에서 사용 가능하고 기본은 page이다. 동작 메커니즘은 해당 scope에 일치하는 id값이 존재하면 재사용하고 없으면 새로 생성한다.

자바빈(JavaBeans) 사용
앞에서 작성했던 LoginBean을 사용하기 위한 방법은 다음과 같다. 
<jsp:useBean id="myBean“ class="com.bean.LoginBean” />

상위 방법은 다음과 일치한다. 즉 자바빈을 사용하기 위해서 객체 생성하는 것이다. 
<%
 LoginBean myBean = new LoginBean();
%>

package org.zerock.myapp.domain;

import java.io.Serializable;

import lombok.Data;

//@ToString
//@Getter
//@Setter
//@NoArgsConstructor

@Data // 이 어노테이션으로 한번에 자바빈즈 클래스에 필요한 모든 것을 만들 수 있다.
public class LoginBean implements Serializable{
	
	private String userid;
	private String passwd;

} // end class

LoginBean.java

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <title>useBean</title>
</head>
<body>
    <h1>/JSP/useBean.jsp</h1>
    <hr>

    <!-- 우선 자바빈즈 객체부터 생성해서 기본 공유영역(page scope)에 바인딩 수행 -->
    <jsp:useBean
        id="myBean"
        class="org.zerock.myapp.domain.LoginBean"
        scope="page" />
    
    
    <h1>useBean 액션태그의 사용실습</h1>
    
    <%  // 자바빈즈 객체의 프로퍼티(속성)에 값을 설정
        myBean.setUserid("John");
        myBean.setPasswd("1234");
    %>

    <!-- LoginBean 자바빈즈 객체의 프로퍼티(속성) 값을 얻어 출력 -->
    <h3> 1. userid : <%= myBean.getUserid() %></h3>
    <h3> 2. passwd : <%= myBean.getPasswd() %></h3>    
</body>
</html>

useBean.jsp


이번엔 자바빈 객체를 Session Scope에 올려보자!

 

package org.zerock.myapp.domain;

import java.io.Serializable;

import lombok.Data;

//@ToString
//@Getter
//@Setter
//@NoArgsConstructor

@Data // 이 어노테이션으로 한번에 자바빈즈 클래스에 필요한 모든 것을 만들 수 있다.
public class LoginBean implements Serializable{
	
	private String userid;
	private String passwd;

} // end class

LoginBean.java

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<jsp:useBean
    id="myBean"
    class="org.zerock.myapp.domain.LoginBean"
    scope="session" />

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>useBeanScope</title>
</head>
<body>
    <h1>/JSP/useBeanScope.jsp</h1>
    <hr>

    <h1>useBean 사용실습</h1>

    <%
        myBean.setUserid("John");
        myBean.setPasswd("1234");
    %>

    1. userid: <%= myBean.getUserid() %> <br>
    2. passwd: <%= myBean.getPasswd() %>

    <p>&nbsp;</p>
    <h3>myBean: <%= myBean %></h3>

</body>
</html>

useBeanScope.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!-- 세션 공유영역에 올라가 있는 로그인 빈 객체를 얻어냄 -->
<!-- 주의 : 이 useBean 액션태그는 빈객체가 이미 지정된 공유영역에 있으면 그 빈 객체를 가져오고, 
            없으면 빈객체를 만들어 지정된 공유영역에 올려놓음 -->

<jsp:useBean
    id="myBean"
    class="org.zerock.myapp.domain.LoginBean"
    scope="session" />

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>useBeanScope2</title>
</head>
<body>
    <h1>/JSP/useBeanScope2.jsp</h1>
    <hr>

    <h1>useBean 사용실습</h1>

    1. userid: <%= myBean.getUserid() %> <br>
    2. passwd: <%= myBean.getPasswd() %>

    <p>&nbsp;</p>
    <h3>myBean: <%= myBean %></h3>
    
</body>
</html>

useBeanScope2.jsp


---

3. <jsp:setProperty /> 액션 태그
자바빈(JavaBeans)을 초기화하기 위해서 사용된다. 기본적인 문법은 다음과 같다. 
<jsp:setProperty name="빈 이름“ property="프라퍼티 이름” value="값“ />

name 속성값에는 <jsp:useBean />태그의 id값을 지정하고 property 속성값에는 자바빈의 멤버변수를 지정한다. value 속성값에는 멤버변수에 저장할 값을 지정한다.

 

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<jsp:useBean id="myBean" class="org.zerock.myapp.domain.LoginBean" scope="page" />
<jsp:setProperty name="myBean" property="userid" value="john" />
<jsp:setProperty name="myBean" property="passwd" value="1234" />

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>useBeanSet</title>
</head>
<body>
    <h1>/JSP/useBeanSet.jsp</h1>
    <hr>

    <h1>useBean 사용실습</h1>

    1. userid : <%= myBean.getUserid() %> <br>
    2. passwd : <%= myBean.getPasswd() %>

    <p>&lt;jsp:getProperty/&gt;액션태그로 출력한다면</p>
    1. userid : <jsp:getProperty name="myBean" property="userid" /> <br>
    2. passwd : <jsp:getProperty name="myBean" property="passwd" /> 
    
</body>
</html>

useBeanSet.jsp