MVC패턴이란?

  • 구현된 개발코드를 의미하는게 아니라, 어플리케이션 개발 시 디자인과 로직은 분리시켜 개발해야 추후 변경사항이 발생했을 때 많은 리소스(개발시간, 인력)를 소모하지 않고 유지보수할 수 있다는 IT의 전해 내려오는 개발방법이론(개발패턴)
  • 자바로 구현한 MVC패턴을 모델2방식이라 한다.
  • ms개발자, .net개발자도 사용 즉, 어떠한 개발에도 사용되는 방식

 

Model

  • 중립적 로직이라서 스윙, 웹 모두 사용할 수 있는 중립적 코드  일반클래스로 정의하면 된다.
  • DAO, DTO와 같은 클래스들이라고 말할 수 있다.

View

  • 디자인적인 요소를 담당하는 부분이다.
  • JSP와 같이 태그들이 들어가는 코드라고 말할 수 있다.

Controller

  •  로직인 Model과 디자인인 View를 분리시키기 위한 용도
  • 웹이건, 응용프로그램이건 모든 컨트롤러 5대역할 

                     1. 요청을 받는다. 
                     2. 요청을 분석한다.. 
                     3. 알맞는 로직 객체에게 일을 시킨다.(지가 직접안함) 
                     4. 일 시킨 후(3단계) 결과가 있다면 결과를 보관한다. 
                     5. 디자인에 그 결과를 반영한다.

  • Servlet과 같은 클래스이다.

 

게시판목록페이지의 코드로 예를 들어보자

 

아래의 코드는 게시판목록의 View담당하는 JSP코드이다. 

DAO와 같은 클래스를 가지고 있지 않다.

<%@page import="com.webapp1216.board.model.Notice"%>
<%@page import="com.webapp1216.common.board.Pager"%>
<%@page import="java.util.List"%>
<%@ page contentType="text/html;charset=utf-8"%>
<%
	List<Notice> list = (List<Notice>)session.getAttribute("noticeList");
	Pager pager = new Pager();
	pager.init(request, list); // 페이지 처리에 대한 계산!!
%>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
table {
	border-collapse: collapse;
	border-spacing: 0;
	width: 100%;
	border: 1px solid #ddd;
}

th, td {
	text-align: left;
	padding: 16px;
}

tr:nth-child(even) {
	background-color: #f2f2f2;
}

img{
	width:100px;
}
</style>
</head>
<body>

	<table>
		<tr>
			<th>No</th>
			<th>제목</th>
			<th>작성자</th>
			<th>작성일</th>
			<th>조회수</th>
		</tr>
		<%int num = pager.getNum(); %>
		<%int cusPos = pager.getCurPos(); %>
		<%for(int i=0;i<pager.getPageSize();i++){ %>
			<%if(num<1)break; %>
				<%Notice notice= list.get(cusPos++); %>
				<tr>
					<td><%=num-- %></td>
					<td><a href="/board/detail?notice_id=<%=notice.getNotice_id()%>"><%=notice.getTitle() %></a></td>
					<td><%=notice.getWriter() %></td>
					<td><%=notice.getRegdate() %></td>
					<td><%=notice.getHit() %></td>
				</tr>
		<%} %>
		  <tr>
			<td colspan="6" style="text-align: center">
			<%if(pager.getFirstPage()-1<=0){ %>
				<a href="javascript:alert('처음페이지입니다.')">◀</a>
			<%}else{ %>
			<a href="list.jsp?currentPage=<%=pager.getFirstPage()-1%>">◀</a>
			<%} %>
				<%for(int i=pager.getFirstPage();i<=pager.getLastPage();i++) {%>
					<%if(i<=pager.getTotalPage()){ %>
						<a href="list.jsp?currentPage=<%=i%>">[<%=i %>]</a>
					<%} %>
				<%} %>
				<%if(pager.getLastPage()>=pager.getTotalPage()){ %>
				<a href="javascript:alert('마지막페이지입니다.')">▶</a>
			<%}else{ %>
				<a href="list.jsp?currentPage=<%=pager.getLastPage()+1%>">▶</a>
			<%} %>
			</td>
		</tr>
		 -<tr>
			<td colspan="6">
				<button type="button" onClick="location.href='regist_form.jsp'">글등록</button>
			</td>
		</tr>
	</table>

</body>
</html>

 

아래의 코드는 M와 V를 연결해주는 역할의 Controller이다.

어떠한 디자인적인 요소가 들어가지 않았다.

/*
 * javaEE 개발패턴 중 mvc패턴을 적용한 개발방법을 가리켜 model2방식이라 일컫는다.
 * 특히 jsp가 디자인에 사용되고 있으며, 웹 상의 요청을 받고 응답이 가능한 서블릿이 컨트롤러로서 역할을 수행하게 된다.
*/
package com.webapp1216.board.controller;

import java.io.IOException;
import java.util.List;

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

import com.webapp1216.board.model.Notice;
import com.webapp1216.board.model.NoticeDAO;

//클라이언트의 목록요청을 처리하는 서블릿 정의!!
public class ListServlet extends HttpServlet{
	NoticeDAO dao = new NoticeDAO();
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		List<Notice> list = dao.selectAll();
		//어떻게 list.jsp까지 살려서 보낼까???
		//세션? 클라이언트가 브라우저 프로세스를 닫지 않거나, 일정 시간내에 재접속했을 때 서버측의 메모리에
		//담겨진 정보를 사용할 수 있는 기술...(새로운 접속인 경우 세션 객체를 새로 생성되고, 세션아이디가 새롭게 발급됨..)
		//session을 어케 가져오지?
		//jsp에서의 session내장객체는 자료형이 HttpSession이다!!
		HttpSession session = request.getSession();//이 요청과 관련한 세션을 얻는다!
		session.setAttribute("noticeList", list);//세션 객체에 보관!
		
		
		//결과페이지 선택
		response.sendRedirect("/board/list.jsp");
	}
}

 

아래의 코드는 DAO를 담당하는 모델의 코드이다.

DB와의 연결을 통해 요청에 대한 응답하기위한 데이터를 처리하는 부분이다.

package com.webapp1216.board.model;

import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.webapp1216.mybatis.config.MybatisConfigManager;

