12/01 55-2 [JSP] 서블릿Basic(get/post/both/multi)
[서블릿]
서블릿은 사용자의 요청( request)을 받아서
요청을 분석한 후 그 요청에 맞는 로직을 호출하고(비지니스 로직인 Model이란것을 가지고 있대)
Model로부터 그 결과값을 받아
request나 session영역에 저장
그리고 결과값을 뿌려줄 적절한 view(jsp페이지)를 선택하는 역할을 담당한다.
최종적으로 선택된 view(jsp페이지)가 요청한 사용자에게 전달(response)된다
브라우저에서 요청이 들어오면 서블릿 컨테이너가 처리 로직짜서 출력하는 jsp 페이지로 보냄
그니까 서블릿에는 내용은 없고 로직만 있으면 되는겨!! 받고 보내는 로직!
그래서 이름을 ~~Controller.java 로 짓는다.
서블릿은 최초 요청이 들어올 때 한 번만 생성(인스턴스화 )됨
서버가 꺼지면 그 때 없어짐 (서버와 함께하는 삶)
[서블릿의 라이프사이클(생명주기에 관한 메소드들임)]
init()
로딩시 최초 수행됨
단, 한.번.만. 수행된다. 서블릿 초기화 할 때 사용.
service()
요청 때 마다 호출
destroy()
톰캣(서블릿엔진)을 중지 할 때 딱 한 번 수행됨.
[mvc모델]
model1/2
차이는 요청을 jsp가 받느냐 서블릿이 받느냐
1은 작성이 간편한 대신에 유지보수 어렵
2.는 복잡한 대신에 유지보수 좋음
베이직 끝내고 모델 2 방식으로 자료실 게시판을 짤 것임 !
web.xml 에 서블릿 등록하고 매핑해야하는데
@어노테이션으로 한방에 가능함
[web.xml]
시작 문서를 설정하는 기능
servlet을 매핑할 수 있다.
.do라는 확장자를 가진 파일을 서블릿 엔진에게 처리하라는 의미
즉 파일 작성후 확장자를 .do로 저장하면 서블릿 엔진이 컴파일 한다.
[서블릿 작성 규칙 및 테스트]
1) javax.servlet 패키지 와 javax.servlet.http패키지 그리고 java.io패키지를 기본적으로 import한다.
2) 클래스명 앞에 public 을 반드시 붙인다.
3) 서블릿은 extends HttpServlet을 상속 받아야 한다.
4) ServletException,IOException 예외를 선언해 줘야 한다
5) doGet()메서드 나 doPost()메서드 메서드를 반드시 오버라이딩 해야한다.
6) 서블릿 엔진은 사용자의 요청을 받았을때 서블릿 클래스에 정의 되어 있는
doGet() 또는 doPost() 메소드를 호출한다.
파라미터는 HttpServletRequest, HttpServletResponse 두개의 클래스를 사용한다.(요청받아서 처리해야 하니까!)
-doGet(): GET방식으로 서블릿을 요청하는 경우.
웹 브라우저에서 서블릿을 호출하는 대부분의 호출 방식(GET방식)
GET 방식으로 호출된 서블릿은
서블릿 엔진이 서블릿의 doGet() 함수를 호출한다.
-doPost(): POST 방식으로 서블릿을 요청하는 경우.
반드시 form요소를 사용하여 서블릿을 호출한다.
POST 방식으로 호출된 서블릿은 서블릿 엔진이 서블릿의
doPost() 함수를 호출한다.
서블릿 대충 요런 그림
@WebServlet ("어떤 jsp파일을 처리할건지 경로를 적어줌 ")
public class 이름 extends HttpServlet{
@Override
protected void doGet/doPost (ttpServletRequest req, HttpServletResponse resp){
파라미터 받고
포워딩/리다이렉트
}
}
1.Basic
이건 jsp 가 중요한건 아니니까 서블릿코드 위주로 정리할거
jsp는 폼이랑 parm명만 잘 보자
아!! 하나 더 잘 봐야하는 거 경로!!
/Basic/~.kosmo
우리 요런 폴더 만든 적 없잖아!! 이 경로를 바로 web.xml에서 설정하는거! 오 신기
하나의 컨트롤러로 여러 요청처리하는거 신기하다 잘 봐두자
<legend class="w-auto p-3">서블릿으로 요청 보내기</legend>
<!--URL은 디렉토리 구조와 상관없다 -->
<ul class="list-unstyled">
<li><kbd>GET방식</kbd> <a href="<c:url value="/Basic/get.kosmo"/>">GET방식</a></li>
<li><kbd>POST방식</kbd>
<form class="form-inline" action="<c:url value="/Basic/post.kosmo"/>" method="POST">
<label>아이디</label>
<input type="text" name="id" class="form-control mx-2" />
<label>비밀번호</label>
<input type="password" name="pwd" class="form-control mx-2" />
<input type="submit" class="btn btn-danger mx-2" value="로그인" />
</form>
</li>
<li>
<kbd>GET/POST에 상관없이 요청받기(하나의 컨트롤러(서블릿)로 GET/POST방식 둘다 처리)</kbd><br/>
<a href="<c:url value="/Basic/both.kosmo"/>">GET방식</a>
<form class="form-inline" action="<c:url value="/Basic/both.kosmo"/>" method="POST">
<input type="submit" class="btn btn-danger mx-2" value="POST방식" />
</form>
</li>
<li>
<kbd>하나의 컨트롤러로 여러 요청 처리하기(파라미터로 구분해서)</kbd><br/>
<a href="<c:url value="/Basic/multi.kosmo?crud=create"/>">입력요청</a>
<a href="<c:url value="/Basic/multi.kosmo?crud=read"/>">조회요청</a>
<a href="<c:url value="/Basic/multi.kosmo?crud=update"/>">수정요청</a>
<a href="<c:url value="/Basic/multi.kosmo?crud=delete"/>">삭제요청</a>
</li>
<li>
<kbd>링크메뉴 클릭(GET요청)->FIRSTController->입력폼페이지로 포워드->입력폼에서 POST방식 요청(SECONDController)->SECONDController에서는 FIRSTController로 포워드(405에러)</kbd>
<a href="<c:url value="/Basic/first.kosmo"/>">링크 메뉴</a>
</li>
</ul>
</fieldset>
<fieldset class="form-group border p-3">
<legend class="w-auto p-3">리퀘스트 영역에 저장된 데이타 출력</legend>
<ul class="list-unstyled">
<li>get.kosmo요청시 : ${GET}</li>
<li>post.kosmo요청시 : ${POST}</li>
<li>both.kosmo요청시 : ${BOTH}</li>
<li>multi.kosmo요청시 : ${MULTI}</li>
</ul>
</fieldset>
요청도 참 징그럽게 많이 한다...
서블릿 작성 할 패키지 생성
호출순서 :
init()(최초요청시) -> service(요청 때마다:super.service()실행 시) doget()혹은 doPost()호출 -> destroy (서버 중지 시 )
controller.basic
1. /GetController 부터 가쟈
서블릿 생성하려면 우선 web.xml에 등록을 먼저 해야 함
<!-- 서블릿 기초 -->
<!-- 요청을 처리할 서블릿 등록 -->
<servlet>
<!-- 서블릿 명:임의로 지정 -->
<servlet-name>SERVLET-BASIC-GET</servlet-name>
<!-- 서블릿 클래스의 패키지를 포함한 경로 -->
<servlet-class>controller.basic.GetController</servlet-class>
</servlet>
<!--URL패턴과 서블릿 매핑 -->
<servlet-mapping>
<servlet-name>SERVLET-BASIC-GET</servlet-name>
<!-- 사용자 요청 URL패턴:반드시 / 로 시작하는 패턴:디렉토리 구조와 무관 -->
<url-pattern>/Basic/get.kosmo</url-pattern>
</servlet-mapping>
하나 등록하는데도 이렇게 길어요 .... 그래서 나온게 @어노테이션!
저렇게 긴 걸 그냥 @WebServlet("/Basic/get.kosmo") 이렇게 한줄로 끝내도 가능!
대신 둘 중 하나만 써야함 둘다 쓰면 에러나요
이렇게 등록한 후
서블릿 만들기
GetController
**** service 오버라이딩 하고 나서 나오는 super는 지우면 안돼!! 꼭 필요함
//1.HttpServlet상속 받아야 서블릿이 됨
public class GetController extends HttpServlet {
//호출순서 : init()(최초요청시) -> service(요청 때마다:super.service()실행 시) doget()혹은 doPost()호출 ->
//destroy (서버 중지 시 )
//2.get방식이라 이것만 필요함
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("서블릿의 doGet");
//3.리퀘스트 영역에 데이터 저장
req.setAttribute("GET","GET방식 요청 입니다.");
//4.뷰로(jsp) 포워딩
//4-1뷰 선택
RequestDispatcher dispatcher= req.getRequestDispatcher("/servlet13/ServletBasic.jsp");
//4-2뷰로 포워
dispatcher.forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("서블릿의 doPost");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.service(req, resp); // 이거 없으면 doget,post가 호출이 안된다...
System.out.println("서블릿의 service get이던 post던 상관없을 때 사용");
}
@Override
public void destroy() {
System.out.println("서블릿의 destroy()");
}
@Override
public void init() throws ServletException {
System.out.println("서블릿의 init()");
}
get방식 링크 눌렀을 때
PostController
public class PostController extends HttpServlet {
// 여긴 post요청들어오는데 만약 doget으로 받으면 405에러남
/*@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
얘 못씀!
*/
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//3.파라미터 받기
String id = req.getParameter("id");
String pwd = req.getParameter("pwd");
//4.
req.setAttribute("POST",String.format("POST방식 요청입니다. 아이디:%s, 비밀:%s",id,pwd));
//5.뷰로 포워딩
req.getRequestDispatcher("/servlet13/ServletBasic.jsp").forward(req, resp);
}
}
get/post 둘이 같이 쓰면 에러나지만 방법이 다 있다!!
BothController
//servlet 3.0부터 아래 어노테이션지원됨
//얘 쓰면 web.xml에 서블릿 등록 안해도 됨!!!
@WebServlet ("/Basic/both.kosmo")
public class BothController extends HttpServlet {
// 하나의 컨트롤러로 get post처리
//방법1. service 하나만 오버라이딩
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("BOTH",req.getMethod()+"방식 요청");
req.getRequestDispatcher("/servlet13/ServletBasic.jsp").forward(req, resp);
// super.service(req, resp); // 내가 재정의해서 이거 없어도 됨
}
==============================================================================================
//방법2. do get/post를 오버라이딩 하고 한쪽으로 몰아주기
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp); //get에서 받고 post로 보냄
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//요청처리을 로직을 여기서만 작성
req.setAttribute("BOTH",req.getMethod()+"방식 요청");
req.getRequestDispatcher("/servlet13/ServletBasic.jsp").forward(req, resp);
}
}
MultiController
하나의 컨트롤러로 여러 요청 처리하기(파라미터로 구분해서)
?=로 넘어왔으니가 get방식으로 넘어왔네
@WebServlet("/Basic/multi.kosmo")
public class MultiController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String crud = req.getParameter("crud");
String message;
switch (crud.toUpperCase()) {
case "CREATE":
message="입력처리 요청입니다."; break;
case "READ":
message="조회처리 요청입니다."; break;
case "UPDATE":
message="수정처리 요청입니다."; break;
default: message="삭제처리 요청입니다.";
}
req.setAttribute("MULTI", message);
req.getRequestDispatcher("/servlet13/ServletBasic.jsp").forward(req, resp);
}
}
순서가 섞였을 때
fist에서 get으로 받아서 뷰로 보냄, 뷰에서 post로 second에게 보냄 second는 fist로 보냄 (404에러남)
그럼 첫 번째를 service로 !
@WebServlet("/Basic/first.kosmo")
public class FirstController extends HttpServlet {
//405피하려면
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if(req.getAttribute("WHERE")==null )
req.setAttribute("WHERE","첫 번째 컨트롤러");
//입력 폼(.jsp)로 포워드
req.getRequestDispatcher("/servlet13/Form.jsp").forward(req, resp);
}
@Override 이거쓰면 404에러남
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("WHERE","첫 번째 컨트롤러");
//입력 폼(.jsp)로 포워드
req.getRequestDispatcher("/servlet13/Form.jsp").forward(req, resp);
}
}
중간에 거쳐감
form.jsp
<h1>서블릿</h1>
${WHERE}
<form method="post" action="<c:url value="/Basic/second.kosmo"/>">
<input type="submit" class="btn btn-danger mx-2" value="post요청"/>
</form>
@WebServlet("/Basic/second.kosmo")
public class SecondController extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//first에서 왔는디(get에서 받음) first로 다시 이동시키려고 하는거?
req.setAttribute("WHERE","두 번째 컨트롤러");
req.getRequestDispatcher("/Basic/first.kosmo").forward(req, resp);
}
}
주말인데.... ㅠㅠ 잠 좀 자고싶다..