패캠 JAVA 9일차
자바 웹프로그래밍 2기 강의 9일차 내용을 정리한 포스팅입니다.
객체지향적 프로그래밍 연습
-
웹프로그래밍은 적합하지 않다
-
HTTP 무상태 프로토콜
-
UI가 맞물려 있다.
-
비지니스로직이 명확하지 않다.
-
객체 지향 연습을 위한 좋은 예
-
이번 실습과 같은 HTTP 웹 서버
-
프레임워크 또는 라이브러리 구현해 보기
-
볼링 게임 점수판(단, UI는 콘솔)
-
체스 게임(단, UI는 콘솔)
-
지뢰 찾기 게임(단, UI는 콘솔)
https://developerfarm.wordpress.com/2012/02/03/object_calisthenics_summary/
프레임워크 보단 자바를 잘해야한다.
- 자바 프로그래밍을 다양한 방식으로 접근해보도록 하자
HTTP
HTTPReuest
- Request Line / Request Header / Blank / Request Body
HTTPResopnse
- Status Line/ Response Header / Blank / Response Body
브라우저가 한번에 여러개의 요청을 보냄
19:46:03.181 [DEBUG] [Thread-0] [webserver.RequestHandler] - New Client Connect! Connected IP : /0:0:0:0:0:0:0:1, Port : 3557
19:46:03.182 [DEBUG] [Thread-1] [webserver.RequestHandler] - New Client Connect! Connected IP : /0:0:0:0:0:0:0:1, Port : 3558
19:46:03.183 [DEBUG] [Thread-2] [webserver.RequestHandler] - New Client Connect! Connected IP : /0:0:0:0:0:0:0:1, Port : 3559
19:46:03.183 [DEBUG] [Thread-3] [webserver.RequestHandler] - New Client Connect! Connected IP : /0:0:0:0:0:0:0:1, Port : 3560
19:46:03.184 [DEBUG] [Thread-5] [webserver.RequestHandler] - New Client Connect! Connected IP : /0:0:0:0:0:0:0:1, Port : 3562
19:46:03.184 [DEBUG] [Thread-4] [webserver.RequestHandler] - New Client Connect! Connected IP : /0:0:0:0:0:0:0:1, Port : 3561
-
console 보면 Thread가 한번에 여러개 생성된 것을 확인 할 수 있다.
-
클라이언트는 매 요청 마다 포트 번호가 다르다.
-
소켓이 연결되기까지 three way hand-shake (한번의 소켓을 연결하는데 많은 비용이 든다.)
동적 자원과 정적 자원의 분리
-
동적 HTML : tomcat
-
js/css/image : static server (nginx)
리펙토링!
-
클래스를 어떻게 쪼갤것인가 (책임을 나눈다.)
-
특정 클래스의 메소드를 다른 클래스에게 역할을 위임해도 된다.
ALT+SHIFT+M -> Refactor Method
내장 톰켓
public static void main(String[] args) throws Exception {
String webappDirLocation = "webapp/";
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);
tomcat.addWebapp("/", new File(webappDirLocation).getAbsolutePath());
logger.info("configuring app with basedir: {}", new File("./" + webappDirLocation).getAbsolutePath());
tomcat.start();
tomcat.getServer().await();
}
MAP
@WebServlet("/user/list")
public class ListUserServlet extends HttpServlet {
이 부분을 보고 맵으로 관리해준다. (누가? 서블릿이)
요청이 많아도 컨트롤러는 1개!
public class RequestMapping {
private static Map<String, Controller> controllers = new HashMap<String, Controller>();
static {
controllers.put("/user/create", new CreateUserController());
controllers.put("/user/login", new LoginController());
controllers.put("/user/list", new ListUserController());
}
public static Controller getController(String requestUrl) {
return controllers.get(requestUrl);
}
}
서버 시작할때 맵이 초기화 되서 사실 1개의 인스턴스를 매 요청하는 사용자가 사용한다.
public class ListUserController extends AbstractController{
// 멤버 변수에 상태값을 관리하면 여러 쓰레드가 해당 인스턴스 하나를 사용하니 문제가 된다. (변하는 값은 쓰지말것!)
Map<String, String> cookie = HttpRequestUtils.parseCookies(httpRequest.getRequestHeader("Cookie"));
private static final Logger log = LoggerFactory.getLogger(ListUserController.class);
@Override
protected void doGet(HttpRequest httpRequest, HttpResponse httpResponse) {
String path = httpRequest.getRequestPath();
if (!isLogined(cookie)) {
path = "/index.html";
}
try {
httpResponse.forward(path.trim(), httpRequest.getRequestHeader("Accept"));
} catch (IOException e) {
log.error("Error - {} ", e.getMessage());
}
}
private boolean isLogined (Map<String, String> cookie) {
return Boolean.parseBoolean(cookie.get("logined"));
}
}
IOC (서블릿 컨테이너)
자바 객체관리를 서블릿 컨테이너가 해준다.
서블릿의 인스턴스를 주도적으로 관리하면서 초기화, 서비스, 후처리와 같은 전체 적인 라이프 사이클을 서블릿 컨테이너가 관리해준다. (= SPRING BEAN CONTAINER)
개발자가 해야했던것을 컨테이너가 해준다는거
public interface Servlet {
void init(ServletConfig var1) throws ServletException; // servicer tomcat start
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy(); //service tomcat stop
}
Sevelet Life Cycle
여러스레드가 하나의 인스턴스 쓰는 원리
-
메서드 레벨에서 사용하는 메모리공간이 쓰레드 별로 별도로 존재해서 사용한다.
-
문제는 멤버 변수는 어떤 메모리 공간에 공유하는 공간에 여러 쓰레드가 접근해서 사용하기 때문에 문제가 발생하는 것이다.
-
자바 스택 영역 힙영역 뭐하는지 찾아보기
JSP == Servlet
- JSP 코드도 나중에 서블릿 코드로 바뀐다.