public class NoticeDAO {
	MybatisConfigManager manager = MybatisConfigManager.getInstance();
	
	// CRUD

	public List<Notice> selectAll() {
		List<Notice> list =null;
		SqlSession sqlSession = manager.getSqlSession();
		list = sqlSession.selectList("Notice.selectAll");
		manager.close(sqlSession);
		return list;
	}
}

 

'프로그래밍 > JSP' 카테고리의 다른 글

JSP | 서블릿(Servlet) 이해  (0) 2020.12.16
JSP | session  (0) 2020.12.16
JSP | 커넥션풀(Connection Pool)  (0) 2020.12.11
JSP | MyBatis 사용해보기  (0) 2020.12.10
JSP - 페이징 이해  (0) 2020.12.08

서블릿(Servlet)이란?

오직 웹서버에서만 해석 및 실행될 수 있는 JavaEE기반의 클래스이다.

 

서블릿의 생명주기

생명주기는 init(), service(), destory() 로 이해할 수 있다.

  • init() : 생성자 호출 후, 서블릿의 초기화 작업때문에 톰캣에 의해
    호출
  • service() : 동시에 많은 클라이언트의 요청을 처리하는 메서드이고, 
    동시에 호출되려면, 쓰레드에 의해 호출됨
  • destory() : 서블릿 소멸시점에 호출, 주로 서블릿이 보유하고 있는 자원들을
    반납하는 용도에 사용..

서블릿의 계보

자식                                        부모                                   할아버지

HttpServlet ( 웹용, 추상클래스) -> GenericServlet(추상클래스) -> Servlet(인터페이스)

 

쉽게 말하면 위와 같이 설명할 수 있다. 

Servlet인터페이스는 간단한 추상메서드들로만 구성되어있다.

GenericServlet은 Servlet보다 더 많은 메서드들로 구성되어있으며, Sun사에서 서블릿을 개발할 때 단순히 Http 즉 웹용으로만 개발하는 것이 아니라 더 방범위한 분야에서 사용할 수 있도록 GenericServlet과 같은 틀을 제공한다.

 

HttpServlet은 웹용의 서블릿을 개발할 때 사용되는 클래스이며, get, post.. 등 다양한 요청에 대해 대응할 수 있는 doGet, doPost.. doXXXX와 같은 메서드들을 지원해준다.

 

JSP는 서블릿이다.

JSP는 사실 서블릿이였다. 

JSP에는 지시영역, 선언부, 스크립틀릿, 표현식의 영역이 존재한다. 사실 서블릿의 영역들 중 한 부분인 것이였다.

<%@ page contentType="text/html;charset=utf-8"%>
<%!
	//멤버메서드, 멤버변수 .. 멤버란? 클래스에서 인스턴스가 갖는 변수, 메서드 작성하는 영역
	int x=5;
	public void test(){
	}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
<style></style>
<script></script>
</head>
<body>
난 jsp야!!
</body>
</html>

