국비/JSP

2023.04.05 49일차 JSP

춘핑이 2023. 4. 5. 18:18

49일차 JSP JSTL

12 jsp standard tag libraray

jsp작성하면서 웹어플리케이션이 어떻게 작동하는지 배우고 있다.
12장 표준태그라이브러리를 배울 것이다.

jsp에 자바코드가 섞여있는게 불편하다. 자바코드를 따로 빼고싶다.
대신할 수 있는 태그들을 만들었다. element를 만든것이다.
tag library를 잘만들어놔서 표준이 되었다.

라이브러리를 다운받아야 사용할 수 있다.
톰캣사이트를 들어가보자.

Standard-1.2.5 jar파일 중 두개 imlp, spec둘다 다운
src-main-webapp-WEB-INF-lib에 복붙
lib폴더는 클래스 라이브러리 등을 넣는 것이다.

294쪽의 코어태그 중 일부를 배울 것이다.

12.1 if

JSTL을 사용하기전엔 IF문 사이사이를 열고 닫고 하면서 출력내용이 들어가야해서
불편했엇다.
코드가 짧으면 상관없는데 길어지면 헷갈릴 수밖에없었다.

<% 
    String name = request.getParameter("name");
    if (name == null || name.isEmpty()){
%>    
    <h1>name 파라미터가 없습니다.</h1>
<%         
    } else{
%>        
    <h1>name 파라미터가 있습니다.</h1>
<%         
    }
%>

12.2 JSTL if

태그를 사용하려면 페이지 디렉티브에 taglib을 작성해줘야한다. 사용할 위치 uri
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
실제 존재하는 사이트가 아니라 특정 uri를 쓰면 이코드를 쓰겟다고 약속을 해둔 것이다.
여기있는 태그를 어떤 prefix로 쓸건지도 정해줘야한다. 태그앞에 c를쓰겟다고 명시하는 것이다.

<c:if>로 사용되고 test attribute로 조건검사를 한다.

<c:if test="true">
    <!-- 실행되거나 되지 않거나 -->
    <h1>항상실행</h1>
</c:if>

<c:if test="false">
    <h1>실행 안됨</h1>
</c:if>

12.3 JSTL if

이전 실습에서는 그냥 true값과 false를 주었지만 JSTL에서 IF문의 조건은 EL을 사용해서 처리한다.
이렇게 자바코드를 없이 작성하게 되면 코드 유지보수가 쉬워진다.
우리눈에는 html이지만 자바코드로 변경이 된다.

<c:if test="${empty param.name }">
    <h1>name 파라미터가 없습니다.</h1>
</c:if>

<c:if test="${not empty param.name }">
    <h1>name 파라미터가 있습니다.</h1>
</c:if>

12.4 JSTL IF

java에서 if를 배우고 else를 사용했는데 jstl에는 else문은 없다
else문처럼 사용할 수 있는 방법은 있다.

조건이 굉장히 복잡한 식이라고 햇을때 not만 붙이면된다.
그래서 if태그에 var attribute로 변수를 선언하면 조건이 페이지 영역에 var변수 이름으로 저장이된다.
pageContext영역에 attribute로 넣는 것이기 때문에 EL태그로 사용할 수 있다.

배타적으로 조건을 적을 수도 있지만 반복해서 사용하지 않도록 코드를 줄일 수 있다.

<c:if test="${(not empty param.name) and (param.age > 20)}" var="test1">
    <h1>${param.name}님은 성인입니다.</h1>
</c:if>

<c:if test="${(empty param.name) or (param.age <= 20)}" >
    <h1>이름이 없거나 성인이 아닙니다.</h1>
</c:if>

<c:if test="${not test1}" >
    <h1>이름이 없거나 성인이 아닙니다.</h1>
</c:if>

12.5 JSTL IF연습

name파라미터가 없을 때와 있을때
movies 파라미터가 없을 때 있을때를 구분해서 작성해보자.

<form action="07process.jsp">
    이름 : <input type="text" name="name" /> <br />
    영화 : <br />
    <input type="checkbox" name="movies" value="스즈메의문단속"/>스즈메의문단속
    <input type="checkbox" name="movies" value="슬램덩크" />슬램덩크
    <input type="checkbox" name="movies" value="에어" />에어
    <br />
    <input type="submit" value="전송"/>
