jsp에서 enum & include 사용하기

murkgom·2021년 1월 7일
0

0. 기존 코드

...
<div class="a">
  <select>
    <option value="A">에이</option>
    <option value="B"></option>
    <option value="C"></option>
    <option value="D"></option>
  </select>
</div>
<div class="a">
  <select>
    <option value="ONE">하나</option>
    <option value="TWO"></option>
    <option value="THREE"></option>
  </select>
</div>
...

문제점

  1. 하드코딩 되어 있는 option의 value와 text
  2. 같은 구조의 반복

1. 하드코딩 해결하기

1.1. Java - Enum 생성

Enum Alphabet

package com.bear.tanned.enums;

@Getter
@AllArgsConstructor
public enum MyAlphabet {
    A("에이"), 
    B("비"), 
    C("씨"), 
    D("디");
    
    private String label;
};

Enum MyNumber

package com.bear.tanned.enums;

@Getter
@AllArgsConstructor
public enum MyNumber {
    ONE("하나"), 
    TWO("둘"), 
    THREE("셋");
    
    private String label;
};
  • 하드코딩보다 safety!

1.2. JSP Directive 활용

<%@ page import="com.bear.tanned.enums.*" %>
  • jsp 내에서 import한 java file 사용이 가능!

1.3. jstl - forEach 활용

...
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
...
<div class="a">
  <select>
    <c:forEach items="MyAlphabet.values()" var="alpha">
    	<option value="${alpha}">${alpha.label}</option>
    </c:forEach>
  </select>
</div>
<div class="a">
  <select>
    <c:forEach items="MyNumber.values()" var="num">
    	<option value="${num}">${num.label}</option>
    </c:forEach>
  </select>
</div>
...
  • taglib으로 jstl 사용 선언 후 c:forEach 활용

2. 같은 구조의 반복 해결하기

2.0. Plan

  1. 중복 구조 분리하기
    • 중복 구조를 별도의 Child.jsp로 추출하자
  2. include
    • Parent.jsp 내의 중복 구조 영역에 Child.jsp 를 include하자
  3. 동적 include
    • 변수를 넘겨 include시 동적인 페이지를 생성하자

= thymeleaf의 fragment 같은 기능이 필요

2.1. Child.jsp 생성하기

jsp vs jspf

  • jsp
    • 각자 compile 후, client단에서 build
    • 변수 할당이 가능
    • <jsp:include page=""> 혹은 <c:import url=""> 이용
  • jspf
    • include하는 Parent.jsp에 포함된 뒤, compile
    • <%@ include file=""> 이용

Child.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<div class="a">
  <select>
    <c:forEach items="<%= ${enumList}" var="enumObj">
    	<option value="${enumObj}">${enumObj.label}</option>
    </c:forEach>
  </select>
</div>
  • Parent.jsp에 이미 taglib 선언이 되어 있더라도 Child.jsp에서 따로 해줘야 c:forEach 사용 가능

2.2. Parent.jsp에서 include

<jsp:include> vs <c:import>

  • <jsp:include>의 <jsp:param>은 취향이 아님
<%
	List enumList = request.getParameter("enumList");
%>
...
<%= enumList %>
  • <c:import> 활용!
...
<c:import url="./Child.jsp">
	<c:param name="enumList" value="${MyAlphabet.values()}" />
</c:import>

<c:import url="./Child.jsp">
	<c:param name="enumList" value="${MyNumber.values()}" />
</c:import>
...
  • But, 제대로 되지 않는다.
  • c:param은 String Type의 variable만 전달 가능 (jsp:param도 마찬가지)

2.3. c:set으로 variable 전달하기

...
<c:set var="enumList" value="${MyAlphabet.values()}" scope="request" />
<c:import url="./Child.jsp" />

<c:set var="enumList" value="${MyNumber.values()}" scope="request" />
<c:import url="./Child.jsp" />
...
  • (중요) c:set의 scope 를 request 로 설정할 것
  • Child.jsp는 수정 불필요

3. 최종 결과물

Java - Enum

Parent.jsp

...
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page import="com.bear.tanned.enums.*" %>
...
<c:set var="enumList" value="${MyAlphabet.values()}" scope="request" />
<c:import url="./Child.jsp" />

<c:set var="enumList" value="${MyNumber.values()}" scope="request" />
<c:import url="./Child.jsp" />
...

Child.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<div class="a">
  <select>
    <c:forEach items="<%= ${enumList}" var="enumObj">
    	<option value="${enumObj}">${enumObj.label}</option>
    </c:forEach>
  </select>
</div>

1개의 댓글

comment-user-thumbnail
2022년 5월 30일

https://stackoverflow.com/a/6014342 (댓글 주목) 을 보고 다음과 같이 작성했는데 되네요. 이 방법도 알아두시면 좋을 것 같아요:

langauge 는 jsp 에 보내는 model 에 들어있는 필드라는 가정입니다. 별도로 패키지 import 는 필요 없습니다.

              <th>언어</th>
              <td>
                  <form:select path="language">
                      <form:option value="">전체</form:option>
                      <form:options items="${enumValues}" itemLabel="korean" />
                  </form:select>
              </td>

위 SO 글에도 나와있지만, enumValues 를 지정하지 않아도 만들어주는게 피쳐라고 합니다 (...).

korean 은 제가 만든 부분입니다.

public enum Language {
    KOREAN("한글"),
    ENGLISH("영어");

    private final String korean;

    Language(String korean) { this.korean = korean; }

    public String getKorean() { return this.korean; }
}
답글 달기