서블릿은 JSP가 나오기전 자바로 웹 애플리케이션을 개발할 수 있도록 만든 기술
서블릿은 서버 단에서 클라이언트의 요청을 받아 처리한 후 응답하는 역할
서블릿의 특징
서블릿을 만들었다고 해서 스스로 작동하는것은 아님
서블릿을 관리하는 컨테이너가 필요하고 그걸 서블릿 컨테이너 라고함
우리는 서블릿 컨테이너로 톰캣을 사용
예시
package com.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet { // Httpservlet 상속
private static final long serialVersionUID = 1L;
@Override //doGet() 오버라이딩
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//메소드 실행부
req.setAttribute("message","HELLO SERVLET");
req.getRequestDispatcher("/12/HelloServlet.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req,resp);
}
}
서블릿 작성은 클라이언트의 요청을 전달할 '요청명'을 결정하는 일부터 시작한다
JSP에서는 클라이언트의 요청을 JSP가 직접 받아 처리하지만,
서블릿은 요청명을 기준으로 이를 처리할 서블릿을 선택하게 된다
요청명과 서블릿을 연결해주는 작업을 매핑(mapping) 이라고 하며, 두가지 방식이있다
web.xml 방식으로 매핑하는법
<servlet> <!-- 서블릿 등록 -->
<servlet-name>서블릿명</servlet-name>
<servlet-class>패키지를 포함한 서블릿 클래스명</servlet-class>
</servlet>
<servlet-mapping> <!--서블릿과 요청명(요청 URL) 매핑, 서블렛과 매핑은 항상 세트-->
<servlet-name>서블릿명</servlet-name>
<url-pattern>클라이언트 요청 URL</url-pattern>
</servlet-mapping>
예제
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta charset="UTF-8">
<title>Hello Servlet</title>
</head>
<body>
<h2>web.xml 에서 매핑 후 JSP 에서 출력하기</h2>
<p>
<strong><%=request.getAttribute("message")%></strong>
<br/>
<a href="./HelloServlet.do">바로가기</a>
</p>
</body>
</html>
<%=request.getAttribute("message")%>
request 영역에 저장된 message 속성을 출력한다, 이속성의 값은 뒤에 작성할 서블릿에서 저장한다
그다음 web.xml에서 요청명으로 서블릿을 매핑해보겠다
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/12/HelloServlet.do</url-pattern>
</servlet-mapping>
HelloServlet = 서블릿을 매핑하기 위한 서블릿 명
com.servlet.HelloServlet = 해당요청을 처리할 서블릿 (패키지까지 포함하여 명시)
/12/HelloServlet.do = 컨텍스트 루트를 제외한 요청명 (보통 .do로 끝나는 형태를 사용하지만 다른형태도 가능)
즉 클라이언트가 /12/HelloServlet.do 로 접속하면 매핑된 서블릿 명으로
등록된 클래스를 찾는 구조
이번엔 실제 요청을 처리할 서블릿 클래스를 작성해보겠다
package com.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("message","HELLO SERVLET");
req.getRequestDispatcher("/12/HelloServlet.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req,resp);
}
}
doGet 메소드 오버라이딩 그리고
request 영역에 message 라는 속성으로 데이터를 저장하고 HelloServlet.jsp로 포워드한다
req는 doGet()메서드의 매개변수로 전달받은 request 내장객체이다 request 영역에 저장된 데이터는 포워드된 페이지까지 공유되므로 해당속성을 출력할수 있다
코드작성을 마쳤으니 실행시켜보자
request 영역에 저장된 데이터가 null이라고 출력된다 단순히 JSP만 실행했으므로
request 영역에는 아직 아무런 데이터도 저장되지 않았기 때문
여기서 바로가기 링크를 누르면
주소표시줄을 보면 web.xml에서 매핑한 요청명으로 변경된 것을 알수있고
HELLO SERVLET 이라는 문자열도 출력되었다
이와같이 서블릿은 요청명을 통해 서블릿이 직접 요청을 처리한 후
데이터를 영역에 저장하고 결과를 출력할 JSP를 선택하여 영역을 통해 공유된 데이터를 출력하는 형식으로 클라이언트에게 응답한다.
대략적인 흐름을보자
요청받은 url로 web.xml에서 매핑된 서블릿을 찾는다
매핑된 서블릿을 찾은후 서블릿에 설정되어있는 클래스로 넘어와 메소드를 호출시킨다
예제는 get방식이기때문에 doGet()을 호출하며 doGet 메소드를 통해
message 에 HELLO SERVLET 이라는 값을 설정해준후
다시 HelloServlet.jsp로 포워드 해준다
이것이 web.xml을 이용한 매핑 방식이다
요청명으로 서블릿을 선택하는 두번째 방법으로 @WebServlet 애너테이션을 사용해보자
요청명을 통한 바로가기 링크가 있는 JSP를 먼저 작성하고
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<meta charset="UTF-8">
<title>Annotation Mapping</title>
</head>
<body>
<h2>Annotation 으로 매핑하기</h2>
<p>
<strong>${msg}</strong>
<br/>
<a href="<%=request.getContextPath()%>/12/AnnoMapping.do">바로가기</a>
</p>
</body>
</html>
실행 시켰을때
참고로 web.xml을 이용한 매핑방식 예제에서는 request.getAttribute("message")를 사용했으므로 null 이 출력되었지만
애너테이션을 이용한 예제에는 EL로 변수를 출력했기때문에 null이아닌 빈공간이 출력되는것
*EL의 특징 참고.
다음은 서블릿 작성
package com.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/12/AnnoMapping.do")
public class AnnoMapping extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("msg","@WebServlet 으로 매핑함!");
req.getRequestDispatcher("/12/AnnoMapping.jsp").forward(req,resp);
}
}
그다음 실행
간단하게 설명하면 위의 서블릿 클래스에서
@WebServlet("/12/AnnoMapping.do") 의 의미가
"/12/AnnoMapping.do" URl을 요청받았을때 그 요청을 이 클래스에 매핑한다는 뜻이다
즉 AnnoMapping.jsp 에서 바로가기 (/12/AnnoMapping.do) 를 눌렀을때
@WebServlet("/12/AnnoMapping.do")로 요청이들어가
@WebServlet("/12/AnnoMapping.do")의 클래스에 매핑이되며 클래스에있는
메소드를 호출하게된다
그이후론 web.xml 매핑방식과 동일하게 msg변수에 값을 설정하고 forward로 돌아와
@WebServlet으로 매핑함! 이라는 값을 출력해줄수있게 된것이다.