</form>

<c:if test="${empty param.name}" var="np">
    <!-- name파라미터가 없을 때 -->
    <div>이름이 없습니다.</div>
</c:if>

<c:if test="${not np}">
    <!-- name파라미터가 있을 때 -->
    <div>${param.name }님</div>
</c:if>

<c:if test="${empty paramValues.movies}" var="nm">
    <!-- movies 파라미터가 없을 때 -->
    <div>선택된 영화가 없습니다.</div>
</c:if>

<c:if test="${empty paramValues.movies}" var="nm">
    <!-- movies 파라미터가 없을 때 -->
    <div>선택된 영화가 없습니다.</div>
</c:if>

<c:if test="${not nm}">
    <div>
        선택한 영화들
        <ul>
            <li>${paramValues.movies[0]}</li>
            <li>${paramValues.movies[1]}</li>
            <li>${paramValues.movies[2]}</li>
        </ul>
    </div>
</c:if>

12.6 JSTL choose-when-otherwise

choose-when-otherwise는 자바의 elsif와 유사하다. switch구문과 비슷하다.

choose 태그를 만나면 안쪽의 when태그를 만나 조건검사를 한다.
else if를 여러개 붙일 수 잇던 것처럼 when태그를 여러개 붙일 수 있다.

else if는 위에서부터 조건을 따져서 조건처리를 했는데
when도 위에서부터 처리해서 조건처리를 한다.
여러개가 true여도 맨처음의 true만 실행된다.

otherwise는 다 false일때 마지막에 else의 느낌으로 처리되는 것이다.
생략할 수도 있다.

<h1>choose, when, otherwise</h1>

<c:choose>
    <c:when test="false">
        <h1>첫번째 조건이 true</h1>
    </c:when>

    <c:when test="false">
        <h1>두번째 조건이 true</h1>
    </c:when>

    <c:when test="false">
        <h1>세번째 조건이 true</h1>
    </c:when>

    <c:otherwise>
        <h1>위의 when이 모두 false</h1>
    </c:otherwise>
</c:choose>

12.7 choose 연습

장르파라미터를 받고 세개의 div중 하나만 출력되도록하자.
if문으로 작성할 수도 있지만 choose문을 사용해서 작성해보자

<form action="03process.jsp">
    <label for="movie">추천 영화</label>
    <select name="genre" id="movie">
        <option value="action">액션</option>
        <option value="horror">호러</option>
        <option value="family">가족</option>
        <option value="other">기타</option>
    </select>
    <br />
    <input type="submit" value="전송" />
</form>

<c:choose>
    <c:when test="${param.genre == 'action'}">
        <!-- genre 파라미터가 action이면 -->
        <div>추천영화 어밴져스 입니다.</div>
    </c:when>

    <c:when test="${param.genre == 'horror'}">
        <!-- genre 파라미터가 horror이면 -->
        <div>추천영화는 스크림 입니다.</div>
    </c:when>

    <c:when test="${param.genre == 'family'}">
        <!-- genre 파라미터가 family이면 -->
        <div>추천영화는 아바타 입니다.</div>
    </c:when>

    <c:otherwise>
        <!-- genre 파라미터가 위의 3개가 모두 아니면 -->
        <div>
            <a href="02form.jsp">장르를 선택해주세요</a>
        </div>
    </c:otherwise>
</c:choose>

12.8 JSTL forEach

자바코드의 반복문에 해당하는 내용이다. 여러번 반복해서 출력하고 싶을때 사용한다.
begin attribute부터 end attribute까지 반복을 한다.

다음 코드는 1번부터 파라미터 num번까지 반복하는 코드이다.

<c:forEach begin="1" end="${param.num }">
    <p>Lorem.</p>
</c:forEach>

12.9 forEach연습

3번파일에서 count와 name을 파라미터로 전달하고
4번파일에서 count만큼 name을 반복 출력해보자.

<h1>3번 파일</h1>
<form action="04process.jsp">
    이름 : <input type="text" name="name" value="서태웅"/> <br />
    반복 : <input type="number" name="count" value="1"/> <br />
    <input type="submit" value="반복 출력" />
