멀티캠퍼스 백엔드 과정36일차[7월 24일] - JSTL, 다운로드

GoldenDusk·2023년 7월 27일
0

JSTL

Maven Repository: javax.servlet » jstl » 1.2

예제

  • 코드

<%@ page import="java.util.Date" %>
<%@ page import="common.Person" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- 변수 선언 -->
<c:set var = "direcVar" value="100" /> <%-- 같은 의미 <%String direceVar = "100"; %> --%>
<c:set var = "elVar" value="${direcVar mod 5}"  /> 
<c:set var = "expVar" value="<%= new Date() %>" /> 
<c:set var = "betweenVar"> c:set은 싱글태그와 스타트 앤드태그 중간에 텍스트 표시 가능 </c:set>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> c:set 변수 사용</title>
</head>
<body>

<h2> EL 이용하여 출력</h2>
<ul>
<li>direcVar : ${pageScope.direcVar }</li>
<li>elVar : ${elVar}</li>
<li>expVar : ${expVar}</li>
<li>betweenVar : ${betweenVar }</li>
</ul>

<h2> 자바빈 생성 1 : 생성자 이용</h2>
<c:set var="personVar1" value='<%= new Person("박학식", 50) %>' scope="request"/>

<!-- 위와 같은 의미 -->
<% request.setAttribute("personVar1", new Person("박학식", 50)); %>
<ul>
<li>이름 : ${requestScope.personVar1.name}</li>
<li>나이 : ${personVar1.age}</li>
</ul>
</body>
</html>

JSTL이란?

JSTL(Java Stamdard Tag Library)

  • JSP에서 빈번하게 사용되는 조건문, 반복문 등을 처리해주는 태그를 모아 표준으로 만들어
    놓은 라이브러리
  • 스크립틀릿 없이 태그만으로 작성할 수 있기 때문에 코드가 간결해지고 읽기 편해짐

태그 종류

종류기능접두어
Core 태그변수 선언, 조건문/반복문, URL
처리c
Formatting 태그숫자, 날짜, 시간 포맷 지정fmt

지시어

  • JSTL을 사용하려는 JSP파일에서는 taglib 지시어 추가해야 함
  • 이때 접두어와 URL 사용
  • Core 태그를 사용하기 위한 지시어 예시
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

JSTL 사용설정

별도 라이브러리

JSTL은 JSP의 기본 태그가 아닌 확장 태그이므로 사용을 위해 별도의 라이브러리가 필요

Core 태그

태그명기능
setEL에서 사용 변수를 설정. setAttribute( ) 메서드와 동일한 기능
remove설정할 변수를 제거. removeAttribute( ) 메서드와 동일한 기능
if다 조건문을 주로 처리. else문이 없다는 단점
choose다중 조건을 처리할 때 사용. 하위에 when~otherwise 태그가 있음
forEach반복문을 처리할 때 사용. 반 for문과 향상된 for문 두 가지 형태로 사용
forTokens구분자로 분리된 각각의 토큰을 처리할 때 사용. StringTokenizer 클래스와 동일 기능.
import외부 페이지를 삽입 때 사용
redirect지정한 경로로 이동. sendRedirect( ) 메서드 동일한 기능
url경로를 설정 때 사용
out내용을 출력 때 사용
catch예외 처리에 사용

1. <c:set 태그>

  • <c:set> 태그는 EL에서 사용할 변수나 자바빈즈를 생성할 때 사용
  • JSP에서 영역에 속성을 저장할 때 사용하는 setAttribute( ) 메서드와 같은 역할
<c:set var="변수명" value="값" scope="영역" />
<c:set var="변수명" scope="영역">
value 속성에 들어갈 값
</c:set>

<c:set 태그>의 속성

속성명기능
var변수명을 설정
value변수에 할당 값
scope변수를 생성 영역을 지정. page가 기본값
target자바빈즈를 설정
property자바빈즈의 속성, 즉 멤버 변수의 값을 지정

2. List 출력하기

  • Person은 따로 클래스 만들어진 것 import
  • List는 add로 넣기
<h2> List 컬렉션 이용</h2>
<%
	ArrayList<Person> pList = new ArrayList<>();
	/* 1. 회원 두명을 pList에 저장 */
	pList.add(new Person("이금금", 26));
	pList.add(new Person("유지지", 34));
	
	%>
	
<!-- 2. c태그에 변수명을 personList 값을 pList 지정 scope은 request로 출력 -->
<c:set var="personList" value='<%= pList %>' scope="request"/>

<!-- 3. personList에 저장되어 있는 회원 두명의 이름과 나이 EL 방식으로 출력 -->
<ul>
<li>이름 : ${requestScope.personList[0].name}</li>
<li>나이 : ${personList[0].age}</li>
<li>이름 : ${requestScope.personList[1].name}</li>
<li>나이 : ${personList[1].age}</li>
</ul>

