1. 서블릿 (Servlet)
● 자바 엔터프라이즈 에디션은 웹 애플리케이션 개발용 스팩과 API 제공.
● 요청 당 쓰레드 (만들거나, 풀에서 가져다가 ) 사용 (프로세스가 떠서 쓰레드로 처리함)
● 그 중에 가장 중요한 클래스중 하나가 HttpServlet.
2. 서블릿 등장 이전에 사용하던 기술인 CGI (Common Gateway Interface)
● 요청 당 프로세스를 만들어 사용
3. 서블릿의 장점 (CGI에 비해)
● 빠르다.
● 플랫폼 독립적
● 보안
● 이식성
4. 서블릿 엔진 또는 서블릿 컨테이너 (톰캣, 제티, 언더토, ...)
● 세션 관리
● 네트워크 서비스
● MIME 기반 메시지 인코딩 디코딩
● 서블릿 생명주기 관리
5. 서블릿 생명주기
● 서블릿 컨테이너가 서블릿 인스턴스의 init() 메소드를 호출하여 초기화 한다.
○ 최초 요청을 받았을 때 한번 초기화 하고 나면 그 다음 요청부터는 이 과정을 생략한다.
● 서블릿이 초기화 된 다음부터 클라이언트의 요청을 처리할 수 있다.
각 요청은 별도의 쓰레드로 처리하고 이때 서블릿 인스턴스의 service() 메소드를 호출한다.
○ 이 안에서 HTTP 요청을 받고 클라이언트로 보낼 HTTP 응답을 만든다.
○ service()는 보통 HTTP Method에 따라 doGet(), doPost() 등으로 처리를 위임한다.
○ 따라서 보통 doGet() 또는 doPost()를 구현한다.
● 서블릿 컨테이너 판단에 따라 해당 서블릿을 메모리에서 내려야 할 시점에 destroy()를 호출한다.
6. 서블릿 구축
- 메이블 프로젝트 생성 (archetype-webapp)
- pom.xml 추가 (서블릿 API)
- 서블릿을 테스트할 톰캣 구성
-Duser.language=en -Duser.region=us (톰캣 로그 한글 깨짐 방지)
- Build exploded artifact 설정 (war를 외부에서 말아서 실행하겠다.)
- webapp/WEB-INF/web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
- src/main/java/servlet/HelloServlet (java 디렉토리는 java 디렉토리 지정해줘야 함)
package servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("init");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet");
resp.getWriter().println("<html>");
resp.getWriter().println("<head>");
resp.getWriter().println("<body>");
resp.getWriter().println("<h1>Hello</h1>");
resp.getWriter().println("</body>");
resp.getWriter().println("</head>");
resp.getWriter().println("</html>");
}
@Override
public void destroy() {
super.destroy();
}
}
- hello 요청화면
- Servlet 동작 로그(Hello 요청시 Init으로 프로세스 생성, doGet 호출, 이후 요청은 쓰레드로 응답, 서버 종료시 Destroy 발생)
7. Listener 등록 (Listenr : 서블릿 초기화, 종료시 작업을 추가하여 수행할 수 있음)
- web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<listener>
<listener-class>servlet.MyListener</listener-class>
</listener>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
- MyListener.java (서블릿 컨텍스트 초기화 및 종료시 상황에 맞는 메서드 실행)
package servlet;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("Context Initialized");
sce.getServletContext().setAttribute("name", "h232ch");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("Context Destroyed");
}
}
8. Servlet Filter (특정 서블릿에 필터를 적용하여 기능 추가 및 실행)
- web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<filter>
<filter-name>myFilter</filter-name>
<filter-class>servlet.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<servlet-name>hello</servlet-name>
</filter-mapping>
<listener>
<listener-class>servlet.MyListener</listener-class>
</listener>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
- myFilter.java
package servlet;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter Init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("Filter");
filterChain.doFilter(servletRequest,servletResponse); // 요청 응답을 필터 체인으로 연결을 해줘야 함 (마지막 필터는 서블릿에 연결됨)
}
@Override
public void destroy() {
System.out.println("Filter Destroy");
}
}
- Servlet Filter 적용 화면
9. 스프링 IoC 적용
- web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>servlet.AppConfig</param-value>
</context-param>
<!-- Spring IoC 컨테이너를 리스너가 적용하는데 적용시 Spring IoC 컨테이너는 Context-param을 참조하여 생성된다. -->
<!-- servlet.AppConfig 파일의 설정을 참조하여 생성 -->
<filter>
<filter-name>myFilter</filter-name>
<filter-class>servlet.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<servlet-name>hello</servlet-name>
</filter-mapping>
<!-- <listener>-->
<!-- <listener-class>servlet.MyListener</listener-class>-->
<!-- </listener>-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring IoC 컨테이너를 서블릿 애플리케이션의 생명주기에 맞추어 바인딩 해주는 코드 -->
<!-- 서블릿 초기화시 Spring IoC 컨테이너를 연동해주고 종료시 연동을 종료 시켜줌 -->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
- AppConfig.java (ComponentScan -> @Service, @Component.. 등 어노테이션 이붙은 클래스를 빈으로 등록)
package servlet;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class AppConfig {
}
- HelloService.java
package servlet;
import org.springframework.stereotype.Service;
@Service
public class HelloService {
public String getName(){
return "h232ch";
}
}
- HelloServlet.java
package servlet;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("init");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet");
ApplicationContext context = (ApplicationContext) getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
// 서블릿 컨텍스트에서 getAttribute를 이용하여 WebApplicationContext를 가져온뒤 context에 담는다.
HelloService helloService = context.getBean(HelloService.class);
// context에서 getBean을 이용하여 HelloService를 불러와서 helloService에 지정해준다.
resp.getWriter().println("<html>");
resp.getWriter().println("<head>");
resp.getWriter().println("<body>");
resp.getWriter().println("<h1>Hello"+ helloService.getName() +"</h1>");
// context를 이용하여 가져온 빈의 메서드를 이용하여 이름을 호출한다.
// 스프링이 제공해주는 IoC 컨테이너에서 가져온 빈이라는 게 중요함
resp.getWriter().println("</body>");
resp.getWriter().println("</head>");
resp.getWriter().println("</html>");
}
@Override
public void destroy() {
System.out.println("destroy");
}
}
'4. Backend Development > 1. Spring Framework' 카테고리의 다른 글
7. Spring boot (0) | 2020.09.24 |
---|---|
6. DispatcherServlet (0) | 2020.09.01 |
4. MacOS Security Management System (0) | 2020.07.21 |
3. Spring Framework 기반 웹 프로젝트 (0) | 2020.06.09 |
2. Spring IoC Container (0) | 2020.04.30 |
댓글