</form>

<h1>4번 파일</h1>
<c:forEach begin="1" end="${param.count}">
    <p>${param.name}</p>
</c:forEach>
<a href="03form.jsp">3번파일로가기</a>

12.10 forEach - 2

java를 배울때 count변수 i를 for문 안쪽에 작성한적이 있었다.
var attribute를 추가하면 forEach문안쪽에서 사용할 수 있다.
begin부터 end의 값이 var에 pageContext attribute로 값이 설정되게 된다.

<c:forEach begin="1" end="5" var="i">
    <p>${i}, lorem</p>
</c:forEach>

활용해서 구구단 5단을 작성해보자

<h1>구구단 5단</h1>
<!-- 5*1~ 5*9 -->
<c:forEach begin="1" end="9" var="n">
    <p>5 X ${n} = ${ 5 * n }</p>
</c:forEach>

12.11 forEach - 3 연습

7번파일에서 구구단 단을 위한 파라미터를 전달해서 해당 단의 구구단을 출력하자.

<h1>7번</h1>
<form action="08process.jsp">
    구구단 <br />
    <input type="number" name="dan" value="2"/>단<br />
    <input type="submit" value="보기"/>
</form>

<h1>8번</h1>
${param.dan} 단 <br />
<c:forEach begin="1" end="9" var="i">
    ${param.dan} x ${i} = ${param.dan * i} <br />
</c:forEach>
<a href="07form.jsp">7번파일로 가기</a>

begin이 end보다 클수는 없다. 그래서 거꾸로 탐색하고 싶다면 출력에서 트릭을 사용해야한다.
그런데 jsp에서는 왠만하면 연산을 하지 않는 것이 좋다.

<h1>거꾸로</h1>
${param.dan} 단 <br />
<c:forEach begin="1" end="9" var="i">
    ${param.dan} x ${(10-i)} = ${param.dan * (10-i)} <br />
</c:forEach>

12.12 forEach응용

게시물 밑에 페이지 번호 링크가 있는것을 본적있을 것이다.
페이징처리

<c:forEach begin="1" end="10" var="pageNumber">
    <a href="#">${pageNumber}</a>
</c:forEach>
<hr />
<c:forEach begin="11" end="20" var="pageNumber">
    <a href="#">${pageNumber}</a>
</c:forEach>

부트스트랩을 활용하면 스타일을 꾸밀수있으니 같이 적용해보자.
Pagination li부분을 반복문으로 해주면된다.

<%@ 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">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Insert title here</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
</head>
<body>
    <nav aria-label="Page navigation example">
      <ul class="pagination">
        <li class="page-item"><a class="page-link" href="#">Previous</a></li>
        <c:forEach begin="1" end="10" var="pageNumber">
            <li class="page-item"><a class="page-link" href="#">${pageNumber}</a></li>
        </c:forEach>
        <li class="page-item"><a class="page-link" href="#">Next</a></li>
      </ul>
    </nav>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
</body>
</html>

12.13 응용

부트스트랩 클래스에 active를 추가하면 선택된 것이 표시되는 기능이있다.
페이지 값을 파라미터로 받고 만약 파라미터와 현재 반복의 번호가 같다면
active클래스가 추가되도록 해보자.
c:if를 사용하거나 EL의 삼항연산을 사용할 수 있다.

<nav>
    <ul class="pagination">
        <c:forEach begin="11" end="20" var="pageNumber">
            <li class="page-item
                <c:if test="${pageNumber == param.p }">
                    active
                </c:if>
            ">
                <a href="?p=${pageNumber }" class="page-link">${pageNumber }</a>
            </li>
        </c:forEach>
    </ul>
</nav>

<nav aria-label="Page navigation example">
  <ul class="pagination">
    <li class="page-item"><a class="page-link" href="#">Previous</a></li>
    <c:forEach begin="11" end="20" var="pageNumber">
        <li class="page-item ${pageNumber == param.p ? 'active' : '' }"><a class="page-link" href="?p=${pageNumber}">${pageNumber}</a></li>
    </c:forEach>
    <li class="page-item"><a class="page-link" href="#">Next</a></li>
  </ul>
