서블릿(Servlet)
Servlet은 JSP표준이 나오기 전에 만들어진 표준 기술
자바에서 웹 어플리케이션 개발을 위해 만들어짐
JSP에 비해 Servlet개발 과정은 비교적 복잡
MVC패턴을 적용하여 개발하는 경우 Servlet 이해 필수
서블릿을 이용한 웹 어플리케이션 개발 과정
1. 서블릿 규약에 따라 자바코드 작성 및 컴파일
2. 클래스파일을 WAS의 /WEB-INF/classes 디렉터리에 위치
3. web.xml파일에 서블릿 클래스 설정(필요 시 설정)
4. WAS(Tomcat 등)를 재 실행(서블릿 리로드기능이 있다면 생략가능)
5. 웹 브라우저를 통해 해당 서블릿을 요청하여 결과응답 페이지 확인
서블릿 클래스를 상속받아 요청을 처리하는 클래스를 작성
src/servletex/NowServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 |
package servletex;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class NowServlet extends HttpServlet{
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException{
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>현재시간 서블릿</title></head>");
out.println("<body>");
out.print("현재 시간은 ");
out.print(new Date());
out.println("입니다.");
out.println("</body></html>");
}
}
|
cs |
위 코드를 보면 HttpServlet클래스를 상속받은 것을 확인할 수 있다.
그리고 상속 받은 HttpServlet의 메서드 중 doGet()메서드를 오버라이딩 한 것을 볼 수 있는데
이 메서드는 서블릿을 실행하는 서버(Tomcat)로 클라이언트의 get요청을 받으면 해당 메서드가 호출되도록 동작된다.
만약 POST메서드를 처리하려는 경우 상속받은 서블릿 클래스에 있는 doPost()를 오버라이딩한다. (하나의 서블릿 클래스에 둘 모두 정의 가능)
doGet()/doPost() 메서드가 전달받는 HttpServletRequest/HttpServletRespons
- JSP에서 request/respons기본 객체와 동일
- request를 이용하여 요청 정보를 읽거나 response를 이용하여 응답을 전송
- response응답 전송 시 응답 컨텐츠 타입 지정(브라우저에서 응답을 해석할 방식)
- 응답결과를 전송(PrintWriter로 응답 스트림에 지정된 컨텐츠 타입의 데이터를 출력)
- 작성된 java코드를 컴파일하고 WAS의 /WEB-INF/classes/하위에 위치
(이클립스의 Dynamic Web Application프로젝트를 이용하는 경우 생략.
단 war배포 시에는 경로 확인필요)
- WAS(이 실습에서는 Tomcat)에서 Servlet을 처리하려면 servlet-api.jar 필요
- Tomcat에는 lib폴더에 포함되어 있으나 만약 없는 환경의 경우 포함 해야 함.
Servlet Mapping?
Servlet클래스를 생성했다면 /WEB-INF/web.xml 파일에 Servlet class 등록해야 함
등록된 정보를 이용해서 요청에 알맞는 서블릿 객체를 찾음
서블릿으로 사용할 클래스 등록 및 등록된 서블릿과 요청 URL간의 매핑
하나의 서블릿에 여러 경로 지정가능
웹 어플리케이션 경로는 제외하여 지정
매핑 설정 실습 예제
WebContent/WEB-INF/web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 |
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>ServletTest</display-name>
<!-- 웹 서블릿 등록 -->
<servlet>
<servlet-name>now</servlet-name>
<servlet-class>servletex.NowServlet</servlet-class>
</servlet>
<!-- 클라이언트의 요청 URL와 서블릿 객체를 연결(매핑) -->
<servlet-mapping>
<servlet-name>now</servlet-name>
<url-pattern>/now</url-pattern>
</servlet-mapping>
</web-app> |
cs |
이제 Tomcat(WAS) 서비스를 시작한다.
서비스가 시작되면 브라우저에서 web.xml에 매핑된 url 요청한 결과확인
(/now에 대한 get요청에 매핑된 서블릿 클래스의 doGet()메서드 처리 결과)
위에서 동작되는 개념을 꼭 이해하도록 한다. 그 후 다음의 예제들을 진행한다.
@WebServlet 어노테이션?
Servlet 2.5 버전까지는 반드시 web.xml에 서블릿을 등록해야만 했다.
Servlet 3.0 버전 부터는 @WebServlet어노테이션으로 서블릿 등록이 가능하다.
서블릿 클래스에 어노테이션으로 경로 매핑 예제
어노테이션 테스트용 클래스 작성
src/servletex/HelloServlet.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 |
package servletex;
import java.io.IOException;
import java.io.PrintWriter;
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(urlPatterns = "/hello")
public class HelloServlet extends HttpServlet{
@Override
protected void doGet(
HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
String name = request.getParameter("name");
out.println("<html>");
out.println("<head><title>인사서블릿</title></head>");
out.println("<body>");
out.print("안녕하세요, " + name + "님 :)");
out.println("</body></html>");
}
}
|
cs |
여러 경로를 지정하는 경우 urlPetterns에 경로 배열을 등록해 줄 수 있다.
Tomcat 재실행 후 다음과 같이 name과 함께 요청하여 결과 확인
어노테이션 적용 시 고려사항
서블릿을 적용할 때 xml설정 파일에 등록하여 적용할 지 어노테이션을 사용하여 등록할 지 고민된다면 다음을 생각해보도록 하자.
- 서블릿이 범용적으로 사용 되는지 여부 중요(자주 변경되지 않는다면 어노테이션으로)
- MVC프레임워크는 어떤 URL경로를 서블릿이 처리할 지 미리 알 수 없음
- 즉 요청 URL이 변경되면 소스코드의 urlPatterns속성을 일일이 변경해야 함
- web.xml에 지정했다면 설정파일 하나로 관리가 가능
- 서블릿의 용도에 따라 자주 URL이 변경된다면 web.xml에 설정을 권장
- 둘 다 설정하는 경우 각각의 객체를 생성하여 url에 매핑 됨
Servlet 초기화 및 로딩
서블릿이 작동되기 전 초기화 작업이 필요한 경우
web.xml <init-param>, <param-name>, <param-value>로 초기화 파라미터 지정
다음 실습을 통해 DB를 연동하도록 초기화 파라미터를 지정하는 예제 확인
드라이버 검색 서블릿 작성(Loader.java)
src/servletex/Loader.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 |
package servletex;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
public class Loader extends HttpServlet{
@Override
public void init() throws ServletException{
try{
String driver = getInitParameter("jdbcdriver");
Class.forName(driver);
System.out.println("DriverLoading Success!");
}catch(Exception e){
System.out.println("DriverLoading Failed!");
throw new ServletException(e);
}
}
} |
cs |
web.xml파일에 서블릿 등록 및 초기화 파라미터 설정
WebContent/WEB-INF/web.xml 파일에 추가
1
2
3
4
5
6
7
8
9
10 |
...<!-- 기존 코드 -->
<servlet>
<servlet-name>JDBCDriverLoader</servlet-name>
<servlet-class>servletex.Loader</servlet-class>
<init-param>
<param-name>jdbcdriver</param-name>
<param-value>oracle.jdbc.driver.OracleDriver</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> |
cs |
위 설정은 web.xml에 드라이버 라이브러리 경로를 초기화 파라미터로 등록(Loader에서 사용)
<load-on-startup>을 통해 서버 시작 시 드라이버 검색 완료되도록 한다.(우선순위 설정 태그)
Loader클래스가 서버실행 시 드라이버를 로드하도록 설정했으므로 Connection만 생성하여 오라클 DB버전을 응답하는 서블릿 작성하여 테스트를 해보도록 한다.
그리고 이 서블릿에서 Connection을 만들 때 사용할 DB접속 경로 url, 계정, 비밀번호를 초기화 파라미터로 설정하여 테스트를 진행한다.
등록할 InitParamEx서블릿 클래스 작성
src/servletex/InitParamEx.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 |
package servletex;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class InitParamEx extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
ServletConfig config = this.getServletConfig();
String url = config.getInitParameter("url");
String account = config.getInitParameter("account");
String password = config.getInitParameter("password");
try{
conn = DriverManager.getConnection(
url, account, password);
System.out.println("Create new Connection!");
String query = "select * from v$version";
stmt = conn.createStatement();
rs = stmt.executeQuery(query);
PrintWriter out = response.getWriter();
while(rs.next()){
out.println(rs.getString(1));
}
}catch(SQLException e){
e.printStackTrace();
} finally{
try{
if(rs != null){ rs.close();}
if(stmt != null){ stmt.close(); }
if(conn != null){ conn.close(); }
}catch(SQLException e){
e.printStackTrace();
}
}
}
} |
cs |
위 서블릿 클래스를 등록하기 위해 다음 설정 작성
WebContent/WEB-INF/web.xml 서블릿 등록 추가(초기화 파라미터 지정)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 |
<!-- ...기존코드 -->
<servlet>
<servlet-name>InitParamEx</servlet-name>
<servlet-class>servletex.InitParamEx</servlet-class>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:oracle:thin:@localhost:1521:xe</param-value>
</init-param>
<init-param>
<param-name>account</param-name>
<param-value>scott</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>tiger</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>InitParamEx</servlet-name>
<url-pattern>/init</url-pattern>
</servlet-mapping> |
cs |
위에서 어떤 JSP/Servlet 에서도 드라이버 로드작업 없이 Connection만 생성이 가능하다.
설정파일이 변경되었으므로 서버를 재시작한다.
요청 확인
위에서 설정한 내용을 어노테이션을 사용하여 적용해보자.
먼저 @WebServlet어노테이션 설정을 위해 InitParamEx에 관련된 web.xml설정을 모두 지운다.
다음 @WebServlet어노테이션 설정하기
src/servletex/InitParamEx.java 클래스에 @WebServlet설정 추가(나머지 코드는 변경 없음)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 |
package servletex;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//서블릿 등록 및 초기화 파라미터 설적 적용
@WebServlet(
urlPatterns="/init",
initParams = {
@WebInitParam(name="url", value="jdbc:oracle:thin:@localhost:1521:xe"),
@WebInitParam(name="account", value="scott"),
@WebInitParam(name="password", value="tiger")
}
)
//-- 나머지 코드는 변경 없음
public class InitParamEx extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
ServletConfig config = this.getServletConfig();
String url = config.getInitParameter("url");
String account = config.getInitParameter("account");
String password = config.getInitParameter("password");
try{
conn = DriverManager.getConnection(
url, account, password);
System.out.println("Create new Connection!");
String query = "select * from v$version";
stmt = conn.createStatement();
rs = stmt.executeQuery(query);
PrintWriter out = response.getWriter();
while(rs.next()){
out.println(rs.getString(1));
}
}catch(SQLException e){
e.printStackTrace();
} finally{
try{
if(rs != null){ rs.close();}
if(stmt != null){ stmt.close(); }
if(conn != null){ conn.close(); }
}catch(SQLException e){
e.printStackTrace();
}
}
}
} |
cs |
서버 재시작 후 요청해보면 동일한 결과를 보여준다.
주의!
- web.xml에 설정하면 서블릿 재컴파일이 필요없다.
- 어노테이션을 사용하면 설정이 변경되면 서블릿도 재컴파일이 필요하다.
추가실습>
<context-param>서블릿 전체에서 사용할 수 있는 값 지정
위 실습에서 url정보만 <context-param>으로 지정하여 테스트를 진행해본다.
1. web.xml파일에서 InitParamEx 초기화 파라미터 설정에서 url값만 삭제
2. <context-param>으로 url에 대한 값 설정(<web-app> 하위에 작성)
|
<context-param>
<param-name>url</param-name>
<param-value>jdbc:oracle:thin:@localhost:1521:xe</param-value>
</context-param> |
cs |
3. InitParamEx클래스에서 context-param값을 이용하여 url값을 얻어오도록 수정
41
41 |
//String url = config.getInitParameter("url"); //초기화 파라미터에서 얻음
String url = this.getServletContext().getInitParameter("url"); //수정 |
cs |
서버 재 시작 후 브라우저에서 /init요청의 결과는 동일하다.
URL Pattern 매핑 규칙
클라이언트가 요청하는 경로에 대한 매핑 규칙
<servlet-mapping>태그는 <url-pattern>태그로 서블릿과 URL을 매핑
서블릿 규약
‘/’로 시작하고 ‘/*’로 끝나는 url-pattern은 경로 매핑을 위해 사용된다.
‘*’로 시작하는 url-pattern은 확장자에 대한 매핑을 할 때 사용된다.
오직 ‘/’만 포함하는 경우 어플리케이션의 기본 서블릿으로 매핑한다.
이 규칙 외의 나머지 다른 문자열은 정확한 매핑을 위해 사용된다.
매핑 예
서블릿의 전반적인 동작을 이해하도록 한다.
'교육자료 > JSP' 카테고리의 다른 글
(교육자료)MVC를 적용하여 게시판 구현 실습 (0) | 2018.09.06 |
---|---|
MVC 이해하기 (0) | 2018.09.06 |
JSTL(Java Standard Tag Library) 사용하기 (0) | 2018.09.06 |
EL(Expression Language) 사용하기 (0) | 2018.09.06 |
(교육자료)파일 업로드 실습 (0) | 2018.09.06 |