위와 같은 JSP파일이 사실은 

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/8.5.61
 * Generated at: 2020-12-15 02:23:06 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {


	//멤버메서드, 멤버변수 .. 멤버란? 클래스에서 인스턴스가 갖는 변수, 메서드 작성하는 영역
	int x=5;
	public void test(){
	}

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private static final java.util.Set<java.lang.String> _jspx_imports_packages;

  private static final java.util.Set<java.lang.String> _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet<>();
    _jspx_imports_packages.add("javax.servlet");
    _jspx_imports_packages.add("javax.servlet.http");
    _jspx_imports_packages.add("javax.servlet.jsp");
    _jspx_imports_classes = null;
  }

  private volatile javax.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public java.util.Set<java.lang.String> getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set<java.lang.String> getClassImports() {
    return _jspx_imports_classes;
  }

  public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
    if (_el_expressionfactory == null) {
      synchronized (this) {
        if (_el_expressionfactory == null) {
          _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
        }
      }
    }
    return _el_expressionfactory;
  }

  public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
    if (_jsp_instancemanager == null) {
      synchronized (this) {
        if (_jsp_instancemanager == null) {
          _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
        }
      }
    }
    return _jsp_instancemanager;
  }

  public void _jspInit() {
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {

    final java.lang.String _jspx_method = request.getMethod();
    if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP들은 오직 GET, POST 또는 HEAD 메소드만을 허용합니다. Jasper는 OPTIONS 메소드 또한 허용합니다.");
      return;
    }

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=utf-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write('\r');
      out.write('\n');
      out.write("\r\n");
      out.write("<!DOCTYPE html>\r\n");
      out.write("<html>\r\n");
      out.write("<head>\r\n");
      out.write("<meta charset=\"utf-8\">\r\n");
      out.write("<title>Insert title here</title>\r\n");
      out.write("<style></style>\r\n");
      out.write("<script></script>\r\n");
      out.write("</head>\r\n");
      out.write("<body>\r\n");
      out.write("난 jsp야!!\r\n");
      out.write("</body>\r\n");
      out.write("</html>");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try {
            if (response.isCommitted()) {
              out.flush();
            } else {
              out.clearBuffer();
            }
          } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

서블릿 클래스로 웹컨테이너가 변환시켜 실행하는 것이다!!! 놀라지 않을 수가 없다!!

 

단지 JSP는 디자인적인 코드를 편히 하기위해 만들어낸 기술일 뿐이다!!!

 

'프로그래밍 > JSP' 카테고리의 다른 글

JSP | MVC패턴에 대한 이해  (0) 2020.12.16
JSP | session  (0) 2020.12.16
JSP | 커넥션풀(Connection Pool)  (0) 2020.12.11
JSP | MyBatis 사용해보기  (0) 2020.12.10
JSP - 페이징 이해  (0) 2020.12.08

웹사이트의 로그인 성공 시 해당 사용자의 정보를 어떻게 가지고 있어야할까?

 

이는 세션쿠키를 이용해서 가지고 있을 수 있다!

 

즉 쉽게 말해서 클라이언트측에 남느냐 서버에 기록이 남느냐에 따라 쿠키(과자부스러기=흔적)이나 세션이냐

클라이언트에 흔적남기기 = 쿠키(Cookie)

서버에 흔적남기기 = 세션(Session)

 

우리는 Session에 대해 알아볼 것 이다.

 

정말 쉽게 말해보자면 클라이언트가 서버에 요청하면 해당 클라이언트에 이름표(?)를 붙여놓는다고 할 수 있다.

이제 그 이름표를 가지고 정보를 가지고 올 수 있다.

 

코드를 보면서 이해해보자!

아래의 예제는 클라이언트측의 코드(jsp)이다.

session.getAttribute(); 라는 코드가 의심스럽다.

파라미터로 값들을 구별할 수 있는 id값을 넣는 것이다. 서버측 코드를 보면 바로 이해할 수 있을 것이다.

<%@page import="admin.member.Admin"%>
<%@ page contentType="text/html;charset=utf-8"%>
<%
	//세션에서 데이터 꺼내기
	out.print("당신이 사용하고 있는 세션객체는 "+session);
	Admin admin = (Admin)session.getAttribute("ad");
	
	//만일 admin VO가 null이면? 인증을 거치지 않거나, 세션이 만료된 상황이므로, 현재
	//페이지에 대한 접근 자체를 막아야한다..
	if(admin!=null){
%>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<%@ include file="/admin/inc/head.jsp" %>
<style>

</style>
</head>
<body>
<div><a href="#"><%=admin.getMid() %></a>님 반갑습니다.</div>
<a href="/admin/logout.jsp">로그아웃</a>
<%@include file="/admin/inc/topnavi.jsp" %>
<div style="padding-left:16px">
  <h2>Top Navigation Example</h2>
  <p>Some content..</p>
</div>

</body>
</html>
<%}else{%>
<script>
alert('올바르지 않은 접근입니다.');
history.back();
</script>
<%}%>

 

이제 서버측의 코드를 보자

단순히 서버에 저장된 id와 password랑 클라이언트측에서 파라미터로 보낸 id와 passsword가 같으면 세션에 저장을 한다.

session.setAttribute("세션ID", 저장할 객체(?)); 

<%@page import="admin.member.Admin"%>
<%@ page contentType="text/html;charset=utf-8"%>
<%@include file="/inc/lib.jsp" %>
<%
	/* 
	원래는 데이터베이스에서 조회를 해야하지만, 추후 하기로 하고
	일단은 스트링으로 비교해본다..
	*/
	String admin_id = "scott";
	String admin_pass="1234";
	
	String mid = request.getParameter("mid");
	String password = request.getParameter("password");
	
	if(admin_id.equals(mid)&&admin_pass.equals(password)){
		//로그인 성공에 대한 보상, 관리자 페이지 보여주기
		//js의 location.href와 동일한 기능의 jsp 기능 이용해보자
		Admin admin = new Admin();
		admin.setMid(mid);
		admin.setPassword(password);
		
		//jsp의 내장객체인 session객체는 클라이언트가 신규접속이라고 생각할 때, 새로운 session
		//인스턴스를 생성하고 세션 ID도 생성하여 세션에 부여한다..
		//이 세션은 클라이언트가 브라우저를 종료하지 않거나, 일정시간내에 재접속을 할 경우 계속
		//사용할 수 있다.. 따라서 웹은 stateless기반이지만, 서버측 메모리에 생성된 세션을 이용
		//하면 마치 연결이 유지된 것처럼 보여질 수 있다. 주용도) 로그인 후 회원정보를 모든 페이지에서
		//사용할 수 있는 기능, 장바구니 등에 사용..
		session.setAttribute("ad", admin);
		System.out.println("로그인 요청 시 사용중인 "+session);
		response.sendRedirect("/admin");//클라이언트로 하여금 지정한 url로 요청을 시도
	}else{
		out.print(getMsgBack("로그인 정보가 일치하지 않습니다"));
	}
%>

 

실행결과

 

위 코드를 이해한다면 DB와 연결하고 위와 비슷하게 세션을 저장하면 끝~

'프로그래밍 > JSP' 카테고리의 다른 글

JSP | MVC패턴에 대한 이해  (0) 2020.12.16
JSP | 서블릿(Servlet) 이해  (0) 2020.12.16
JSP | 커넥션풀(Connection Pool)  (0) 2020.12.11
JSP | MyBatis 사용해보기  (0) 2020.12.10
JSP - 페이징 이해  (0) 2020.12.08

지금까지 DAO를 쓸 때마다 Connection객체를 생성하고 해당 메서드가 끝나면 자원을 해제하고를 반복했다.

//접속 개체 얻기 
	public Connection getConnection(){
		Connection con=null;//return 시키기 위해..
		try{
		Class.forName(driver);
		System.out.println("드라이버 로드 성공");

		con = DriverManager.getConnection(url, user,password);
	
		}catch(ClassNotFoundException e){
			e.printStackTrace();
			System.out.println("드라이버 로드 실패");
		}catch(SQLException e){
			e.printStackTrace();	
		}
		return con;
	}

	//자원해제
	public void release(Connection con){//쿼리문 수행 안했을 때..
		if(con!=null){
			try{
				con.close();	
			}catch(SQLException e){
				e.printStackTrace();
			}
		}
	}

 

웹페이지를 만들어서 많은 사람들이 사용한다고 생각해보면 많은 사람들이 페이지에 접속하고 사용할 때마다
Connection을 받고 바로 해제하고 이러한 과정이 반복된다.
DB로부터 Connection을 얻는 행동은 엄청난 자원을 필요로 하는데 (쿼리, 유저맞어?, 권한?...)
우리는 지금까지 그런 소중한 자원을 썻다 바로 버리고 있었다....;;; 

 

이런 고충을 해결하기 위해 Connection Pool을 이용해보자

 

나는 Tomcat에서 지원하는 Connection Pool을 사용했다.

1) server.xml

    <!--톰캣서버의 server.xml 파일을 열어서 GlobalNamingResources태그 안에 넣어준다-->
    <!--myoracle은 개발자 마음대로 선언해주면 된다.-->
    <Resource name="jdbc/myoracle"
		auth="Container"
		type="javax.sql.DataSource"
        <!--driver의 위치-->
		driverClassName="oracle.jdbc.driver.OracleDriver"
        <!--사용하는 DB의 url-->
		url="jdbc:oracle:thin:@localhost:1521:XE"
        <!--유저의 id-->
		username="lastuser"
        <!--유저의 비밀번호-->
		password="lastuser"
		maxActive="20"
		maxIdle="10"
		maxWait="3000"/>

