Study Web Development

1월 20일

이전으로

Servlet & JSP

8. EL & JSTL

8-1 EL

EL 특징
EL 표기법
EL의 연산자
  1. jspMain 프로젝트의 src/main/webapp 오른쪽 클릭하고 새 폴더 ch17-el 생성 후 새 JSP 파일 s01_el.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL</title>
</head>
<body>
<table border="1">
	<tr>
		<th>표현식</th>
		<th></th>
	</tr>
	<tr>
		<td>\${2 + 5}</td> <%-- $ 앞에 \를 붙여 EL 표현식을 그대로 출력 --%>
		<td>${2 + 5}</td> <%-- EL 표현식의 연산 결과를 출력 --%>
	</tr>
	<tr>
		<td>\${"10" + 2}</td>
		<td>${"10" + 2}</td> <%-- 문자열과 숫자를 + 연산시, 연결하는 대신 문자열을 숫자로 parsing해서 덧셈 수행 --%>
	</tr>
	<tr>
		<td>\${"10" + "2"}</td>
		<td>${"10" + "2"}</td> <%-- 문자열을 숫자로 parsing해서 덧셈 수행 --%>
	</tr>
	<tr>
		<td>\${"십" + 5}</td>
		<td>에러 발생</td> <%-- 문자열을 숫자로 parsing하는 데 실패하여 NumberFormatException 발생 --%>
	</tr>
	<tr>
		<td>\${4 / 5}</td>
		<td>${4 / 5}</td> <%-- 정수끼리 연산하더라도 실수 몫을 반환 --%>
	</tr>
</table>
</body>
</html>
EL의 기본 객체
기본 객체 설명
pageContext JSP의 page 기본 객체와 동일
pageScope pageContext 기본 객체에 저장된 속성의 <속성, 값> 매핑을 저장한 Map 객체
requestScope request 기본 객체에 저장된 속성의 <속성, 값> 매핑을 저장한 Map 객체
sessionScope session 기본 객체에 저장된 속성의 <속성, 값> 매핑을 저장한 Map 객체
applicationScope application 기본 객체에 저장된 속성의 <속성, 값> 매핑을 저장한 Map 객체
param 요청 파라미터의 <파라미터 이름, 값> 매핑을 저장한 Map 객체
  1. 새 JSP 파일 s02_el.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	//전송된 데이터 인코딩 처리
	request.setCharacterEncoding("UTF-8");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL</title>
</head>
<body>
<h3>표현 언어(EL) - 파라미터값 처리</h3>
<form action="s02_el.jsp" method="post"> <!-- 자기 자신에 데이터를 전송 -->
	이름 : <input type="text" name="name">
	<input type="submit" value="확인">
</form>
<br>
이름은 <%= request.getParameter("name") %><br> <%-- 파라미터가 없는 경우 null 반환 --%>
이름은 ${param.name} <%-- 파라미터가 없는 경우 null 대신 빈 문자열 반환 --%>
</body>
</html>
  1. s03_el.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>EL</title>
<%
	// 변수에 값 저장
	String str = "여름 여행";
	// JSP 4개 영역에 데이터 저장
	pageContext.setAttribute("msg", "봄");
	request.setAttribute("msg2", "여름");
	session.setAttribute("msg3", "가을");
	application.setAttribute("msg4", "겨울");
%>
</head>
<body>
<%-- JSP 4개 영역에 속성을 저장하고 EL로 읽는 경우, 내장 객체를 생략하고 속성명만으로 호출 가능; 영역을 명시하지 않았는데 속성명이 유일하지 않으면 가장 작은 영역인 pageContext부터 검색 --%>
page 영역 : ${pageScope.msg}, ${msg}<br>
request 영역 : ${requestScope.msg2}, ${msg2}<br>
session 영역 : ${sessionScope.msg3}, ${msg3}<br>
application 영역 : ${applicationScope.msg4}, ${msg4}<br>
변수의 값 : ${str} <%-- 스크립트릿에서 만든 변수의 값은 EL에서 직접 호출하지 못함 --%>
</body>
</html>

8-2 JSTL

