ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JSP피피티 06강 서블릿(Servlet)
    JSP 피피티 2020. 8. 20. 16:25

    Servlet이란? 

    • 그냥 자바 클래스다. 웹프로그래밍에서 클라이언트의 요청(URL에 접속해서get/post)을 처리하고 그 결과(HTML을 다시 보내주는 것)를 다시 클라이언트에게 전송하는 HttpServlet 클래스의 구현 규칙을 지킨 자바 프로그래밍 기술
    • 자바로 작성된 프로그램, 서버에서 웹페이지 등을 동적으로 생성하고나 데이터 처리를 수행
    • 클라이언트가 어떠한 요청을 하면 그에 대한 결과를 다시 전송해 주어야 하는데 이런 역할을 하는 자바 프로그램

      -메모리에 상주하여 요청마다 프로세스보다 작은 스레드를 시작하기 때문에 효율이 좋다

      -실행환경은 웹컨테이너(아파치 톰켓) 혹은 서블릿 컨테이너라고 불림
      기능을 포함하기 때문에 웹 컨테이너라고 불리기도함

    • 서버쪽에서 실행되면서 클라이언트의 요청에 따라 동적으로 서비스를 제공하는 자바 클래스

      -JSP같은 웹 어플리케이션은 동적기능을 제공하는데, 옛날에는 JSP가 동적기능을 제공하는것이 아니라 자바기반 서블릿(클래스)이 동적기능을 제공 / 서블릿을 사용해서 동적웹 프로그래밍을 하다가 단점을 보완하기위해 JSP로 발전했다.

    일단 위에는 여러 자료에서 찾은 서블릿에 대한 설명인데 확실하게 잘 모르겠다. 일단 서블릿은 자바로 쓴 프로그램인건 알겠고 요청을 받고 응답을 해주는 것  이것도 뭐 알겠는데 뭔가 확실하지 않다. 실습을 진행해보면서 생각해 봐야겠다.

     

    Servlet의 동작 방식

     

    오 그럴듯한 Servlet 설명을 찾았음


    클라이언트
    0.회원목록 보여줘
    ( 웹 서버에 request)
    ------------------------------------->
    <-------------------------------------
    5.'코드'로 만든 회원목록을 보내줌
    (response)
    실행환경(Container 톰캣)
                  웹 서버
    1.요청들어온 웹문서를 검색
    2.그 문서가 회원목록이 아니라 데이터만 있으면 회원목록을 만들 수 있는 '코드'야
                      WAS
         (Web Application Server)
    3. 그 '코드(server application)' 는 코드가 실행될 수 있는 환경이 필요해(WAS)
                                                                  ↑↓
         4. DB의 정보를 가져다 '코드'로 회원목록을 만들어 WAS에서
                                         데이터베이스

    서블릿이라는 이름은 만약에 사용자(Client)의 요청이 C,R,U,D 이렇다고 치면 웹서버는 C,R,U,D를 할 수 있는 각각의 '코드'를 찾아!! 그때그때 요청에 맞는 코드를! 이때 각 요청에 맞게 따로따로 작성된 코드를 서블릿이라 한다.

     

    이때 웹서버에서 실시간으로 저장되어 있는 데이터를 가지고 회원목록을 만들어서 주기 때문에 동적이라 한다.

    엤날에는 웹서버에서 이미 만들어진 회원목록 웹문서를 보내줘 서버에 있는 문서가 업데이트되면 여러명의 사용자는 다시 업댓같은거 해야 하는 불편함이 있었다고 한다.

     

    src/study.jsp.model2.controller/HelloServlet.java

    HelloServlet.java

    package study.jsp.model2.controller;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Hello ServletMain 서블릿 클래스.
     * 모든 서블릿은 javax.servlet.http.HttpServlet을 상속받아야 한다.
     * 
     */
    // 이 클래스를 URL에 노출시키기 위한 경로
    //여기에 들어가는 URL과 클래스의 이름은 전혀 상관이 없다.
    //지금까지 URL은 폴더구조와 파일 위치였는데 이제부터는 아무 상관 없다는 말
    @WebServlet("/HelloServlet")
    public class HelloServlet extends HttpServlet {
    	
    	//객체 질렬화 아이디 --> 이클립스가 생성한 값을 사용하게 된다.
    	private static final long serialVersionUID = 1L;
           
        /**
         * 생성자(특별한 경우가 아니면 사용안함)
         */
        public HelloServlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * 브라우저가 별도의 파라미터 없이 접속되거나 HTTP GET 방식으로 접근한 경우 실행
    	 * @param request - JSP의 request 내장객체
    	 * @param response = JSP의 response 내장객체
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		response.getWriter().append("Served at: ").append(request.getContextPath());
    	}
    
    	/**
    	 * 브라우저가 HTTP POST 방식으로 접근한 경우 실행된다.
    	 * 기본 코드는 현재 클래스의 doGet() 메서드를 호출해서 프로그램의 흐름을 
    	 * doGet() 메서드 한 곳에서만 처리하도록 제시하고 있다.
    	 * @param request - JSP의 내장 객체
    	 * @param response = JSP의 response 내장객체
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    

    @WebServlet("/HelloServlet") == http://localhost:8080/프로젝트명/HelloServlet 

       ↑(어노테이션)이게 이 클래스의 URL을 결정하는데 ( )안에 뭐가 들어가든 아무상관 없다. 보통 .do 를 많이 쓴다더라.

      *주의: 이 값이 다른 클래스와 중복될 경우 Tomcat 자체의 실행에 문제가 발생하므로 값 지정에 주의해야 한다.
             만약 중복이 된다면 이클립스에 등록된 모든 프로젝트가 실행되지 못하고 에러

     

    웹 브라우저가 GET/ POST중 어떤 방식으로 접근하는지에 따라 doGet() 메서드와 doPost() 메서드가 선택적으로 실행된다.

     

    직렬화란?? 더보기클릭

    더보기

    프로그래밍에서 오브젝트를 저장가능하거나 전송가능한 형태로 바꾸기 위해 필요한 직렬화


    Serial 연쇄. 연속해서 이어지는 어떤것


    ex) 드라마 씨리즈, 연속적인 010101010 2진수 데이터, 연속적인 문장형 데이터를 표현할때 사용하는 단어

     

    직렬화?  
    오브젝트를 연속된 문장형데이터나 바이트데이터로 바꾸는것 

     

    왜?
    오브젝트는 메모리에 존재하고 추상적
    스트링과 바이트는드라이브에 저장할수있고 통신선을 통해 전송할수도 있다.

    반대로 스트링과 바이트로 부터 오브젝트를 생성하는것을 역직렬화 라 한다.

    게임 오브젝트a 를편집한다고 했을때 컴터를 끄고 다시 실행해서 편집을 이어 가는것은 이상하다. 

    왜냐하면 오브젝트는 프로그램에게 할당된 메모리상에 존재하고 프로그램이 종료되면 해당프로그램이 사용중이던 메모리상의 오브젝트도 없어지기 때문이다. 하지만 실제로는 편집하다 중간에 끄고 다시 켰을때 나의 수정사항이 존재한다. 그이유는 오브젝트a 에게 시리얼라이즈화 가능하다는 표시가 붙어있기때문! 우리는 게임오브젝트a를 편집했다고 생각하지만 실제로는 시리얼라이즈 화를 통해서 편집된 게임오브젝트의 정보가 텍스트 파일로 나의 컴퓨터 어딘가에 저장되어있다. 그렇게 파일로서 저장된 게임오브젝트a의 정보가 어딘가에 있기때문에 나중에 편집을 다시 시작할때 해당 텍스트파일로 부터역직렬화를 통하여 게임오브젝트a 를 생성하는것 

    예를 들어 1번컴퓨터에 오브젝트a가 있는데 2번 컴터에 전송하고 싶다.
    문제는 1번컴터와 2번컴터는 사용하는 하드웨어 운영체제 프로그래밍 언어가 전부 다르다 .

    오브젝트는 물리적인 회선으로 전송가능한 타입이 아니라 메모리에 존재하는 추상적인 타입이다.
    하지만 두컴터모두 0101이라는 날것그대로의 2진법 신호 바이트데이터를 다룰수 있다.
    이런 바이트데이터는 물리적인 회선을 통해서 전기신호로 전송할 수 있다. 
    두컴터가 회선으로 연결되있다 봤을때 
    1번 컴터에서 오브젝트a를 바이트 데이터로 직렬화 >회선을 통해 전달> 2번 컴터에서 전송받은 바이트를 역직렬화 한다. 다운로드 받은 바이트 데이터는 그저 파일일 뿐이니까 


    파일은 메모리위에 존재하는 실체가 아니다  메모리위에 존재하는 실체로 만들기 위해서 바이트데이터를 역직렬화해 실제로 존재하는 오브젝트로 탄생시킨다. 

    같은 예로 서버와 웹브라우저에 사이에서 데이터를 주고받을때 json 포멧을 통해 오브젝트를 주고 받는다. 
    오브젝트에서 json으로 직렬화 해서 전송을 하고 다운로드받은 json파일을 역직렬화해서 오브젝트를 복구한다. 

    객체 직렬화 아이디가 왜 필요한지 찾아보다가 직렬화 개념 잡고 간다. 저 글을 읽어보니까 객체 직렬화 아이디가 필요한 이유는 객체를 저장했다가 직렬화된 아이디로 찾기 위해서 라고 이해하기로함

     

    FromServlet.java

    package study.jsp.model2.controller;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class FromServlet
     */
    @WebServlet("/FromServlet")
    public class FromServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public FromServlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		/* 1) 페이지 헤더 설정 */
    		//브라우저에 전달되는 컨텐츠의 형식 지정
    		response.setContentType("text/html; charset=utf-8");
    		//브라우저로부터 전달받는 파라미터의 인코딩 형식 지정
    		request.setCharacterEncoding("utf-8");
    		
    		/* 2)브라우저에게 전달될 HTML 출력하기 */
    		//JSP에서 사용되던 out내장객체를 생성한다. -->import java.io.PrintWriter;
    		PrintWriter out = response.getWriter();
    		
    		out.println("<!doctype html>");
    		out.println("<html>");
    		out.println("<head><meta charset='utf-8'/></head>");
    		out.println("<body>");
    		out.println("<h1>FromServlet 클래스 입니다.</h1>");
    		
    		
    		//SubPage에게 GET파라미터 전달하기
    		out.println("<p><a href='ToServlet?num1=100&num2=200'>go to ToServlt</a></p>");
    		
    		//SubPage에게 POST파라미터 전달하기
    		out.println("<form method='post' action='ToServlet'>");
    		out.println("<input type='text' name='user_name'>");
    		out.println("<input type='submit' value='전송'/>");
    		out.println("</form>");
    		
    		out.println("</body>");
    		out.println("</html>");
    		
    		
    		// TODO Auto-generated method stub
    		response.getWriter().append("Served at: ").append(request.getContextPath());
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    

    서블릿의 역할은 클라이언트의 요청(@WebServlet("/FromServlet") + enter)에 대해HTML 코드를 응답(doGet()메서드실행) 데이터로 전달하는것. 

     

    내생각에 위의 코드에서 doGet()에만 기능을 써놓은 이유가 이 클라이언트의 요청이 URL이었기 때문인거 가틈

     

     

    ToServlet.java

    package study.jsp.model2.controller;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class ToServlet
     */
    @WebServlet("/ToServlet")
    public class ToServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public ToServlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// 브라우저에 전달되는 컨텐츠의 형식 지정
    		response.setContentType("text/html; charset=utf-8");
    		//브라우저로부터 전달받는 파라미터의 인코딩 형식 지정
    		request.setCharacterEncoding("utf-8");
    		
    		//GET파라미터 받기
    		String num1 = request.getParameter("num1");
    		String num2 = request.getParameter("num2");
    		
    		//파라미터를 통한 연산 수행하기
    		int num3 = Integer.parseInt(num1) + Integer.parseInt(num2);
    		String result = String.format("%s + %s = %d",num1,num2,num3);
    		
    		//웹 페이지에 출력을 위한 out객체 생성
    		PrintWriter out = response.getWriter();
    		
    		//HTML 결과 출력하기
    		out.println("<!doctype html>");
    		out.println("<html>");
    		out.println("<head><meta charset='utf-8' /></head>");
    		out.println("<body><h1>"+ result + "</h1></body>");
    		out.println("</html>");
    		response.getWriter().append("Served at: ").append(request.getContextPath());
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		//브라우저에 전달되는 컨텐츠의 형식 지정
    		response.setContentType("text/html; charset=utf-8");
    		//브라우저로부터 전달받는 파라미터의 인코딩 형식 지정
    		request.setCharacterEncoding("utf-8");
    		
    		//POST 파라미터 받기
    		String user_name = request.getParameter("user_name");
    		
    		//웹 페이지에 출력을 위한 out 객체 생성.
    		PrintWriter out = response.getWriter();
    		//HTML 결과 출력하기
    		out.println("<!doctype html>");
    		out.println("<html>");
    		out.println("<head><meta charset='utf-8' /></head>");
    		out.println("<body><h1>"+ user_name + "님 안녕하세요.</h1></body>");
    		out.println("</html>");
    		
    		doGet(request, response);
    	}
    
    }
    

     

    FromServlet.java 페이지에서 'go to ToServlet'을 클릭하면 

     

    @WebServlet("/ToServlet") 이 페이지의 doGet()이 요청을 처리 왜냐하면 FromServlet.java에서 전달된 파라미터가 url이기 때문에

     

    FromServlet.java페이지에서 input태그에 입력값을 넣으면 form태그에 post라고 method 속성을 정해줬기 때문에 ToServlet에서 doPost()이 실행되어 요청을 처리함

전설의 개발자