3. Map 출력하기

  • Map은 해시맵
  • hash는 키, 값 형태로 키로 값을 찾음 put으로 값 넣기
<h2> Map 컬렉션 이용</h2>
<%
	Map<String, Person> pMap = new HashMap<String, Person>();
	/* 1. 회원 두명을 pList에 저장 */
	pMap.put("person1", new Person("이금금", 26));
	pMap.put("person2", new Person("유지지", 34));
	
	%>
	
<!-- 2. c태그에 변수명을 personMap 값을 pMap 지정 scope은 request로 출력 -->
<c:set var="personMap" value='<%= pMap %>' scope="request"/>

<!-- 3. personList에 저장되어 있는 회원 두명의 이름과 나이 EL 방식으로 출력 -->
<ul>
<li>이름 : ${requestScope.personMap.person1.name}</li>
<li>나이 : ${personMap.person1.age}</li>
<li>이름 : ${requestScope.personMap.person2.name}</li>
<li>나이 : ${personMap.person2.age}</li>
</ul>

4. <c:if> 태그

  • <c:if> 태그는 자바의 if와 동일하게 제어 구문을 작성 때 사용
  • else가 별도로 없기 때문에 일련의 여러 조건을 나열하는 형태로 작성은 어려움
<c:if test="조건" var="변수명" scope="영역">
 조건이 true일 때 출력할 문장
</c:if>
  • 태그 속성
속성명기능
testif문에서 사용할 조건을 지정
var조건의 결과를 저장 변수명을 지정
scope변수가 저장될 영역을 지정

<%@ page import="java.util.Date" %>
<%@ page import="common.Person" %>
<%@ 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> c:if 사용 1</title>
</head>
<body>
<!-- c태그를 이용해서 저장 -->
<c:set var="number" value="100"/>
<c:set var="string" value="JSP" />

<h2>if 태그로 짝수와 홀수 판별</h2>
<c:if test="${number mod 2 eq 0}" var="result">${number }은 짝수 입니다.</c:if>  <br/>
result : ${result } <br/>

<h2>문자열을 비교 / else 구문 만들어보기</h2>
<c:if test="${string eq 'Java' }" var="result2">
문자열은 Java입니다.<br/>
</c:if>
<c:if test="${not result2}">
문자열은 Java이 아닙니다.<br/>
</c:if>
</body>
</html>

5. 주의 사항

  • c태그 안에 꼭 “ ”으로

<h2>주의사항</h2>
<c:if test="100" var="result3">
EL이 아닌 정수를 지정하면 false<br/>
</c:if>
result3 : ${result3 }<br/>

<c:if test="tRuE" var="result4">
대소문자 없이 "tRuE" true<br/>
</c:if>
result4 : ${result4 }<br/>
<br/>
<c:if test=" ${ true } " var="result5">
""과 EL양쪽에 공백이 있는 경우 false<br/>
</c:if>
result5 : ${ result5 }<br/>

<c:choose>, <c:when>, <c:otherwise> 태그

  • <c:choose> 태그는 다중 조건을 통해 판단해야 할 때 사용
  • 하위 태그로 <c:when>, <c:otherwise> 태그를 함께 사용
<c:choose>
 <c:when test="조건1">조건1을 맊족하는 경우</c:when>
 <c:when test="조건2">조건2을 맊족하는 경우</c:when>
 <c:otherwise>아무 조건도 맊족하지 않는 경우</c:otherwise>
</c:choose>

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>JSTL - choose/when/otherwise</title>
</head>
<body>
	<!-- 변수 선언 -->
	<c:set var="number" value="100" />

	<h4>choose 태그로 홀짝 판단하기</h4>
	<c:choose>
		<c:when test="${ number mod 2 eq 0 }">
          ${number}은 짝수
        </c:when>
		<c:otherwise> ${number}은 홀수 </c:otherwise>
	</c:choose>

	<h4>,,수 점수를 입력하면 평균을 내어 학점 출력</h4>
	<form>
		<!-- 점수 입력 폼 -->
		국어 : <input type="text" name="kor" /> <br /> 영어 : <input type="text"
			name="eng" /> <br /> 수학 : <input type="text" name="math" /> <br />
		<input type="submit" value="학점 구하기" />
	</form>
	<!-- 모든 과목의 점수가 입력되었는지 확인 -->
	<c:if
		test="${ not (empty param.kor or empty param.eng or empty param.math) }">
		<!-- 평균 계산 -->
		<c:set var="avg" value="${(param.kor + param.eng + param.math)/3 }" />
        평균 점수는 ${avg }으로
        <!-- 학점 출력 -->
		<c:choose>
			<c:when test="${avg >= 90 }">A</c:when>
			<c:when test="${avg >= 80 }">B</c:when>
			<c:when test="${avg ge 70 }">C</c:when>
			<c:when test="${avg ge 60 }">D</c:when>
			<c:otherwise>F</c:otherwise>
		</c:choose>  
        입니다.
   </c:if>