</nav>

12.14 forEach - 4

반복문을 사용한 이유중 하나가 collection, 배열의 값들을 탐색하려고 사용햇엇다.
forEach도 역시나 attribute에 list가 있다면 탐색해서 사용할 수 있다.

list의 아이템들을 반복해서 가져오고 싶다.
items attribute에는 탐색할 list를 EL표기법으로 넣으면된다. 실수해서 EL을 안하는 경우가 있는데 잊지말자.
이것을 넣어두면 item의 개수만큼 반복한다.

안의 element가 순서대로 들어가는 것이 var attribute의 값으로 들어가게 된다.
page영역에 var의 이름으로 들어가게 되는 것이다. 향상된 for문과 비슷한 느낌이다.
그래서 출력할때는 EL을 사용해야한다.

<%
    List<String> list = List.of("sql", "spring", "jsp", "java", "html");
    pageContext.setAttribute("mylist", list);
%>

<c:forEach items="${mylist}" var="item">
    <p>${item}</p>
</c:forEach>

12.15 forEach 연습

영화이름 3개가 출력되도록 list를 작성해보자.

<%
    List<String> list = new ArrayList<>();
    list.add("스즈메의문단속");
    list.add("던전앤드래곤");
    list.add("슬램덩크");

    pageContext.setAttribute("movies", list);
%>
<c:forEach items="${movies}" var="movie">
    <p>${movie}</p>
</c:forEach>

12.16 forEach 연습 - 2

form으로 넘어온 값들을 다른 jsp에서 반복문으로 출력해보자.
같은 이름으로 넘어오면 paramValues맵에 담아지는데
paramValues.이름(키)로 추출하면 밸류값으로 같은이름의 배열이 담겨있다.
그래서 item에 paramValues.이름을 넣으 수 있다.

<h1>14번 파일</h1>    
<form action="15process.jsp">
    좋아하는 음식들 : <br />
    <!-- select[name=foods][multiple]>option*5 -->
    <select name="foods" multiple>
        <option value="apple">apple</option>
        <option value="banana">banana</option>
        <option value="melon">melon</option>
        <option value="pizza">pizza</option>
        <option value="coffee">coffee</option>
    </select>
    <br />
    <input type="submit" value="전송" />        
</form>

<h1>15번파일</h1>
좋아하는 음식 : <br />
<ul>
    <c:forEach items="${paramValues.foods}" var="item">
        <li>${item }</li>
    </c:forEach>
</ul>

12.17 forEach연습 3

if와 함께 이용해보자
선택한 영화가 없다면 없다고 나오기 있다면 목록으로 나오기
checkbox는 실제로 가는 값이 value이기때문에 꼭 넣어주자.

<h1>16번 파일</h1>
<form action="17process.jsp">
    <label for="check1">스즈메의문단속</label>
    <input type="checkbox" name="movies" id="check1" value="스즈메의문단속"/> <br />
    <label for="check2">슬램덩크</label>
    <input type="checkbox" name="movies"  id="check2" value="슬램덩크"/> <br />
    <label for="check3">던전앤드래곤</label>
    <input type="checkbox" name="movies" id="check3" value="던전앤드래곤"/> <br />
    <label for="check4">리바운드</label>
    <input type="checkbox" name="movies" id="check4" value="리바운드"/> <br />
    <label for="check5">에어</label>
    <input type="checkbox" name="movies" id="check5" value="에어" /> <br />

    <input type="submit" value="전송" />
</form>

<a href="16form.jsp">16번파일로 이동</a>

<c:if test="${empty param.movies}">
    <div>
        <p>선택한 영화가 없습니다.</p>
    </div>
</c:if>

<c:if test="${not empty param.movies}">
    <div>
        <ul>
            <!-- forEach사용해서 영화목록 출력 -->
            <c:forEach items="${paramValues.movies}" var="movie"> 
                <li>${movie}</li>
            </c:forEach>
        </ul>
    </div>
</c:if>

12.18 forEach varStatus

begin end var / items var조합으로 작성해보았다.
var가 item이랑 쓰일때는 item값이 하나씩 begin end는 장가하는 값이 들어간다.
그런데 우리는 반복문을 list의 index와 쓰고싶은 경우가 있다.