2) web.xml

	<resource-ref>
	<res-ref-name>jdbc/myoracle</res-ref-name><!--server.xml에서 썼던 이름와 동일하게!-->
	<res-type>javax.sql.DataSource</res-type>
	<res-auth>Container</res-auth>
	</resource-ref>

3) tomcat/context.xml

<ResourceLink type="javax.sql.DataSource"
                      name="jdbc/myoracle"
                      global="jdbc/myoracle" />
                      <!--여기도 이름을 동일하게!!-->

4) 사용방법 (테스트)

<html>
<head>
<%@ page
import="java.sql.*,
javax.sql.*,
java.io.*,
javax.naming.InitialContext,
javax.naming.Context" %>
</head>
<body>
<h1>JDBC JNDI Resource Test</h1>

<%
/*
JNDI란? 
JAVA Naming Directory interface : 어떤 정보를 프로그래밍 언어인 자바코드에 넣지 말고, 외부의 xml과 같은 자원으로 관리하는 방법 
(즉, 자바코드 안에 설정정보를 넣지 말고, 코드 밖으로 빼서 유지관리하자!)  server.xml
*/

InitialContext initCtx = new InitialContext(); //검색 객체
DataSource ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/myoracle"); //검색객체가 안에 내용을 찾는다. server.xml의 datasource를 찾아나선다
//새로운 접속이 아니라, 이미 풀에 존재하는 접속 객체를 대여하는 것!
Connection conn = ds.getConnection();//커넥션풀로부터 하나의 커넥션을 얻는 작업!! 

Statement stmt = conn.createStatement();
ResultSet rset = stmt.executeQuery("select * from board");
while (rset.next()) {
out.println("title=="+rset.getString("title")+"<br>");
}
rset.close();
stmt.close();
conn.close();
initCtx.close();
%>
</body>
</html>

 

JNDI란?

JAVA Naming Directory Interface : 어떤 정보를 프로그래밍 언어인 자바코드에 넣지 않고 외부의 xml과 같은 자원으로 관리하는 방법  (즉, 자바코드 안에 설정정보를 넣지 말고, 코드 밖으로 빼서 유지관리하자!) 

ex) server.xml, web.xml ..?

 

DataSource?

  • Connetion Pool을 관리하기 위한 객체!!!
  • Connection 획득과 반환 등의 작업을 한다! 
<Resource name="jdbc/myoracle"
		auth="Container"
		type="javax.sql.DataSource"
        <!--driver의 위치-->
		driverClassName="oracle.jdbc.driver.OracleDriver"
        <!--사용하는 DB의 url-->
		url="jdbc:oracle:thin:@localhost:1521:XE"
        <!--유저의 id-->
		username="lastuser"
        <!--유저의 비밀번호-->
		password="lastuser"
		maxActive="20"
		maxIdle="10"
		maxWait="3000"/>
  • 위의 server.xml에서 넣어줬던 코드는 DataSource를 의미! (type="javax.sql.DataSource")

'프로그래밍 > JSP' 카테고리의 다른 글

JSP | 서블릿(Servlet) 이해  (0) 2020.12.16
JSP | session  (0) 2020.12.16
JSP | MyBatis 사용해보기  (0) 2020.12.10
JSP - 페이징 이해  (0) 2020.12.08
JSP - 이미지 업로드  (0) 2020.12.04

dependency를 사용하지 않고 jar파일을 사용해보았다.

 

1. mvnrepository로 들어가 Mybatis검색 후 원하는 버전의 jar파일을 다운받는다.

Maven Repository: org.mybatis » mybatis » 3.4.6 (mvnrepository.com)

2. 자신의 웹프로젝트의 WEB-INF의 lib폴더에 등록!

 

정리한 순서

1. 설정xml을 만들어서 DB의 정보(driver, url, user, password)를 기입하고 mapper들의 위치도 등록한다.

 

 

 

2.  Mapper(VO명Mapper.xml)XML을 만들어서 namespace(메모리상에서 이름을 가지고 구분할 수 있게)를 등록하고 
각 쿼리문을 입력 이때 id는 쿼리 구분id, parameteType은 파라미터의 자료형(int, VO객체), resultType은 결과타입(List를 반환하는 쿼리일지라도 해당 List안의 들어갈 객체들의 자료형을 적어주면됨, List처리는 Mybatis가 담당!!)

 