</body>
</html>

6. <c:forEach> 태그

  • <c:forEach> 태그는 반복을 위해 사용
  • 자바는 두 가지 형태의 for문을 제공
    • 시작과 종료를 지정하는 일반 for문

      <c:forEach var="변수명" begin="시작값" end="마지막값" step="증가값" />
       for ( int i = 0 ; i < 100 ; i += 2 ) { ... }
    • 예제

```java
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>JSTL - forEach 1</title></head>
<body>
    <h4>일반 for문 형태의 forEach 태그</h4>
    <c:forEach begin="1" end="3" step="1" var="i">
        <p>반복 ${ i }입니다</p>
    </c:forEach>

    <h4>varStatus 속성 살펴보기 : 속성값: 상태를 알려줄 변수명 지정 : loop</h4>
    <table border="1">
    <c:forEach begin="3" end="5" var="i" varStatus="loop">
        <tr>
            <td>count : ${ loop.count }</td>
            <td>index : ${ loop.index }</td>
            <td>current : ${ loop.current }</td>
            <td>first : ${ loop.first }</td>
            <td>last : ${ loop.last }</td>
        </tr>
    </c:forEach>
    </table>

    <h4>1에서 100까지 정수 중 홀수의 합</h4>
    <c:forEach begin="1" end="100" step = "1" var="j">
        <c:if test="${ j mod 2 ne 0}">
            <c:set var="sum" value="${ sum + j }" />
        </c:if>
    </c:forEach>
    1~100 사이의 정수 중 홀수의 합은? ${ sum }
</body>
</html>
```

- 배열이나 컬렉션을 순회할 때 사용하는 향상된 for문(enhanced for loop)

```java
<c:forEach var="변수명" items="컬렉션 혹은 배열" />
for ( int number : numbers ) { ... }
```

- 예제

![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/76add442-87c8-440f-aacc-4b06dae57602/Untitled.png)

```java
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>JSTL - forEach2</title></head>
<body>
    <h4>향상된 for문 형태의 forEach 태그</h4>
    <%
    String[] rgba = {"Red", "Green", "Blue", "Black"};
    %>
    <c:forEach items="<%= rgba %>" var="c">
        <span style="color:${ c };">${ c }</span>
    </c:forEach>

    <h4>varStatus 속성 살펴보기</h4>
    <table border="1">
    <c:forEach items="<%= rgba %>" var="c" varStatus="loop">
        <tr>
        	<td>${c}</td>
            <td>count : ${ loop.count }</td>
            <td>index : ${ loop.index }</td>
            <td>current : ${ loop.current }</td>
            <td>first : ${ loop.first }</td>
            <td>last : ${ loop.last }</td>
        </tr>
    </c:forEach>
    </table>
</body>
</html>
```

- 예제 2

![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/a6b416cc-b0a6-4d4c-9218-0521edc34912/Untitled.png)

```java
<%@ page import="java.util.HashMap"%>
<%@ page import="java.util.Map"%>
<%@ page import="common.Person"%>
<%@ page import="java.util.LinkedList"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>JSTL - forEach 2</title></head>
<body>
    <h4>List 컬렉션 사용하기</h4>
    <%
    LinkedList<Person> lists = new LinkedList<Person>();
    lists.add(new Person("맹사성", 34));
    lists.add(new Person("장영실", 44));
    lists.add(new Person("신숙주", 54));
    %>
    <c:set var="lists" value="<%= lists %>"/>
    <c:forEach items="${ lists }" var="list">
    <li>
        이름 : ${ list.name }, 나이 : ${ list.age }
    </li>
    </c:forEach>

    <h4>Map 컬렉션 사용하기</h4>
    <%
    Map<String,Person> maps = new HashMap<String,Person>();
    maps.put("1st", new Person("맹사성", 34));
    maps.put("2nd", new Person("장영실", 44));
    maps.put("3rd", new Person("신숙주", 54));
    %>
    <c:set var="maps" value="<%= maps %>" />
    <c:forEach items="${ maps }" var="map">
        <li>Key => ${ map.key }  <br />
            Value => 이름 : ${ map.value.name }, 나이 : ${ map.value.age }</li>
    </c:forEach>
</body>
</html>
```

7. <e:forTokens> 태그

  • <c:forTokens> 태그는 마치 자바의 StringTokenizer 클래스처럼 구분자를 기준으로
    문자열을 나눠 토큰의 개수큼 반복

<%@ 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>JSTL- forTokens</title>
</head>
<body>
토큰 - 문법적으로 의미있는 최소 단위
<% 
	String rgba = "Red-Green-Blue-Black";
