1. 개요
Tomcat은 7.0부터 Servlet 3.0(JSR-315)을 지원하고 있습니다. 오늘은 Java EE 6의 핵심이기도 한 Servlet 3.0에 대해서 간략히 정리해 보려고 합니다.
* Tomcat에 올릴까 하다가 그냥 Java에 올립니다.
2. 기능
2.1. Annotation을 통한 선언적 프로그래밍
기존에 web.xml을 통해 제공하던 설정을 Annotation을 통해 코드에 직접 선언할 수 있게 되었습니다. 대표적으로 다음과 같은 Annotation을 사용할 수 있습니다.
@WebServlet@WebListener@WebFilter@MultipartConfig
예를 들어 간단한 서블릿은 다음처럼 web.xml 매핑 없이 선언할 수 있습니다.
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().write("Hello Servlet 3.0");
}
}
만일 Annotation을 이용한다면 web.xml의 metadata-complete 설정에 주의해야 합니다.
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"
metadata-complete="true">
</web-app>
metadata-complete="true"는 사용해서는 안 됩니다. 기본값은 false인데, 이를 true로 하면 컨테이너가 Annotation 처리를 하지 않게 됩니다.
2.2. 동적 등록
Servlet, Filter의 등록과 매핑을 코드 레벨에서 처리할 수 있게 되었습니다. 보통 ServletContextListener나 ServletContainerInitializer 같은 초기화 시점에서 필요한 Servlet 또는 Filter를 등록합니다.
ServletContext.addServlet()ServletRegistration.Dynamic.addMapping()ServletContext.addFilter()FilterRegistration.Dynamic.addMappingForUrlPatterns()
ServletRegistration.Dynamic servlet = context.addServlet("hello", new HelloServlet());
servlet.addMapping("/hello");
2.3. 보안 확장
Servlet 3.0에서는 보안 설정도 Annotation 기반으로 일부 선언할 수 있습니다. URL 패턴별 접근 제어를 모두 코드로 대체한다기보다는, 기존 web.xml 설정과 함께 필요한 부분을 명시적으로 표현할 수 있게 된 것으로 이해하면 됩니다.
@ServletSecurity@HttpConstraint@HttpMethodConstraint
또한 환경에 따라 JSR-250 기반의 @RolesAllowed, @DenyAll, @PermitAll 같은 Annotation을 함께 사용하는 경우도 있습니다.
2.4. Web Application 설정 확장
- Annotation을 통한 Servlet, Filter 정의
web-fragment.xml을 통한 deployment descriptor의 모듈화 기능
web-fragment.xml은 라이브러리 JAR 안에 웹 관련 설정을 함께 포함할 수 있게 해 줍니다. 여러 프레임워크나 공통 모듈이 각자 필요한 Listener, Filter, Servlet 설정을 조각 단위로 제공할 수 있다는 점이 장점입니다.
2.5. Asynchronous 지원
말 그대로 비동기 모드 지원입니다. 요청 처리 스레드를 오래 붙잡아 두지 않고, 시간이 오래 걸리는 작업을 별도로 진행한 뒤 응답을 완료할 수 있습니다.
비동기 처리를 사용하려면 Servlet 또는 Filter에서 asyncSupported=true를 선언하고, 요청 객체에서 startAsync()를 호출해 비동기 컨텍스트를 얻는 방식으로 처리합니다.
@WebServlet(urlPatterns = "/async", asyncSupported = true)
public class AsyncServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
AsyncContext asyncContext = request.startAsync();
asyncContext.start(new Runnable() {
@Override
public void run() {
try {
asyncContext.getResponse().getWriter().write("async response");
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
asyncContext.complete();
}
}
});
}
}
비동기 서블릿에 대한 보다 자세한 내용은 여기에서 확인할 수 있습니다.