자바 웹프로그래밍 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 코드도 나중에 서블릿 코드로 바뀐다.