%>
<h4>JSTL의 forTokens 태그 사용 : "Red Green Blue Black"</h4>
<c:forTokens items="<%= rgba %>" delims="-" var="color">
<span style="color:${color};">${color }</span> <br/>
</c:forTokens>
</body>
</html>

8. <c:import> 태그

  • <c:import> 태그는 jsp:include 액션 태그와 같이 외부 파일을 현재 위치에 삽입할 때 사용
  • 또한 같은 웹 애플리케이션에 속하지 않은 외부의 페이지도 삽입할 수 있음
<c:import url="페이지 경로 혹은 URL" var="변수명" scope="영역" />
${ 변수명 }
<c:import url="페이지 경로 혹은 URL?매개변수1=값1" >
 <c:param name="매개변수2" value="값2" />
</c:import>
  • import.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>JSTL - import</title></head>
<body>
    <c:set var="reqVar" value="MustHave" scope="request" />
    <c:import url="/10JSTL/core/inc/OtherPage.jsp" var="contents">
        <c:param name="user1" value="JSTL" />
        <c:param name="user2" value="JSP" />
    </c:import>       
    
    <h4>다른 문서 삽입하기</h4>
    ${contents }
    
    <h4>외부 자원 삽입하기</h4>    
  
</body>
</html>
  • Otherpage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<ul>
<li> value : ${ reqVar }</li>
<li> param1 : ${ param.user1 }</li>
<li> param2 : ${ param.user2 }</li>
</ul>

</body>
</html>

9. <c:redirect> 태그

  • <c:redirect> 태그는 response 내장 객체의 sendRedirect( )와 동일하게 페이지 이동을 처리
  • redirect는 새로운 페이지를 열어서 위에 있는 것 들은 전달이 안됨

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>JSTL - import</title></head>
<body>
<c:set var="reqVar" value="MustHave" scope="request" />
    <c:import url="/10JSTL/core/inc/OtherPage.jsp" var="contents">
        <c:param name="user1" value="JSTL" />
        <c:param name="user2" value="JSP" />
    </c:import>       
    
    <h4>다른 문서 삽입하기</h4>
    ${contents }
    
    <c:set var="requestVar" value="multi" scope="request"/>
    <!-- redirect는 새로운 페이지를 열어서 위에 있는 것 들은 전달이 안됨 -->
    <c:redirect url="/10JSTL/core/inc/OtherPage.jsp">
    <c:param name="user4" value="홍길동" />
    <c:param name="user5" value="고길동" />
    </c:redirect>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<ul>
<li> value : ${ reqVar }</li>
<li> param1 : ${ param.user1 }</li>
<li> param2 : ${ param.user2 }</li>
<li> param3 : ${ param.user4 }</li>
<li> param4 : ${ param.user5 }</li>
</ul>

</body>
</html>

10. <c:url> 태그

  • <c:url> 태그는 지정한 경로와 매개변수를 이용해서 컨텍스트 루트를 포함한 URL을 생성
  • 생성된 URL은 태그의 href 속성이나, 태그의 action 속성에 사용할 수 있음
<c:url value="설정한 경로" scope="영역" var="변수명" />
... 생략(JSP 코드) ...
${ 변수명 } <!-- 원하는 위치에 URL 삽입 -->

11. <c:out> 태그

  • <c:out> 태그는 JSP의 표현식처럼 변수를 출력 때 사용
  • value 속성이 null 일 때만 default값 출력

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>   
<html>
<head><title>JSTL - out</title></head>
<body>
    <c:set var="iTag">
        i 태그는 <i>기울임</i>을 표현합니다.
    </c:set>

    <h4>기본 사용</h4>
    <c:out value="${ iTag }" />
    
    <h4>escapeXml 속성</h4>
    <c:out value="${ iTag }" escapeXml="false" />  
    
    <h4>default 속성</h4>
    <c:out value="${ param.name }" default="이름 없음" />
    <c:out value= "" default="빈 문자열도 값입니다." />
</body>
</html>

12. catch 태그

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>    
<html>
<head><title>JSTL - catch</title></head>
<body>
    <h4>자바 코드에서의 예외</h4>
   <c:set var= "num1" value= "100"/>
    <%
        int num1 = 100;
        %>
    <c:catch var="eMessage">
        <%
        int result = num1 / 0;
        %>
    </c:catch>
    예외 내용 : ${ eMessage }
    
    <h4>EL에서의 예외</h4>
    <c:set var="num2" value="200" />

    <c:catch var="eMessage">
        ${"일" + num2 }
    </c:catch>    
    예외 내용 : ${ eMessage }
</body>
</html>

국제화 태그

Formatting

  • 국가별로 다양한 언어, 날짜, 시간, 숫자 형식을 설정 시 사용
  • 국제화 태그 사용하려면 지시어 선언
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
  • 숫자 포맷 설정