그리고, PreparedStatement에서 ?를 #{}로 대신하여 쓰고 #{}안에는 파라미터명을 적어주면 된다.. (이때, 파라미터명은 파라미터가 1개일 때는 아무거나 적어도 상관이 없지만 구분하기 쉽게 해당 컬럼명으로 써주는게 좋은거같구, VO로 넘어오는 매개변수면 해당 테이블의 컬럼명을 써줘야한다!!  그리고 가장 중요한 VO와 테이블의 컬럼명들을 일치시켜주는게 제일 중요!!)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 이름으로 메모리 영역을 구분하는 법 namespace 중복되면 안된다 -->
<mapper namespace="mybatis.config.Dept">
	<!--
	개발자는 Mybatis를 이용할 경우, 자바코드에서 쿼리문을 작성하지 않으며
	수많은 jdbc관련 코드 또한 작성할 필요가 없고, 오직 쿼리문에만 집중하면 된다!
	-->
	<!--모든글 가져오기 -->
	<!-- List는 자체적으로 만들어준뎨!!! -->
	<select id="selectAll" resultType="emp.model.Dept">
		select * from dept order by deptno asc
	</select>
	
	<!-- 한건 가져오기 -->
	<!-- paramertType : 파라미터자료형 -->
	<!-- ?대신 #{파라미터명} -->
	<select id="select" parameterType="int" resultType="emp.model.Dept">
		select * from dept where deptno=#{deptno}
	</select>
	
	<!-- 한건 등록 -->
	<insert id="insert" parameterType="emp.model.Dept">
		insert into deptno(dname, loc) values(#{dname}, #{loc})
	</insert>
	
	<!-- 한건 수정 -->
	<!-- 반드시 VO와 컬럼명이 일치해야함!! -->
	<update id="update" parameterType="emp.model.Dept" >
		update dept set dname=#{dname}, loc=#{locg} where deptno=#{deptno}
	</update>
	
	<!-- 삭제하기 -->
	<delete id="delete" parameterType="int">
		delete from deptno where deptno=#{deptno}
	</delete>
</mapper>

3. 지금까지 DAO를 JDBC에 따라 만들었지만 이제는 MyBatis의 코드기술을 따라만들어보았다.

Mapper를 사용하려면 SqlSession객체가 필요하다!! SqlSession객체는 SqlSessionFactory객체를 이용하여 .openSession()메서드를 이용한다. 그리고 Mapper에서 만든 쿼리문을 사용하려면 id가 필요한데 id앞에 해당 Mapper의 namespace의 이름이 필요!!

 

MybatisManager 클래스는 설정파일을 연결하여 SqlSessionFactory를 만들고 get메소드를 이용해 사용할 수 있게 해주는 클래스

/*
	DB 접속 정보 및 매퍼들에 대한 위치가 지정된 마이바티스의 설정파일을 읽어보자!!
*/
package db;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MybatisManager {
	private SqlSessionFactory sqlSessionFactory;
	
	public MybatisManager() {
		String resource = "mybatis/config/config.xml";
		InputStream inputStream;
		try {
			inputStream = Resources.getResourceAsStream(resource);
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
			System.out.println(sqlSessionFactory);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public SqlSessionFactory getSqlSessionFactory() {
		return sqlSessionFactory;
	}

	public static void main(String[] args) {
		new MybatisManager();
	}
}
/*
	지금까지는 DAO의 코드 기술을 JDBC로 이용하였기 때문에 쿼리문보다 그 외의 코드가 더 장황했었다..
	따라서 이번 DAO에서는 Mybatis 프레임웍을 도입하여, 코드를 보다 간결하게 작성해보겠다..
*/
package emp.model;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import db.MybatisManager;

public class DeptDAO {
	//DAO에서 SQL문이 들어있는 xml을 호출하자!!! 이떄, 어떤 쿼리수행을 원하는 지를 구분하기 위해서는
	// xml 태그에 부여한 id를 이용하면 된다!!!
	//xml 태그를 호출하기 위해서는 mybatic의 SqlSession이 필요하고, 현재는 MybatisManager 클래스의 멤버로
	//두었다...
	MybatisManager manager = new MybatisManager();
	SqlSessionFactory factory;
	
	public DeptDAO() {
		factory = manager.getSqlSessionFactory();
	}
	
	//모든 데이터가져오기
	public List<Dept> selectAll() {
		SqlSession session = factory.openSession();//쿼리문 수행객체 생성
		return session.selectList("mybatis.config.Dept.selectAll");
	}
}

실행결과

jsp파일을 만들어서 페이지로드 시 list들을 불러오도록 해보았다.

<%@page import="emp.model.Dept"%>
<%@page import="java.util.List"%>
<%@page import="emp.model.DeptDAO"%>
<%@ page contentType="text/html;charset=utf-8"%>
<%
	//DAO 이용하여 부서 정보 출력해보자!!!
	DeptDAO dao = new DeptDAO();
	List<Dept> list = dao.selectAll();
	
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
<style></style>
<script></script>
</head>
<body>
-----------------------------------------
	<%for(int i=0;i<list.size();i++){ %>
	<%Dept dept = list.get(i); %>
	<br>
		부서번호<%=dept.getDeptno()%><br>
		부서명<%=dept.getDname()%><br>
		부서위치<%=dept.getLoc()%><br>
		-----------------------------------------
	<%} %>
</body>
</html>

'프로그래밍 > JSP' 카테고리의 다른 글

JSP | session  (0) 2020.12.16
JSP | 커넥션풀(Connection Pool)  (0) 2020.12.11
JSP - 페이징 이해  (0) 2020.12.08
JSP - 이미지 업로드  (0) 2020.12.04
JSP - JSP(Java Server Page)란?  (0) 2020.12.01

테이블의 모든 레코드들을 가져와서 페이징 처리하기

 

필요한 값

1. totalRecord : 전체 레코드 수

2. pageSize : 한 페이지 당 보여줄 레코드 수

3. totalPage : 총 페이지 수

4. blockSize : 한 블럭(1~10페이지 이런 식으로 나누는?)당 보여질 페이지 수

5. currentPage : 현재 페이지

6. firstPage : 블럭의 시작 페이지

7. lastPage : 블럭의 끝 값 (firstPage와 lastPage를 이용하여 반복문을 사용해 블럭 나타낼 수 있다)

8. num : 페이지당 시작 번호

9. curPos : 페이지 당 List에서의 시작 index (List로 DB에서 레코드들을 받아올 경우)

 

구하는 방법

totalRecord : 총 레코드의 수 ex) list.size() = 26

pageSize : 10 (개발자 마음대로)

totalPage : 26개의 글을 각 페이지 당 10개의 글로 나오게 한다면?

=>(int)Math.ceil((float)totalRecord/pageSize) = 3

firstPage : currentPage-(currentPage-1)%blockSize 

lastPage : firstPage+(blockSize-1)

num : totalRecord-(pageSize*(currentPage-1))

curPos : pageSize*(currentPage-1)

 

예시 코드

<%@page import="board.model.QnA"%>
<%@page import="java.util.List"%>
<%@page import="board.model.QnADAO"%>
<%@ page contentType="text/html;charset=utf-8"%>
<%
	//DB연동
	QnADAO dao = new QnADAO();
	List<QnA> list = dao.selectAll();
	
	int totalRecord=list.size();//총 레코드 수, 실제 DB에 있는 데이터 수를 대입하면 된다!!
	int pageSize=10;//한 페이지당 보여줄 레코드 수
	//int totalPage=(totalRecord%pageSize)==0?(totalRecord/pageSize):(totalRecord/pageSize)+1;
	int totalPage = (int)Math.ceil(((float)totalRecord/pageSize)); //총 페이지 수
	int blockSize=10; //한 블럭 당 보여질 페이지 수
	int currentPage=1; //현재 페이지
	
	//아래의 코드는 아무때나 하는게 아니다!! 누군가 파라미터를 넘겼을 때만..
	if(request.getParameter("currentPage")!=null){//즉 페이지를 넘겼다면
		currentPage=Integer.parseInt(request.getParameter("currentPage"));
	}
	
	//int firstPage=((currentPage/blockSize)*blockSize)+1; 
	int firstPage=currentPage-(currentPage-1)%blockSize;//반복문의 시작값
	//int lastPage=((currentPage/blockSize)+1)*blockSize;
	int lastPage=firstPage+(blockSize-1);// 반복문의 끝값
	int num=totalRecord-(pageSize*(currentPage-1));//페이지당 시작 번호 ( 힌트: 위에 있는 모든 변수 조합)
	int curPos=pageSize*(currentPage-1);//페이지당 List에서의 시작 index 
%>
<%="totalRecord : "+ totalRecord+"<br>" %>
<%="pageSize : "+ pageSize+"<br>" %>
<%="totalPage : "+ totalPage +"<br>" %>
<%="blockSize : "+ blockSize+"<br>" %>
<%="currentPage : "+ currentPage +"<br>" %>
<%="firstPage : "+ firstPage+"<br>" %>
<%="lastPage : "+ lastPage +"<br>" %>
 <%="num : "+ num +"<br>" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>페이징 처리</title>
<style>
table {
  border-collapse: collapse;
  border-spacing: 0;
  width: 100%;
  border: 1px solid #ddd;
}

th, td {
  text-align: left;
  padding: 16px;
}

tr:nth-child(even) {
  background-color: #f2f2f2;
}

button {
  background-color: #4CAF50;
  color: white;
  padding: 12px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:hover {
  background-color: #45a049;
}

input[type=image]{
  width:100px;
 
}

img{
box-sizing: border-box;
}

a{
	text-decoration: none;
}

.pageNum{
	font-size:20pt;
	color:red;
	font-weight:bold;
}
</style>
<script></script>
</head>
<body>
<table>
  <tr>
    <th>No</th>
    <th>제목</th>
    <th>작성자</th>
	<th>등록일</th>
	<th>조회수</th>
  </tr>
	<%for(int i=1;i<=pageSize;i++){ %>
  		<%if(num<1) break; %>
  		<%
  		//break문을 만나지 않았다는 것은 레코드가 있다는 것이므로, break문 아래에서 데이터를 추출하자!! 
  			QnA qna = list.get(curPos++); //1page:0~9, 2page:10~19...
  		%>
		  <tr>
				<td><%=num-- %></td>
				<td>
					<%if(qna.getDepth()>0){ %>
						<img alt="" src="/images/reply.png" style="margin-left:<%=20*qna.getDepth()%>px">
					<%} %>
					<a href="/qna/detail.jsp?qna_id=<%=qna.getQna_id()%>"><%=qna.getTitle()%></a>
				</td>
				<td><%=qna.getWriter() %></td>
				<td><%=qna.getRegdate() %></td>
				<td><%=qna.getHit() %></td>
		  </tr>
  <%} %>
  <tr>
  	<td colspan="5" style="text-align:center">
  		<%if((firstPage-1)>0){ %>
  			<a href="/qna/list2.jsp?currentPage=<%=firstPage-1%>">◀</a>
  		<%}else{ %>
  			<a href="javascript:alert('처음 페이지입니다!');">◀</a>
  		<%} %>
  		<%for(int i=firstPage;i<=lastPage;i++){ %>
  			<%if(i>totalPage) break; //페이지 출력하는 i가 총 페이지 수에 도달하면 반복문 빠져나와라..%>
  			<a href="/qna/list2.jsp?currentPage=<%=i%>" <%if(currentPage==i){ %>class="pageNum" <%} %>>[<%=i%>]</a>
  		<%} %>
  		<%//if(totalPage<lastPage){ %>
  		<%if((lastPage+1)<lastPage){ %>
	  		<a href="/qna/list2.jsp?currentPage=<%=lastPage+1%>">▶</a>
  		<%}else{ %>
  			<a href="javascript:alert('마지막 페이지입니다!');">▶</a>
  		<%} %>
  	</td>
  </tr>
  	<tr>
	<td colspan="5">
		<button>글 등록</button>
	</td>
  </tr>
  <tr>
	<td colspan="5" style="text-align:center">
		<%@ include file="/inc/footer.jsp"%>
	</td>
  </tr>
</table>
</body>
</html>

'프로그래밍 > JSP' 카테고리의 다른 글

JSP | session  (0) 2020.12.16
JSP | 커넥션풀(Connection Pool)  (0) 2020.12.11
JSP | MyBatis 사용해보기  (0) 2020.12.10
JSP - 이미지 업로드  (0) 2020.12.04
JSP - JSP(Java Server Page)란?  (0) 2020.12.01

방법

1. oreilly에서 만든 라이브러리 사용하기

2. Apache에서 만든 라이브러리 사용하기

 

oreilly에서 만든 라이브러리 사용

Servlets.com | com.oreilly.servlet

 

Servlets.com | com.oreilly.servlet

 

www.servlets.com

위 사이트에 들어가서 MulitpartRequest 클래스를 사용하여 업로드할 수 있다.

 

페이지 아래 쪽에 jar파일을 다운로드받을 수 있게 제공해준다. jar파일을 라이브러리에 등록해준다.

<%@page import="java.io.File"%>
<%@page import="common.FileManager"%>
<%@page import="java.io.IOException"%>
<%@page import="com.oreilly.servlet.MultipartRequest"%>
<%@ page contentType="text/html;charset=UTF-8"%>
<%
	/*
클라이언트가 전송한 제목, 텍스트 및 바이너리 파일을 서버의 특정 디렉토리에 저장해보자
= 업로드라 한다!!
*/
request.setCharacterEncoding("utf-8");//파라미터 한글 깨지지 않게 인코딩
//String msg = request.getParameter("msg");//String 메시지 받기

//이미지는 글씨가 아닌 바이너리 파일이므로, request.getParameter로는 받을 수 없다!
//따라서 IO, 네트워크 등의 처리를 해야 하는데, 이 자체만으로도 하나의 개발 프로젝트일 것이다.
//해결책?? 누군가 만든 라이브러리를 이용해서 개발시간을 단축하자!!
//현재 우리가 선택한 라이브러리는 cos.jar라는 Oreilly라는 출판사에서 제작한 컴포넌트이다!!
String saveDirectory = "C:/workspace/javaee_workspace/BoardApp/WebContent/data";//하드디스크의 물리적 경로를 명시해야 한다!!
int maxSize = 1024 * 1024 * 2; //2MByte
String encoding = "utf-8";
//FileRenamePolicy policy : 업로드 시 , 동일한 파일을 업로드했을 때?? 자동으로 이름을 부여한다...
//예) p.jpg, 1p.png.. (파일명은 개발자가 주도하여 명명하므로, policy를 굳이 이용할 필요 없다.)
try {
	MultipartRequest multi = new MultipartRequest(request, saveDirectory, maxSize, encoding);
	//업로드 컴포넌트를 이용할 경우, 스트링 파라미터도 업로드 컴포넌트를 이용해야한다!!
	String msg = multi.getParameter("msg");
	//out.print("전송한 메시지는 " + msg);
	//업로드가 완료된 후, 즉 서버의 저장소에 파일이 존재하게 된 후 해야할 일!
	//파일명을 개발자가 정한 규칙으로 변경해야 한다..현재시간의 밀리세컨드까지 구해보자!
	long time = System.currentTimeMillis();
	//out.print(time);
	//구한 시간에 확장자를 붙이면 최종적으로 절대 중복되지않는 파일이 생성
	String filename = multi.getOriginalFileName("photo");
	//out.print("전송한 파일의 이름은 " + filename);
	String ext = FileManager.getExtend(filename);
	out.print("내가 조작한 파일명은 " + time + "." + ext);
	
	//조작한 이름으로 파일명을 바꾸어야함
	//결국 파일을 다루어야 하므로 javaSE의 File클래스를 이용하면 된다!
	File file = multi.getFile("photo");
	file.renameTo(new File("C:/workspace/javaee_workspace/BoardApp/WebContent/data/"+time+"."+ext));
	
	//클라이언트에게 전송할 응답정보를 가진 객체
	//클라이언트의 브라우저로 하여금 지정한 URL로 재접속을 시도하게 만듦
	response.sendRedirect("/gallery/send.html");
} catch (IOException e) {
	e.printStackTrace();//콘솔로그에 에러 출력
	out.print("업로드 용량이 너무 큽니다..");//사블릿 쓰레드 에러..
}
%>

위 코드에서 볼 수 있듯이  MultipartRequest와 request 객체를 이용해서 파일을 업로드할 수 있다.

다운받은 파일에 doc폴더 아래에 html파일들을 보면서 자세히 알 수 있다.

Apache에서 제공하는 라이브러리 사용

Maven Repository: commons-fileupload » commons-fileupload (mvnrepository.com)

 

Maven Repository: commons-fileupload » commons-fileupload

The Apache Commons FileUpload component provides a simple yet flexible means of adding support for multipart file upload functionality to servlets and web applications. VersionRepositoryUsagesDate1.4.x1.4Central226Dec, 20181.3.x1.3.3Central514Jun, 20171.3.

mvnrepository.com

위 사이트에서 jar파일을 다운받아 라이브러리에 등록한다.

<%@page import="org.apache.catalina.filters.SetCharacterEncodingFilter"%>
<%@page import="common.FileManager"%>
<%@page import="org.apache.commons.fileupload.FileItem"%>
<%@page import="java.util.List"%>
<%@page import="java.io.File"%>
<%@page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%>
<%@page import="org.apache.commons.fileupload.DefaultFileItemFactory"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%
	/*
파일 업로드 컴포넌트 종류엔 여러종류가 있지만, 그 중 아파치의 공식 업로드 컴포넌트를 사용해본다.
*/
//업로드 객체를 생성해주는 팩토리 객체 : 주로 설정을 담당(서버의 저장경로, 파일의 용량제한..)
String saveDir = "C:/workspace/javaee_workspace/BoardApp/WebContent/data";
int maxSize = 1024 * 1024 * 3; // 3MB
DefaultFileItemFactory itemFactory = new DefaultFileItemFactory();
itemFactory.setRepository(new File(saveDir)); //저장될 위치!, 물리적인 저장이 아닌, 임시 디렉터리
//디렉터리도 파일의 종류 중 하나이다!!
itemFactory.setSizeThreshold(maxSize);//파일 크기 제한

//이 객체가 실제 업로드를 수행함
ServletFileUpload upload = new ServletFileUpload(itemFactory);//설정정보를 생성자의 인수로 전달!!

//FileItem은 클라이언트의 [전송 정보 하나 하나]를 의미한다!! 즉, html에서의 input, file 컴포넌트 들을..
//우리의 경우 input type="text"가 FileItem에 담기고
//우리의 경우 input type="file"도 FileItem에 담긴다.
List<FileItem> items = upload.parseRequest(request);//request를 전달하여 upload컴포넌트에게 클라이언트의 요청정보를 전달!!

for (FileItem item : items) {
	//out.print(item.getFieldName());//컴포넌트의 name추출 
	//반복문으로 처리되다보니, 파일만 따로 처리를 하려면 구분로직이 필요함..
	//out.print(item.getFieldName()+"은 텍스트 박스 여부 " + item.isFormField()+"<br>");
	
	if (!item.isFormField()) {//type이 text가 아닌 것만 업로드 처리!
		//out.print(item.getFieldName()+"의 값은 "+item.getString()+"<br>");
		//업로드 처리하자!! 메모리상의 이미지 정보를 실제 물리적 파일로 저장하자!
		//out.print( item.getName());
		String ext = FileManager.getExtend(item.getName());
		String filename = System.currentTimeMillis() + "." +ext;
		File file = new File(saveDir+"/"+filename);//비어있는 파일
		item.write(file);//저장 정보를 File클래스의 인스턴스로 전달!!
		out.print("보고서 작성<br>");
		out.print("본래 파일명 : "+item.getName()+"<br>");
		out.print("변경 파일명 : "+filename+"<br>");
		out.print("저장 위치 : "+saveDir+"<br>");
		out.print("파일 크기 : "+item.getSize()+"<br>");
	}
}
%>

아파치에서 제공하는 라이브러리는 Factory객체를 이용하여 설정을 할 수 있고 ServletFileUpload 객체를 이용하여 request내에 담긴 파라미터들을 해석하여 List로 받아 사용할 수 있다.!!

'프로그래밍 > JSP' 카테고리의 다른 글

JSP | session  (0) 2020.12.16
JSP | 커넥션풀(Connection Pool)  (0) 2020.12.11
JSP | MyBatis 사용해보기  (0) 2020.12.10
JSP - 페이징 이해  (0) 2020.12.08
JSP - JSP(Java Server Page)란?  (0) 2020.12.01

JSP란 무엇일까?

JSP는 자바가 서버에서 실행되는 형태로 문서내에 있는 자바코드를 서버에서 실행시켜주는 페이지(?) 같다.

EJS처럼 html문서 내에 자바코드가 들어가게 되는 형태이다. 

 

구조

1. 지시영역 (<%@ %>)

 지시영역는 해당 페이지의 정보를 설정한다고 보면 된다.

예를 들면 <%@ page contentType="text/html;charset=utf-8"%>이런 식으로 페이지의 파일 형태나 인코딩방식을 정의할 수 있고, <%@ page import="java.sql.Connection"%> 이런 식으로 클래스를 import할 수 있다.

 

2. 선언부 (<%! %>)

선언부는 멤버변수를 선언하는 것과 같다고 볼 수 있다. 

<%! int number=3%>와 같이 쓸 수 있으며, 이 변수는 응답에 완료하기 전까지 메모리에 남아있는 변수로 생각할 수 있다.

 

3. 스크립트릿 (<%%>)

스트립트릿(Scriptlet)는 단순히 문서내에 자바코드를 삽입할 수 있는 영역이다.

<table>
	<tr>
    	<%for(int i=0;i<10;i++){%>
    		<td><%out.print(i);%></td>
        <%}%>
    </tr>
</table>

EJS와 매우 흡사하며, 위 코드와 같이 사용할 수 있다.

 

4. 표현식 (<%= %>)

표현식은 페이지내에 선언된 메모리에 남아있는 변수들을 쉽게 사용할 수 있는 방법이다.

3번 코드블럭 내에 <%out.print(i);%>를 단순히 <%=i%>로 간편히 사용할 수 있게 된다.

 

작동원리

JSP문서는 서버에서 처리를 하게 되는데, 만약 서버로 정적인 요소(html, image..)들이 요청된다면, 서버는 단지 요청하는 요소를 클라이언트측으로 응답만 한다.

만약 .jsp 파일이 요청된다면 서버는 해당 파일내에 <%%>(스크립트릿)의 내용들을 해석하여 실행한 뒤, 이 문서를 html형태의 문서로 변환하여 클라이언트측으로 응답하게 된다! (정말 신기함)

 

<%@ page contentType="text/html;charset=utf-8"%>
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
	function getMsg(){
		return "<%="안녕"%>";
	}
	<%
		out.print(getMsg()+" 하세요");
	%>
	
</script>
</head>
<body>
</body>
</html>

예를 들어, 위와 같은 코드의 문서를 서버로 요청하게 된다면?? 과연 실행이 될까??

getMsg()는 현재 스크립트 영역 내에 존재하는 메서드이다. 그리고, 바로 아래에 <%%>내에서 getMsg()를 호출하고 있다. 

위에서 말했듯이, <%%>는 서버에서 실행되는 영역이다. 그리고 스크립트 영역의 코드는 반드시 클라이언트 측에서 실행된다. 이 개념을 이해했다면, 왜 에러가 나는 지 알 수 있다.

 

이유는, 실행순서(?)이다.  

1. 먼저, 클라이언트가 .jsp 파일을 요청하게 되면 서버는 해당 파일 내에 존재하는 <%%>를 실행하게 된다. 

2. 실행도중 getMsg()라는 메서드를 만나게 되는데, 이때 undefine 예외가 발생한다.

3. 왜냐하면, getMsg()는 스크립트 영역 내에 존재하는 메서드로 클라이언트에서 실행되기 때문에, 서버가 코드를 해석할 때는 아직 define되지 않은 상태이기 때문이다!! 

 

내장객체

jsp에서 지원하는 내장객체는 아래와 같다.

1. request : 클라이언트의 요청정보를 갖는 객체 (요청에 대한 처리 완료 시 소멸)
2. response : 클라이언트에게 보낼 응답정보를 갖는 객체 (요청에 대한 처리 완료 시 소멸)
3. out : jsp에 출력을 담당하는 객체
4. session : 정보를 세션 범위에서 유지하지 위해 지원되는 객체(로그인 정보 처리 시 사용할 예정)
5. application : 정보를 어플리케이션 범위에서 유지하기 위해 지원되는 객체
6. page : jsp를 표현한 객체
7. config : jsp 설정 정보를 보유한 객체
8. exception : jsp에서 발생한 예외정보를 보유한 객체

 

또한, 내장객체는 이미 내부적으로 인스턴스가 지원되면서, 해당 인스턴스의 변수명까지 이미 정해진 
상태이므로, 개발자는 그냥 사용하기만 하면 된다!! 

 

해당 객체들의 상세한 내용은 다음 시간에 ~ ^^

 

참고

jsp 파일 내에서 라이브러리나 외부클래스들을 사용하고 싶다면??

Sun사에서 이미 정해놓은 WEB-INF라는 보안된 디렉터리에 파일들을 위치시켜야한다!!(프로젝트 폴더 내에서)

클래스의 위치는 WEB-INF/classes, 라이브러리의 위치는 WEB-INF/lib에 두어야한다!

이런 식으로!

'프로그래밍 > JSP' 카테고리의 다른 글

JSP | session  (0) 2020.12.16
JSP | 커넥션풀(Connection Pool)  (0) 2020.12.11
JSP | MyBatis 사용해보기  (0) 2020.12.10
JSP - 페이징 이해  (0) 2020.12.08
JSP - 이미지 업로드  (0) 2020.12.04

+ Recent posts