items를 쓰면 var에 item이 들어가서 넣을 공간이 없다 varStatus attribute를 사용하면된다.
varStatus은 현재 var의 상태에 관한 정보가 들어있다.
여기에 들어가는 객체의 타입은 LoopTagStatus타입이다.
LoopTagStatus은 인터페이스로 여러 메소드들이 있다.
getBegin() getCount() getIndex()등이 있다.

LoopTagStatus의 getIndex()메소드를 사용하면 index를 알 수 있다.
EL에서는 property를 가져오는 것임으로 문법에 맞춰 작성해주면된다.

<% 
    pageContext.setAttribute("mylist", List.of("java", "css", "html", "spring", "jsp"));
%>
<!-- varStatus : LoopTagStatus  -->
<c:forEach items="${mylist}" var="item" varStatus="status"> 
    <p>${status.index} : ${item}</p>
</c:forEach>

12.19 varStatus - 2

현재 loop에 관한 상태가 varStatus의 객체에 저장되어 있다.
begin end조합에서는 index아 current는 begin~end의 값
count는 루프 횟수이니 1부터 시작한다.

index : list의 index
count : 루프의 횟수가 몇번째인가 1번부터
current : 현재 객체
first: 첫객체면 true 아니면 false
last : 마지막객체면 true아니면 false

<% 
    pageContext.setAttribute("mylist", List.of("java", "python", "js", "c", "c++"));
%>
<c:forEach items="${mylist}" var="item" varStatus="stat">
    <div class="card">
        <div>index: ${stat.index}</div>
        <div>count : ${stat.count}</div>
        <div>current : ${stat.current}</div>
        <div>first : ${stat.first}</div>
        <div>last : ${stat.last}</div>
    </div>
</c:forEach>

12.20 varStatus - 3 응용

java / html / react / vue 으로 출력하고 싶은데 마지막만 /이 없이 출력하고 싶다.
status를 참고할 수 있다.

<%
    pageContext.setAttribute("list", List.of("java", "html", "react", "vue"));
%>

<c:forEach items="${list}" var="item" varStatus="status">
    ${item} 
    <c:if test="${not status.last }">
        /
    </c:if>
</c:forEach>

12.21 forEach map

map이 attribute로 들을때 forEach로 값을 추출할 수 있다.
키밸류쌍을 가지고 있는 것이 Map.Entry타입이다. getKey, getValue등의 메소드를 가지고 있다.

<% 
    pageContext.setAttribute("mymap", Map.of("guard","송태섭","foward","강백호","center","채치수"));
%>

<c:forEach items="${mymap}" var="entry" varStatus="status">
    <p>${status.count} : ${entry.key} : ${entry.value}</p>
</c:forEach>

12.22 forEach javabean

javabean을 forEach로 탐색할 수 있다.

<%
    List<Bean01> list2 = new ArrayList<>();
    Bean01 b1 = new Bean01();
    b1.setName("강백호");
    b1.setAge(30);
    b1.setMarried(true);

    Bean01 b2 = new Bean01();
    b2.setName("서태웅");
    b2.setAge(40);
    b2.setMarried(false);

    Bean01 b3 = new Bean01();
    b3.setName("정대만");
    b3.setAge(50);
    b3.setMarried(true);

    list2.add(b1);
    list2.add(b2);
    list2.add(b3);

    pageContext.setAttribute("list2", list2);
%>

<c:forEach items="${list2}" var="player" varStatus="status">
    <p>${status.count} : ${player.name}, ${player.age}, ${player.married}</p>
</c:forEach>

2023.04.05 후기

el문자열 비교시 문자열 묶는거 잊지말자

head first sql받았는데 시리즈 초보자 위한 책 많음.
중요한것만 찝어서 접근하기 쉽게 만들어놓음.
굉장히 오래됫긴한데 사용할 db이 큰변화는 없다.

책의 중요한 페이지만 보고 실제 배울때는 w3school예제 활용할계획이다.
어떻게 작성 테이블 설계하는 방법 등등 jsp배우고나서 할듯하다.
배우면서 java에서 안한 jdbc챕터 배울예정이라고 한다.