https://javaee.github.io/jstl-api/ https://projects.eclipse.org/projects/ee4j.jstl https://mvnrepository.com/artifact/javax.servlet/jstl/1.2

  1. Files에서 jar 선택하여 C:\javaWork\appsjstl-1.2.jar 다운로드
  2. 다운로드된 파일을 복사하여 C:\javaWork\workspace_jsp\jspMain\src\main\webapp\WEB-INF\lib에 붙여넣기
core 라이브러리
  1. kr.web.member 패키지에 새 클래스 UserVO 생성
package kr.web.member;

public class UserVO {
	// 프로퍼티
	private String name;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
  1. webapp 폴더 오른쪽 클릭하여 새 폴더 ch18-jstl 생성 후 새 JSP 파일 s01_set.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="kr.web.member.UserVO" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%-- jar 파일에서 설정 정보를 읽어들여 JSTL 커스텀 태그를 사용할 수 있도록 함; uri는 실제 웹 주소가 아니라 태그 라이브러리의 식별자 --%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>set 태그</title>
</head>
<body>
<c:set var="msg" value="봄" scope="page"/> <%-- var에 속성명, value에 속성값, scope에 저장 영역을 명시; scope 생략시 기본값은 page --%>
${pageScope.msg}, ${msg}<br>

<%
	UserVO user = new UserVO();
%>
<c:set var="user" value="<%= user %>"/> <%-- UserVO 객체를 page 영역의 속성에 저장 --%>
<c:set target="${user}" property="name" value="도로롱" /> <%-- EL로 저장된 객체를 읽어와 target으로 지정한 후 대상 객체의 프로퍼티에 값을 저장 --%>
회원 이름 : ${user.name}<br> <%-- 객체에 접근한 후 프로퍼티명을 명시하면 값을 읽어옴 --%>
회원 이름 : ${user.getName()} <%-- Tomcat의 상위 버전에서는 객체의 메서드 호출도 가능 --%>
</body>
</html>
  1. 새 JSP 파일 s02_remove.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>remove 태그</title>
</head>
<body>
<c:set var="str" value="서울"/> <%-- setAttribute() 메서드의 구현 --%>
데이터 삭제 전 : ${str}<br> <%-- getAttribute() 메서드의 구현 --%>
<c:remove var="str"/> <%-- removeAttribute() 메서드의 구현 --%>
--------<br>
데이터 삭제 후 : ${str}
</body>
</html>
  1. 새 JSP 파일 s03_if.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>if 태그</title>
</head>
<body>
<%-- if 태그는 단일 if문만 지원하며 if~else나 다중 if문을 지원하지 않음 --%>
<c:if test="true"> <%-- test에 if문의 조건식을 명시 --%>
항상 수행<br> <%-- 태그로 영역을 분리하고 있기 때문에, 영역 내에 다른 태그도 사용 가능 --%>
</c:if>

<c:if test="${param.name == 'sleepy'}"> <%-- 조건식에 EL의 비교 연산자 사용; 큰따옴표 안에 문자열로 EL을 전달하고 있기 때문에, EL 내에서 문자열 사용시에는 작은따옴표를 사용 --%>
name 파라미터의 값이 ${param.name} 입니다.<br>
</c:if>

<c:if test="${param.name.equals('sleepy')}"> <%-- Tomcat의 상위 버전에서는 (비교 연산자 대신) equals() 메서드 호출 가능 --%>
name 파라미터의 값이 ${param.name} 입니다.<br>
</c:if>

<c:if test="${param.age>= 20}">
당신의 나이는 20세 이상입니다.
</c:if>
</body>
</html>
  1. 새 JSP 파일 s04_choose.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>choose 태그</title>
</head>
<body>
<%-- choose 태그는 if~else나 다중 if문을 대체 --%>
<c:choose>
	<c:when test="${param.name == 'sleepy' && param.age >= 20}">
		당신의 이름은 ${param.name} 이고 20세 이상입니다.
	</c:when>
	<c:when test="${param.name == 'sleepy'}">
		당신의 이름은 ${param.name} 입니다.
	</c:when>
	<c:when test="${param.age >= 20}">
		당신은 20세 이상입니다.
	</c:when>
	<c:otherwise>
		당신은 sleepy가 아니고 20세 이상이 아닙니다.
	</c:otherwise>
</c:choose>
</body>
</html>
  1. 새 JSP 파일 s05_forEach.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.HashMap" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>forEach 태그</title>
</head>
<body>
<h4>1부터 100까지 홀수의 합</h4>
<c:set var="sum" value="0"/>
<c:forEach var="i" begin="1" end="100" step="2">
	<c:set var="sum" value="${sum + i}"/>
</c:forEach>
결과 : ${sum}

<h4>구구단 : 5단</h4>
<ul>
<c:forEach var="i" begin="1" end="9">
	<li>5 * ${i} = ${5 * i}</li>
</c:forEach>
</ul>

<h4>int형 배열</h4>
<c:set var="intArray" value="<%= new int[]{10, 20, 30, 40, 50} %>"/>
<c:forEach var="i" items="${intArray}" begin="2" end="4" varStatus="status">
	${status.index} - ${status.count} - ${i}<br>
</c:forEach>

<h4>Map</h4>
<%
	HashMap<String,String> mapData = new HashMap<String, String>();
	mapData.put("name", "sleepy");
	mapData.put("job", "경찰");
%>
<c:set var="map" value="<%= mapData %>"/>
<c:forEach var="i" items="${map}">
	${i.key} = ${i.value} <br>
</c:forEach>
</body>
</html>
  1. 새 JSP 파일 s06_forTokens.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>forTokens 태그</title>
</head>
<body>
<h4>쉼표와 점을 구분자로 사용</h4>
<c:forTokens var="token" items="붉은색,주황색.노란색.초록색,파란색,남색.보라색" delims=",."> <%-- StringTokenizer 역할 --%>
	${token}<br>
</c:forTokens>

<h4>날짜를 연월일시분초로 구분해서 출력</h4>
<c:forTokens var="now" items="2022-01-20 15:11:05" delims="- :"> <%-- 공백의 경우 delims에 명시하지 않더라도 기본적으로 구분자로 사용됨 --%>
	${now}<br>
</c:forTokens>
</body>
</html>
  1. 새 JSP 파일 s07_out.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>out 태그</title>
</head>
<body>
<%-- out 태그는 출력을 담당하며, 일반적으로는 출력에 EL을 사용하지만 HTML 태그를 불인정해야 하는 경우에 out 태그를 사용 --%>
<c:out value="<h1>오늘은 목요일</h1>" escapeXml="true"/><br> <%-- escapeXml="true"이면 HTML 태그 불인정(기본값) --%>
<c:out value="<h1>내일은 금요일</h1>" escapeXml="false"/> <%-- escapeXml="false"이면 HTML 태그 인정 --%>
</body>
</html>
formatting 라이브러리
  1. 새 JSP 파일 s08_date.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%-- core 라이브러리 사용 --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%-- formatting 라이브러리 사용 --%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>formatDate 태그</title>
</head>
<body>
<c:set var="now" value="<%= new java.util.Date() %>"/>
${now}<br>
<fmt:formatDate value="${now}" type="date" dateStyle="full"/><br>
<fmt:formatDate value="${now}" type="date" dateStyle="short"/><br>
<fmt:formatDate value="${now}" type="time" timeStyle="full"/><br>
<fmt:formatDate value="${now}" type="time" timeStyle="short"/><br>
<fmt:formatDate value="${now}" type="both" dateStyle="full" timeStyle="full"/><br>
<fmt:formatDate value="${now}" pattern="yyyy년 MM월 dd일 a hh:mm:ss"/> <%-- SimpleDateFormat과 동일한 패턴 문자 사용 --%>
</body>
</html>
  1. 새 JSP 파일 s09_number.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>formatNumber 태그</title>
</head>
<body>
숫자 : <fmt:formatNumber value="10000" type="number"/><br> <%-- 세 자리 단위로 쉼표 삽입 --%>
통화 : <fmt:formatNumber value="10000" type="currency" currencySymbol="$"/><br>
통화 : <fmt:formatNumber value="10000" type="currency" currencySymbol="\\"/><br> <%-- 원 표시 \는 1개만 사용시 특수문자로 취급되어 에러가 발생하므로, \를 2개 사용하여 일반문자로 변환 --%>
퍼센트 : <fmt:formatNumber value="0.3" type="percent"/><br>
패턴 : <fmt:formatNumber value="12.345" pattern="0000.00"/> <%-- 소수점 이상의 0 갯수는 자릿수보다 적은 경우 원래 값대로, 자릿수보다 많은 경우 0을 앞에 붙이며, 소수점 이하의 0 갯수는 자릿수보다 적은 경우 반올림 처리하고, 자릿수보다 많은 경우 0을 뒤에 붙임 --%>
</body>
</html>
functions 라이브러리
  1. 새 JSP 파일 s10_functions.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <%-- functions 라이브러리 사용 --%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>functions 라이브러리</title>
</head>
<body>
<c:set var="str1" value=" Functions <태그>를 사용합니다. "/>
<c:set var="tokens" value="10,20,30,40"/>

문자열의 길이 : ${fn:length(str1)}<br>
문자열의 길이 : ${str1.length()}<br>
대문자로 변경 : ${fn:toUpperCase(str1)}<br>
대문자로 변경 : ${str1.toUpperCase()}<br>
소문자로 변경 : ${fn:toLowerCase(str1)}<br>
소문자로 변경 : ${str1.toLowerCase()}<br>
인덱스 3부터 6 전까지의 문자열 추출 : ${fn:substring(str1, 3, 6)}<br>
인덱스 3부터 6 전까지의 문자열 추출 : ${str1.substring(3, 6)}<br>
문자열에서 원래 문자를 지정한 문자로 대체 : ${fn:replace(str1," ", "-")}<br>
문자열에서 원래 문자를 지정한 문자로 대체 : ${str1.replace(" ", "-")}<br>
문자열에서 지정한 문자를 구분자로 문자열 잘라내기<br>
<c:forEach var="array" items="${fn:split(tokens,',')}">
	${array}<br>
</c:forEach>
</body>
</html>

9. MVC

9-2 모델 2 구조(MVC)

9-3 MVC 패턴

mvcMain

프로젝트 생성 및 설정
  1. 새 다이나믹 웹 프로젝트를 생성하여 프로젝트명에 mvcMain 입력 후 Next-Next-Generate web.xml depolyment descriptor 선택 후 Finish
  2. 프로젝트를 오른쪽 클릭하여 Build Path-Configure Build Path... 선택하고 Libraries 탭에서 JRE System Library를 선택 후 Edit...에서 JavaSE-1.8(jre)로 변경
  3. 프로젝트를 오른쪽 클릭하여 Properties 선택하고 좌측 목록에서 Project Facets 선택 후 Java의 Version을 1.8로 변경
  4. src/main/webapp 오른쪽 클릭하고 새 JSP 파일 index.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>hello world</title>
</head>
<body>
hello world
</body>
</html>
VC
  1. WEB-INF 폴더의 web.xml를 열고, 왼쪽 하단의 Source 탭 선택
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>mvcMain</display-name>
  <servlet>
  	<servlet-name>DispatcherServlet</servlet-name>
  	<servlet-class>kr.controller.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>DispatcherServlet</servlet-name>
  	<url-pattern>/disp</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>
  1. src/main/java 오른쪽 클릭하여 새 패키지 kr.controller 생성 후 새 클래스 DispatcherServlet 생성
package kr.controller;

import java.io.IOException;

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

public class DispatcherServlet extends HttpServlet {
	// 클라이언트가 GET 방식으로 요청하건 POST 방식으로 요청하건 에러가 발생하지 않도록 doGet() 메서드와 doPost() 메서드를 모두 Override하되, 작업은 한 번만 하기 위해 별도의 메서드 requestPro()를 만들어 해당 메서드로 request와 response를 전달
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		requestPro(request, response);
	}
	
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		requestPro(request, response);
	}
	
	private void requestPro(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// forward 방식으로 JSP(View) 호출
		RequestDispatcher dispatcher = request.getRequestDispatcher("views/messageView.jsp");
		dispatcher.forward(request, response);
	}
}
  1. webapp 오른쪽 클릭하고 새 폴더 views 생성 후 새 JSP 파일 messageView.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>View</title>
</head>
<body>
결과 : <%= request.getAttribute("result") %><br> <%-- result 속성은 Servlet에서 만들기 때문에 JSP 직접 호출시에는 null이 반환됨 --%>
결과 : ${result} <%-- result가 유일하기 때문에 영역 명시하지 않고 속성명만 명시해도 의도대로 request 영역의 result가 호출됨 --%>
</body>
</html>

다음으로