2008 Sep 06

- by
Changwoo Park

Enum Jsp

Enum을 JSP 페이지에 노출 시키기

개요

scriptlet은 독이다. scriptlet을 잘쓰고 있는 지인에게 ‘scriptlet은 독이이야’라고 말했다가 미움받았다. 어쨌든 scriptlet을 안쓰고 jsp짜려니까 좀 골때려지는 부분들도 있다. 먼가 방법이 있을까 찾아보니 Spring Interceptor를 이용해서 Enum을 request 스콥에 노출시켜주는 글을 찾았다.

request 스콥에 노출시키는 방법은 다음과 같은 방법이 있을 수 있다.

  • ServletFilter
  • Spring Interceptor
  • Controller

하지만 Enum을 요청마다 매번 request에 넣어주는게 좀 후져 보였다. 저장소를 application 스콥으로 잡고 WAS가 기동할 때 넣어줄 수 있도록 ContextListener로 구현하기로 했다.

예제

다음과 같은 enum 클래스가 있다고 하면:

package kr.pismute

public enum Week {
  MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

jsp에서 다음과 같이 사용할 수 있다. 사실 applicationSope이란 내장객체라는게 참 촌스럽다. 그냥 application으로 하지 못할 이유라도 있었는지…

${applicationScope.week.MONDAY}

Week라는 클래스 이름은 자바 네이밍 컨벤션에 따라 week으로 바꿔서 넣는다. GoldenWeek였다면 goldenWeek로 바뀐다.

이제 web.xml에 이 ContextListner를 넣는다:

<context-param>
    <param-name>enumServletContextConfig</param-name>
    <param-value>kr.pismute.Week</param-value>
</context-param>

<listener>
    <listener-class>kr.pismute.EnumContextListener</listener-class>
</listener>

Enum에 빈을 추가해서 사용할 수도 있다. Week에 다음과 같이 추가하고:

private Integer day;

  public Integer getDay(){
    return day;
  }

jsp에서 다음과 같이 day 프로퍼티를 사용할 수 있다.

${applicationScope.week.MONDAY.day}

Code

pacakge kr.pismute

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * JSP에서 ENUM 클래스에 접근할 수 있도록 ServletContext에 넣어줍니다.
 *
 * @author pismute
 *
 */
public class EnumContextListener implements ServletContextListener {
    public void contextDestroyed(ServletContextEvent sce) {
    }

    public void contextInitialized(ServletContextEvent sce) {
        String param = sce.getServletContext().getInitParameter("enumServletContextConfig");
        String[] params = param.split(",");

        for(String className : params) {
            className = className.trim();
            this.loadEnum(className, sce.getServletContext());
        }
    }

    /**
     * Enum 인스턴스를 찾아서 Map<name, Enum<?>> 맵으로 변환하고
     * ServletContext에 넣습니다.
     *
     * @param className
     */
    @SuppressWarnings("unchecked")
    private void loadEnum(String className, ServletContext context) {
        Map<String, Enum<?>> ret = null;

        try {
            Class<Enum> clazz = (Class<Enum>)Class.forName(className);
            Enum[] enums = clazz.getEnumConstants();

            ret = new HashMap<String, Enum<?>>(enums.length);
            for(Enum e : enums) {
                ret.put(e.name(), e);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        ret = Collections.unmodifiableMap(ret);
        context.setAttribute(this.getAlias(className), ret);
    }

    /**
     * 클래스 첫 문자를 소문자로 바꿔서 alias를 만듭니다.
     *
     * @param className
     * @return
     */
    private String getAlias(String className) {
        String[] token = className.split("\\.");
        String alias = token[token.length - 1].trim();
        String initial = alias.substring(0, 1);
        String suffix = alias.substring(1);

        initial = initial.toLowerCase();
        alias = initial + suffix;

        return alias;
    }
}