<fmt:formatNumber value="출력할 숫자" type="출력 양식" var="변수 설정"
 groupingUsed="구분 기호 사용 여부" pattern="숫자 패턴" scope="영역" />
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>       
<html>
<head><title>JSTL - fmt 1</title></head>
<body>
    <h4>숫자 포맷 설정</h4>
    <c:set var="number1" value="12345" />
    콤마 O : <fmt:formatNumber value="${ number1 }" /><br />
    콤마 X : <fmt:formatNumber value="${ number1 }" groupingUsed="false" /><br />
    <fmt:formatNumber value="${number1 }" type="currency" var="printNum1" />
    통화기호 : ${ printNum1 } <br />
    <fmt:formatNumber value="0.03" type="percent" var="printNum2" />
    퍼센트 : ${ printNum2 }
    
    <h4>문자열을 숫자로 변경</h4>
    <c:set var="number2" value="6,789.01"  /> 
    <fmt:parseNumber value="${ number2 }" pattern="00,000.00" var="printNum3" /> 
    소수점까지 : ${ printNum3 } <br />
    <fmt:parseNumber value="${ number2 }" integerOnly="true" var="printNum4" /> 
    정수 부분만 : ${ printNum4 }
</body>
</html>
  • 날짜 포맷 및 타임존
<fmt:formatDate value="출력할 날짜" type="출력 양식" var="변수 설정"
 dateStyle="날짜 스타일" timeStyle="시간 스타일" pattern="날짜 패턴" scope="영역"
/>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>       
<html>
<head><title>JSTL - fmt 2</title></head>
<body>
    <c:set var="today" value="<%= new java.util.Date() %>" />
    
    <h4>날짜 포맷</h4>
    full : <fmt:formatDate value="${ today }" type="date" dateStyle="full"/> <br /> 
    short : <fmt:formatDate value="${ today }" type="date" dateStyle="short"/> <br />
    long : <fmt:formatDate value="${ today }" type="date" dateStyle="long"/> <br />
    default : <fmt:formatDate value="${ today }" type="date" dateStyle="default"/>

    <h4>시간 포맷</h4> 
    full : <fmt:formatDate value="${ today }" type="time" timeStyle="full"/> <br /> 
    short : <fmt:formatDate value="${ today }" type="time" timeStyle="short"/> <br />
    long : <fmt:formatDate value="${ today }" type="time" timeStyle="long"/> <br />
    default : <fmt:formatDate value="${ today }" type="time" timeStyle="default"/>
    
    <h4>날짜/시간 표시</h4>    
    <fmt:formatDate value="${ today }" type="both" dateStyle="full" timeStyle="full"/> 
    <br />
    <fmt:formatDate value="${ today }" type="both" pattern="yyyy-MM-dd hh:mm:ss"/> 
    
    <h4>타임존 설정</h4>
    <fmt:timeZone value="GMT"> 
        <fmt:formatDate value="${ today }" type="both" dateStyle="full" timeStyle="full"/>
        <br />    
    </fmt:timeZone>
    <fmt:timeZone value="America/Chicago">
        <fmt:formatDate value="${ today }" type="both" dateStyle="full" timeStyle="full"/>
    </fmt:timeZone>
</body>
</html>
  • 로케일 설정을 한글, 영어, 일어로 설정
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>       
<html>
<head><title>JSTL - fmt 3</title></head>
<body>
    <h4>로케일 설정</h4>    
    <c:set var="today" value="<%=  new java.util.Date() %>"/>
    
    한글로 설정 : <fmt:setLocale value="ko_kr" />
    <fmt:formatNumber value="10000" type="currency" /> /
    <fmt:formatDate value="${ today }" /><br />

    일어로 설정 : <fmt:setLocale value="ja_JP" />
    <fmt:formatNumber value="10000" type="currency" /> /
    <fmt:formatDate value="${ today }" /><br />
    
    영어로 설정 : <fmt:setLocale value="en_US" />
    <fmt:formatNumber value="10000" type="currency" /> /
    <fmt:formatDate value="${ today }" /><br />    
</body>
</html>

10. 파일 업로드 및 다운로드

라이브러리 추가

  • cos.jar 다운

Servlets.com | com.oreilly.servlet

파일 업로드

작성폼

  • 사진

  • method 속성은 반드시 post로, enctype 속성은 multipart/form-data로 지정
  • enctype은 폼값을 서버로 전송할 때의 인코딩 방식을 지정하는 속성
  • input 태그의 type 속성을 file로 지정
