이제 서블릿 스펙에 맞게 개발을 해줘야겠다~
톰캣의 라이브러리를 열어보면 서블릿을 사용하기위한 api가 있다
따라서 톰캣을 프로젝트에서 구동시켜주거나(아파치톰캣8.5 폴더 잡아서), 내 프로젝트의 WEB-INF폴더의 lib에 저 jar파일을 넣어주면 사용이 가능해진다.
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class T01_ServletLifeCycle extends HttpServlet{
@Override
public void init() throws ServletException {
// 초기화 코드 작성...
System.out.println("init() 호출됨....");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 실제적인 작업이 실행되는 지점....(자바의 메인메서드 역할)
System.out.println("service() 호출됨...");
super.service(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 메소드 방식이 get인경우 호출됨...
System.out.println("doGet() 호출됨...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 메서드 방식이 post인 경우 호출됨
System.out.println("dpPost() 호출됨...");
}
@Override
public void destroy() {
// 객체 소멸시 (컨테이너로부터 서블릿객체 제거시) 필요한 코드 작성...
System.out.println("destroy() 호출됨...");
}
}
여러 WAS들은 lib에 넣어주면 알아서 인식한다!
또한 프로젝트를 위한 설정정보를 넣어줄수 있다. WEB-INF폴더에 web.xml을 만들어준 후 거기에 넣어야만 한다.
셀프로 만들어도되고// 이클립스의 경우엔
이렇게 하면 생긴다
<servlet>
<servlet-name>T01_SLC</servlet-name>
<servlet-class>kr.or.ddit.basic.T01_ServletLifeCycle</servlet-class>
</servlet>
/T01_SLC 라는 url 요청이 사용자에게 오면 T01_SLC를 실행할거야
<servlet-mapping>
<servlet-name>T01_SLC</servlet-name>
<url-pattern>/T01_SLC</url-pattern>
</servlet-mapping>
톰캣 더블클릭으로 들어가서 모듈을 보면 다음과 같이 설정되어있음
따라서 웹브라우저로 http://localhost/ServletTest/T01_SLC 라는 url로 접속하게되면
톰캣서버 종료시 (주의 : 콘솔창 종료 누르지말것)
destroy()는 자원반납같은 내용을 넣어주기 좋은 메소드이다!
<< 톰캣이 만들어주는 객체, 요청처리 완료후 사라짐
💡 **서블릿 동작 방식** 1. 사용자(클라이언트)가 URL을 클릭하면 HTTP Request를 Servlet Container로 전송(요청)한다. 2. 컨테이너는 web.xml에 정의된 url패턴을 확인하여 어느 서블릿을 통해 처리해야 할지를 검색한다(로딩이 안된경우에는 로딩함. 로딩시 init()메소드 호출됨) 3. 서블릿 컨테이너는 요청을 처리할 개별 스레드 객체를 생성하여 해당 서블릿 객체의 service()를 호출한다. (톰캣이 HttpServletRequest 및 HttpServletResponse 객체를 생성하여 파라미터로 넘겨준다) 4. service() 메소드는 메소드타입을 체크하여 적절한 메소드를 호출한다. (doGet, doPost, doPut, doDelete 등) 5. 요청처리 완료되면, HttpServletRequest 및 HttpServletResponse 객체는 소멸된다. 6. 컨테이너로 부터 서블릿이 제거되는 경우에 destroy()가 호출된다.import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class T02_ServletTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Request 객체의 메서드 확인하기
System.out.println("getCharacterEncoding() : "+req.getCharacterEncoding());
System.out.println("getContentLength() : "+req.getContentLength());
System.out.println("getQueryString() : "+req.getQueryString());
System.out.println("getProtocol() : "+req.getProtocol());
System.out.println("getMethod() : "+req.getMethod());
System.out.println("getRequestURI() : "+req.getRequestURI());
System.out.println("getRequestedSessionId() : "+req.getRequestedSessionId());
System.out.println("getRequestDispatcher() : "+req.getRequestDispatcher("/"));
System.out.println("getHeaderNames() : "+req.getHeaderNames());
System.out.println("getRemoteAddr() : "+req.getRemoteAddr());
System.out.println("getRemotePort() : "+req.getRemotePort());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
<servlet>
<servlet-name>T02_ST</servlet-name>
<servlet-class>kr.or.ddit.basic.T02_ServletTest</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>T02_ST</servlet-name>
<url-pattern>/T02_ST</url-pattern>
</servlet-mapping>
url : http://localhost/ServletTest/T02_ST?name=apple&age=33을 넣는다면 (쿼리스트링)
get 특징 : 바디가 필요없다 url쓰고 엔터치는게 겟! 링크(a태그)도 get!
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class T03_ServletParameterTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 요청객체로부터 파라미터 데이터를 가져오는 방법
// -getParameter() : 파라미터값이 한개인 경우에 가져올때 사용함
// -getParameterValues() : 파라미터값이 여러개인 경우에 가져올때 사용함. ex) checkBox
// -getParameterNames() : request에 존재하는 모든 파라미터 정보를 가져올때 사용함
// Post방식으로 넘어오는 Body데이터를 인코딩 처리함. get방식은 톰캣의 URIEncoding 설정을 이용하여 처리함
// 반드시 request에서 값을 가져오기 전에 먼저 설정해야 적용됨
req.setCharacterEncoding("UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String gender = req.getParameter("gender");
String hobby = req.getParameter("hobby");
String rlgn = req.getParameter("rlgn");
String[] food = req.getParameterValues("food");
////
// 응답관련. response객체 이용해준다 body 정보를... 설정
resp.setContentType("text/html");
resp.setCharacterEncoding("UTF-8");
PrintWriter pw = resp.getWriter();
pw.print("<html>");
pw.print("<body>");
pw.print("<p>username : "+username+"</p>");
pw.print("<p>password : "+password+"</p>");
pw.print("<p>gender : "+gender+"</p>");
pw.print("<p>hobby : "+hobby+"</p>");
pw.print("<p>rlgn: "+rlgn+"</p>");
if(food!=null) {
for(String s : food) {
pw.print("<p>food: "+s+"</p>");
}
}
Enumeration<String> params = req.getParameterNames();
while(params.hasMoreElements()) {
String param = params.nextElement();
pw.print("<p>파라미터이름: "+param+"</p>");
}
pw.print("</body>");
pw.print("</html>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>T03_SPT</servlet-name>
<servlet-class>kr.or.ddit.basic.T03_ServletParameterTest</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>T03_SPT</servlet-name>
<url-pattern>/T03_SPT</url-pattern>
</servlet-mapping>
파일은 WEB-CONTENT 하단에 있어야한다
form 데이터의 메소드를 post로 쓰면 post이다!
의 action 설정해주기!form의 name속성은 서블릿에서 사용하기 때문에 매우 중요하다!
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>입력폼 예제</title>
</head>
<body>
**<form method="post" action="T03_SPT">**
<label for="username">유저명:</label><br>
<input type="text" name="username" id="username"><br>
<label for="password">패스워드:</label><br>
<input type="password" name="password" id="password"><br>
<hr>
<input type="radio" id="male" name="gender" value="male">
<label for="male">Male</label><br>
<input type="radio" id="female" name="gender" value="female">
<label for="female">Female</label><br>
<input type="radio" id="other" name="gender" value="other">
<label for="other">Other</label><br>
<hr>
<input type="checkbox" id="cb01" name="hobby" value="ch01">
<label for="cb01">낚시</label>
<input type="checkbox" id="cb02" name="hobby" value="ch02">
<label for="cb02">등산</label>
<input type="checkbox" id="cb03" name="hobby" value="ch03">
<label for="cb03">하이킹</label>
<input type="checkbox" id="cb04" name="hobby" value="ch04">
<label for="cb04">독서</label><br>
<hr>
<label for="rlgn">종교</label>
<select id="rlgn" name="rlgn">
<option value="01">불교</option>
<option value="02">기독교</option>
<option value="03">힌두교</option>
<option value="04">기타</option>
</select>
<hr>
<label for="food">좋아하는 음식</label>
<select id="food" name="food" multiple="multiple">
<option value="01">소고기</option>
<option value="02">돼지고기</option>
<option value="03">물고기</option>
<option value="04">채식</option>
</select>
<br>
<br>
<input type="submit" value="Submit">
</form>
</body>
</html>
html은 동적인 작업을 하지 못함.
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class T04_ErrorHandler extends HttpServlet {
// get이 있으니 당연히 set도있음
req.setAttribute("name",new String("홍길동));
System.out.println(:name: )+req.getAttribute("name");
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 서블릿 예외정보 가져오기
Throwable throwable = (Throwable) req.getAttribute("javax.servlet.error.exception"); // 예외객체
Integer statusCode = (Integer) req.getAttribute("javax.servlet.error.status_code"); //에러상태코드
String message = (String) req.getAttribute("javax.servlet.error.message"); //에러메세지
String servletName = (String) req.getAttribute("javax.servlet.error.servlet_name"); //에러발생한 서블릿 이름
if(servletName == null) {
servletName = "알 수 없는 서블릿 이름";
}
String requestURI = (String) req.getAttribute("javax.servlet.error.request_uri"); // 에러발생 url정보
if(requestURI == null) {
requestURI="알 수 없는 URI";
}
//////////////////////////////
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html");
PrintWriter out = resp.getWriter(); //문자기반이기 때문에 writer사용
//바이트기반이면 getOutputStream()사용
String title = "에러/예외정보";
out.println("<!doctype html><html><head><title>"+title+"</title></head>"+"<body>");
if(throwable == null && statusCode == null) {
out.println("<h2>에러정보 없음</h2>");
}else {
out.println("<h2>예외/에러정보 없음</h2>");
out.println("상태코드 : "+statusCode+"<br><br>");
out.println("에러(예외메세지) : "+message+"<br><br>");
out.println("서블릿 이름 : "+servletName+"<br><br>");
out.println("요청 URI : "+requestURI+"<br><br>");
if(statusCode != null) {
out.println("예외타입: "+throwable.getClass().getName()+"<br><br>");
out.println("예외(에러) 메세지:"+throwable.getMessage());
}
}
out.println("</body>");
out.println("</html>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<servlet>
<servlet-name>T04_EH</servlet-name>
<servlet-class>kr.or.ddit.basic.T04_ErrorHandler</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>T04_EH</servlet-name>
<url-pattern>/T04_EH</url-pattern>
</servlet-mapping>
404에러 발생하면 이동해라
<error-page>
<error-code>404</error-code>
<location>/T04_EH</location>
</error-page>
서블릿예외 발생하면 이동해라
<error-page>
<exception-type>javax.servlet.ServletException</exception-type>
<location>/T04_EH</location>
</error-page>
T01 예제에 추가
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 메소드 방식이 get인경우 호출됨...
System.out.println("doGet() 호출됨...");
throw new ServletException("서블릿 예외 발생");
}
예외정보 꺼내고 싶으면 req에서 꺼낸대