<form method="post" enctype="multipart/form-data" action="업로드 처리 파일 경로">
<input type="file" name="input 이름" />
</form>
  • java

  • MyfileDTO
    package fileupload;
    
    public class MyfileDTO { //게시글 하나의 저장소
    	
    	private String idx; //pk 파일기본키
    	private String name; //작성자
    	private String title; //제목
    	private String cate; //카테고리
    	private String ofile; //
    	private String sfile;
    	private String postdate;
    	
    	public String getIdx() {
    		return idx;
    	}
    
    	public void setIdx(String idx) {
    		this.idx = idx;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public String getTitle() {
    		return title;
    	}
    
    	public void setTitle(String title) {
    		this.title = title;
    	}
    
    	public String getCate() {
    		return cate;
    	}
    
    	public void setCate(String cate) {
    		this.cate = cate;
    	}
    
    	public String getOfile() {
    		return ofile;
    	}
    
    	public void setOfile(String ofile) {
    		this.ofile = ofile;
    	}
    
    	public String getSfile() {
    		return sfile;
    	}
    
    	public void setSfile(String sfile) {
    		this.sfile = sfile;
    	}
    
    	public String getPostdate() {
    		return postdate;
    	}
    
    	public void setPostdate(String postdate) {
    		this.postdate = postdate;
    	}
    
    	public MyfileDTO() {
    		
    	}
    	
    }```
  
- MyfileDAO.java
    
package fileupload;

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

import common.DBConnPool;

public class MyfileDAO extends DBConnPool{
	public MyfileDAO () {
		
	}
	// 새로운 게시물을 입력(Insert) 기능
	public int insertFile(MyfileDTO dto) { //int로 받는 이유는 해당 함수가 파일을 삽입하고, 그 작업의 성공 여부를 호출한 쪽에 알려주기 위해서
		int result = 0;
		
		try {
			// 쿼리문 작성
			String query =  "INSERT INTO myfile( "
					+" idx, name, title, cate, ofile, sfile )"
					+" VALUES ( "
					+" seq_board_num.nextval, ?, ?, ?, ?, ?, sysdate)";
					
			// pstmt에 쿼리문을 싣고, 인파라미터 작업
			pstmt = con.prepareStatement(query);		
			pstmt.setString(1, dto.getName());		
			pstmt.setString(2, dto.getTitle());		
			pstmt.setString(3, dto.getCate());		
			pstmt.setString(4, dto.getOfile());
			pstmt.setString(5, dto.getSfile());
			// 쿼리 실행
			result = pstmt.executeUpdate();
			
		}catch(Exception e) {
			System.out.println("insert 중 예외 발생");
			e.printStackTrace();
		}
		
		return 0;
	}
	
	//myfile테이블로부터 파일업로드한 리스트 목록 가져오기 
	
		public List<MyfileDTO> myFileList(){
			
			List<MyfileDTO> fileList = new ArrayList<MyfileDTO>(); //자바어플리케이션 myfile테이블의 전체레코드셋을 저장
			
				
			//쿼리문 작성 
			  String query = "SELECT * FROM myfile ORDER BY idx DESC";
			try {
				//쿼리문 실행 
				pstmt = con.prepareStatement(query);
				rs = pstmt.executeQuery();  
				
				
				//목록안의 파일 수만큼 반복 
				while(rs.next()) {
	           		//DTO 저장
					MyfileDTO  dto = new MyfileDTO();
					
					dto.setIdx(rs.getString("idx"));
					dto.setName(rs.getString("name"));
					dto.setTitle(rs.getString("title"));
					dto.setCate(rs.getString("cate"));
					dto.setOfile(rs.getString("ofile"));
					dto.setSfile(rs.getString("sfile"));
					dto.setPostdate(rs.getDate("postdate"));
					
					fileList.add(dto);  //목록에 추가 			
				}
					
			} catch (Exception e) {
				System.out.println("SELECT 시 예외상황 발생");
				e.printStackTrace();
			}
			
			return fileList;  //목록 반환
		}
}
```
  • 생성 후 파일이 저장될 폴더 생성

  • 11FileUpload
    • fileUploadMain.jsp
      - form.name.focus(); : 커서 이동

      <%@ page language="java" contentType="text/html; charset=UTF-8"
          pageEncoding="UTF-8"%>
          <%@ page import="utils.JSFunction" %>
      <!DOCTYPE html>
      <html>
      <head>
      <meta charset="UTF-8">
      <title>Insert title here</title>
      </head>
      <body>
      <script type="text/javascript">
      		function validateForm(form) {
      			if (!form.name.value) {
      				alert('작성자 이름 입력해주세요');
      				form.name.focus();
      				return false;
      			}
      			if (form.title.value == "") {
      				alert("제목를 입력하세요");
      				form.title.focus();
      				return false;
      			}
      			if (form.fileInput.value == "") {
      				alert("첨부파일 넣어주세요");
      				form.fileInput.focus();
      				return false;
      			}
      
      		}
      	</script>
      	
      <table align=center>
          <form method="post" enctype="multipart/formdata" 
          action="UploadProcess.jsp" onsubmit="return validateForm(this)">
              <h2>파일 업로드</h2>
              <div>
                  <label for="name">작성자 :</label>
                  <input type="text" id="name" name="name" required>
              </div>
              <div>
                  <label for="title">제목 :</label>
                  <input type="text" id="title" name="title" required>
              </div>
              <div>
              	<label for="check">선택사항 : </label>
                  <label><input type="checkbox" name="cata" value="사진" checked> 사진</label>
                  <label><input type="checkbox" name="cata" value="사회"> 사회</label>
                  <label><input type="checkbox" name="cata" value="과학"> 과학</label>
                  <label><input type="checkbox" name="cata" value="음악"> 음악</label>
              </div>
              <div>
                  <label for="fileInput">첨부파일 :</label>
                  <input type="file" id="fileInput" name="fileInput" required>
              </div>
              <div>
                  <input type="submit" value="전송">
              </div>
          </form>
      </body>
      </html>
    • UploadProcess.jsp

      <%@ page import="fileupload.MyfileDAO"%>
      <%@ page import="fileupload.MyfileDTO"%>
      <%@ page import="java.util.Date"%>
      <%@ page import="java.text.SimpleDateFormat"%>
      <%@ page import="java.io.File"%>
      <%@ page import="com.oreilly.servlet.MultipartRequest"%>
      <%@ page language="java" contentType="text/html; charset=UTF-8"
          pageEncoding="UTF-8"%>
      <%
      String saveDirectory = application.getRealPath("/Uploads");  // 저장할 디렉터리
      int maxPostSize = 1024 * 1000;  // 파일 최대 크기(1MB)
      String encoding = "UTF-8";  // 인코딩 방식
      
      try {
          // 1. MultipartRequest 객체 생성
          MultipartRequest mr = new MultipartRequest(request, saveDirectory,
                                                     maxPostSize, encoding);
      
          // 2. 새로운 파일명 생성
          String fileName = mr.getFilesystemName("attachedFile");  // 현재 파일 이름
          String ext = fileName.substring(fileName.lastIndexOf("."));  // 파일 확장자
          String now = new SimpleDateFormat("yyyyMMdd_HmsS").format(new Date());
          String newFileName = now + ext;  // 새로운 파일 이름("업로드일시.확장자")
      
          // 3. 파일명 변경
          File oldFile = new File(saveDirectory + File.separator + fileName);
          File newFile = new File(saveDirectory + File.separator + newFileName);
          oldFile.renameTo(newFile);
      
          // 4. 다른 폼값 받기
          String name = mr.getParameter("name");
          String title = mr.getParameter("title");
          String[] cateArray = mr.getParameterValues("cate");
          StringBuffer cateBuf = new StringBuffer();
          if (cateArray == null) {
              cateBuf.append("선택 없음");
          }
          else {
              for (String s : cateArray) {
                  cateBuf.append(s + ", ");
              }
          }
      
          // 5. DTO 생성
          MyfileDTO dto = new MyfileDTO();
          dto.setName(name);
          dto.setTitle(title);
          dto.setCate(cateBuf.toString());
          dto.setOfile(fileName);
          dto.setSfile(newFileName);
      
          // 6. DAO를 통해 데이터베이스에 반영
          MyfileDAO dao = new MyfileDAO();
          dao.insertFile(dto);
          dao.close();
      
          // 7. 파일 목록 JSP로 리디렉션
          response.sendRedirect("FileList.jsp");
      }
      catch (Exception e) {
          e.printStackTrace();
          request.setAttribute("errorMessage", "파일 업로드 오류");
          request.getRequestDispatcher("FileUploadMain.jsp").forward(request, response);
      }
      %>
  • FileList.jsp
    <%@ page import="java.net.URLEncoder"%>
    <%@ page import="java.util.List"%>
    <%@ page import="fileupload.MyfileDAO"%>
    <%@ page import="fileupload.MyfileDTO"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <html>
    <head><title>FileUpload</title></head>
    <body>
        <h2>DB에 등록된 파일 목록 보기</h2>
        <a href="FileUploadMain.jsp">파일 등록하기</a>
        <%
        MyfileDAO dao = new MyfileDAO();
        List<MyfileDTO> fileLists = dao.myFileList();
        dao.close();
        %>
        <table border="1">
            <tr>
                <th>No</th><th>작성자</th><th>제목</th><th>카테고리</th>
                <th>원본 파일명</th><th>저장된 파일명</th><th>작성일</th><th></th>
            </tr>
        <% for (MyfileDTO f : fileLists) { %>
            <tr>
                <td><%= f.getIdx() %></td>
                <td><%= f.getName() %></td>
                <td><%= f.getTitle() %></td>
                <td><%= f.getCate() %></td>
                <td><%= f.getOfile() %></td>
                <td><%= f.getSfile() %></td>
                <td><%= f.getPostdate() %></td>
                <td><a href="Download.jsp?oName=<%= URLEncoder.encode(f.getOfile(),"UTF-8") %>&sName=<%= URLEncoder.encode(f.getSfile(),"UTF-8") %>">[다운로드]</a></td>
            </tr>
        <% } %>
        </table>    
    </body>
    </html>
    • Download.jsp

      <%@ page import="java.io.File" %>
      <%@ page import="java.io.FileNotFoundException" %>
      <%@ page import="java.io.FileInputStream" %>
      <%@ page import="java.io.OutputStream" %>
      <%@ page import="java.io.InputStream" %>
      <%@ page import="utils.JSFunction" %>
      <%@ page language="java" contentType="text/html; charset=UTF-8"
          pageEncoding="UTF-8"%>
          
      <%
      	String saveDirectory = application.getRealPath("/Uploads");
      	String saveFilename = request.getParameter("sName");
      	String originalFilename = request.getRealPath("oName");
      	
      	try{
      		//파일을 찾아 입력 스트림 생성
      		File file = new File(saveDirectory, saveFilename);
      		InputStream inStream = new FileInputStream(file);
      		
      		String client = request.getHeader("User-Agent");
      		if(client.indexOf("WOW64")==1){
      			originalFilename = new String(originalFilename.getBytes("UTF-8"), "ISO-8859-1");
      		}
      		else{
      			originalFilename = new String(originalFilename.getBytes("KSC5601"),"ISO-8859-1");
      		}
      		//파일 다운로드용 응답 헤더 설정
      		response.reset();
      		response.setContentType("application/octet-stream"); //8bit단위의 바이너리 데이터
      		response.setHeader("Content-Disposition", "attachment; filname=\""+originalFilename + "\"");
      		response.setHeader("Content-Length", "" + file.length());
      		
      		// 출력 스트림 초기화
      		out.clear();
      		
      		//response 객체로부터 새로운 출력스트림 생성
      		OutputStream outStream = response.getOutputStream();
      		
      		byte[] b = new byte[(int)file.length()];
      		int readBuffer = 0;
      		while((readBuffer = inStream.read(b)) > 0){
      			outStream.write(b, 0, readBuffer);
      		}
      		
      		inStream.close();
      		outStream.close();
      	}
      	catch(FileNotFoundException e){
      		JSFunction.alertBack("파일을 찾을 수 없습니다", out);
      	}
      	catch(Exception el){
      		JSFunction.alertBack("예외 발생 다시 시도 해주세요", out);
      	}
      %>
      <!DOCTYPE html>
      <html>
      <head>
      <meta charset="UTF-8">
      <title>Download.jsp</title>
      </head>
      <body>
      
      </body>
      </html>

오늘의 에러

문제 상황

- 두 가지의 문제 상황
    - prepareStatment가 null로 넘어온다는 것
    - DBConnPool이 실패

- DBConnPool이 실패 그래서  server.xml과 context.xml을 확인 해봄

⇒ 잘못 이름이 들어가 있나 해서
  • server.xml

    <GlobalNamingResources>
        <!-- Editable user database that can also be used by
             UserDatabaseRealm to authenticate users
        -->
        <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
    
     <Resource auth="Container" driverClassName="oracle.jdbc.OracleDriver" initialSize="0" maxIdel="20" maxTotal="20" maxWaitMillis="5000" minIdle="5" name="dbcp_myoracle" password="1234" type="javax.sql.DataSource" url="jdbc:oracle:thin:@localhost:1521:orcl" username="multi"/>
    
      </GlobalNamingResources>
  • db 자체는 연결이 돼서 로그인은 됐음

  • 그렇다면 context.xml?

    <ResorurceLink global="dbcp_myoracle" name="dbcp_myoracle" type="javax.sql.DataSource"/>	
    </Context>

    ⇒ 잘 들어가 있음

이거는 파일이랑 작성자 등을 입력 받아서 파일 목록 출력 후 다운로드 하는 형태

해결

  • 바인딩
  • Servelt.api와 jsp.api를 직접 바인딩해서 해결

공부하면 좋은 것

java.io.InputStream
java.io.File클래스
java.io.OutPutStream 클래스 학습

회고

끙끙 앓았던 것이 결국.. 서버가 API를 못 찾아서 직접 바인딩 해결을 못해서 블로그 올리는 시점인 7월27일 강사님과 같이 해결했다. 나는 NULLPOINTException 나길래 다른 문제인가 했더니이 문제 였구나 하나 더 배워 간다.

profile
내 지식을 기록하여, 다른 사람들과 공유하여 함께 발전하는 사람이 되고 싶다. 참고로 워드프레스는 아직 수정중

0개의 댓글