BoostCource/Back-end

#02. BE - JSP & Servlet

칸타탓 2018. 7. 13. 16:21

<2. DB 연결 웹 애플리케이션 - JSP & Servlet>

[boostcourse full-stack] http://www.edwith.org/boostcourse-web





* JSP



JSP 코드 예제

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>sum10</title>
</head>
<body>

<% 
    int total = 0;
    for(int i = 1; i <= 10; i++){
        total = total + i;
    }
%>

1부터 10까지의 합 : <%=total %>

</body>
</html>


JSP 코드

- 기본적인 구조는 html 파일과 유사하나 첫번째 줄(<%@page ... )이 차이

- <%@ : 페이지 지시자 (자바 언어로 작성되어 있으며, 지금 출력되는 결과는 utf-8이라는 문자 셋으로 된 html문서임을 알려줌)

- JSP 자체가 동작하는 것이 아니라 Servlet으로 변환되어 동작된다. 바뀐 서블릿이 동작하는 것!

- html 안에서 프로그램을 사용하기 위해(자바 코드를 넣어) 사용

- <% //java code %>

  <%= //응답 결과로 출력 %>: 표현식(out.println과 같다)

  <%! %>: 선언식, 서블릿의 service 메소드 바깥쪽에 만들어진다.



JSP 등장 배경

마이크로소프트에서 ASP(Active Server Page)라는 쉽게 웹을 개발할 수 있는 스크립트(script) 엔진을 발표했다.

1997년에 발표된 서블릿은 ASP에 비하여 상대적으로 개발 방식이 불편했다.

따라서 ASP에 대항하기 위하여 1999년 썬마이크로시스템즈에서 JSP를 발표함

JSP는 실제로 서블릿 기술을 사용한다.







* JSP 라이프사이클


WAS는 웹 브라우저로부터 JSP에 대한 요청을 받게 되면, JSP코드를 서블릿 소스코드로 변환한 후 컴파일 하여 실행
[참고] https://beginnersbook.com/2013/05/jsp-tutorial-life-cycle/


JSP의 실행순서

  1. 브라우저가 웹서버에 JSP에 대한 요청 정보를 전달한다.

  2. 브라우저가 요청한 JSP가 최초로 요청했을 경우에만

    1. JSP로 작성된 코드가 서블릿으로 코드로 변환한다. (.java 파일 생성)

    2. 서블릿 코드를 컴파일해서 실행가능한 bytecode로 변환한다. (.class 파일 생성)

    3. 서블릿 클래스를 로딩하고 인스턴스를 생성한다.

  3. 서블릿이 실행되어 요청을 처리하고 응답 정보를 생성한다.






* JSP 문법

선언문

  • 선언문은 JSP 페이지 내에서 필요한 멤버변수나 메소드가 필요할 때 선언해 사용하는 요소이다.


- 선언문의 문법

<%! 문장 %>


ex) <%! public void jspInit() { ... } %>와 같이 작성하는 경우 service가 아닌 init에 작성된다.



선언문으로 멤버변수나 메소드를 선언하면 자바 코드로 바뀔 때의 위치는 위와 같다.





스크립트릿

  • 가장 일반적으로 많이 쓰이는 스크립트 요소이다.

  • 주로 프로그래밍의 로직을 기술할 때 사용한다.

  • 스크립트릿에서 선언된 변수는 지역변수이다.

  • 스크립트릿 안에서 선언되는 변수는 모두 Service라는 메소드안에 선언되는 변수이다.


- 스크립트릿의 문법

<% 문장%>



스크립트릿은 서블릿으로 바뀔 때 service 메소드 안에서 위와 같이 바뀌어 실행된다.




표현식(Expression)

  • JSP 페이지에서 웹 브라우저에 출력할 부분을 표현 (즉, 화면에 출력하기 위한 것)

  • 스크립트릿내에서 출력할 부분은 내장객체인 out 객체의 print() 또는 println() 메소드를 사용해서 출력


- 표현식의 문법

<%=문장%>




주석(Comment)

1. HTML 주석

HTML 주석은 <!--로 시작해서 -->로 끝나는 형태

HTML 주석은 HTML주석을 사용한 페이지를 웹에서 서비스할 때 화면에 주석이 내용이 표시되지는 않으나, [소스보기]수행하면 HTML주석의 내용이 화면에 표시한다.


- HTML주석의 예시

<!-- html 주석입니다. -->


2. JSP주석

JSP 페이지에서만 사용되며 <%--로 시작해서 --%>로 끝나는 형태

JSP 주석은 해당 페이지를, 웹 브라우저를 통해 출력 결과로서 표시하거나, 웹 브라우저 상에서 소스 보기를 해도 표시 되지 않음. 또한 JSP주석 내에 실행코드를 넣어도 그 코드는 실행되지 않는다.


- JSP주석의 예시

<%-- JSP 주석입니다. --%>


3. 자바주석

자바 주석은 //, /**/을 사용해서 작성한다.

//은 한 줄짜리 주석을 작성할 때 사용되고, /**/은 여러 줄의 주석을 작성할 때 사용

스크립트릿이나 선언문에서 사용되는 주석으로, 자바와 주석 처리 방법이 같다.


- 자바주석의 예시

//주석

/*주석

여러 줄에 걸친 주석이다.

*/






JSP 내장객체


내장객체: JSP에서 개발자가 선언하지 않아도, 사용할 수 있는 미리 선언된 변수


JSP 내장 객체란?

JSP를 실행하면 서블릿 소스가 생성되고 실행된다.

JSP에 입력한 대부분의 코드는 생성되는 서블릿 소스의 _jspService() 메소드 안에 삽입되는 코드로 생성된다.

_jspService()에 삽입된 코드의 윗부분에 미리 선언된 객체들이 있는데, 해당 객체들은 jsp에서도 사용 가능하다.

response, request, application, session, out과 같은 변수를 내장객체라고 한다.





* redirect


리다이렉트는 HTTP프로토콜로 정해진 규칙이다.

서버는 클라이언트의 요청에 대해 특정 URL로 이동을 요청할 수 있다. 이를 리다이렉트라고 한다.


서버는 클라이언트에게 HTTP 상태코드 302로 응답하는데 이때 헤더 내 Location 값에 이동할 URL 을 추가한다.

클라이언트는 리다이렉션 응답을 받게 되면 헤더(Location)에 포함된 URL로 재요청을 보내게 된다. 이때 브라우저의 주소창은 새 URL로 바뀌게 된다.

클라이언트는 서버로부터 받은 상태 값이 302이면 Location헤더값으로 재요청을 보내게 된다. 이때 브라우저의 주소창은 전송받은 URL로 바뀌게 된다.


서블릿이나 JSP는 리다이렉트하기 위해 HttpServletResponse 클래스의 sendRedirect() 메소드를 사용한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    response.sendRedirect("redirect02.jsp");
%>    

크롬 개발자 도구로 확인해보면 redirect01 요청이 된 후 302 상태코드를 받아오면, redirect02가 요청되고 있다.







* forward

  1. 웹 브라우저에서 Servlet1에게 요청을 보냄

  2. Servlet1은 요청을 처리한 후, 그 결과를 HttpServletRequest에 저장

  3. Servlet1은 결과가 저장된 HttpServletRequest와 응답을 위한 HttpServletResponse를 같은 웹 어플리케이션 안에 있는 Servlet2에게 전송(forward)

  4. Servlet2는 Servlet1으로 부터 받은 HttpServletRequest와 HttpServletResponse를 이용하여 요청을 처리한 후 웹 브라우저에게 결과를 전송


  • redirect와 forward의 차이

redirect는 클라이언트가 서버에 요청을 보내면 일을 처리하고 클라이언트에게 알린 후 다시 요청 (URL 바뀜)

forward는 클라이언트가 요청을 보내면 혼자 처리하는 것이 아닌 처리를 맡기는 것 (URL 바뀌지 않음)


=> 요청이 하나(포워드)인지, 요청이 서로 다른 두개인지(리다이렉트)가 가장 중요한 차이점!

포워드는 요청이 들어와서 서버가 내부적으로 옮겨줬을 뿐, 새로운 요청을 하는 것이 아님(요청, 응답 객체가 그대로 유지)



@WebServlet("/front")
public class FrontServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public FrontServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
     */
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            
            int diceValue = (int)(Math.random() * 6) + 1; 
            request.setAttribute("dice", diceValue);
            
            RequestDispatcher requestDispatehcer = request.getRequestDispatcher("/next");
            requestDispatehcer.forward(request, response);
    }

}

RequestDispatcher 객체를 사용한다.

포워드 경로는 /로 시작해야하며 같은 웹 어플리케이션 내에서만 가능

포워드 메소드를 실행할 때 request, response 객체를 반드시 넘겨주어야 한다.



NextServlet.java

@WebServlet("/next")

protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head><title>form</title></head>");
        out.println("<body>");

        int dice = (Integer)request.getAttribute("dice");
        out.println("dice : " + dice);
        for(int i = 0; i < dice; i++) {
            out.print("<br>hello");
        }
        out.println("</body>");
        out.println("</html>");
    }

넘겨받은 값 출력 (넘겨받은 값의 수 만큼 hello를 출력한다.)

request로부터 값 찾아오기 (dice로 이름을 설정해 주었으므로 꼭 이름을 맞춰주어야 함)

받아온 값은 object형이므로 정수로 변환 하여 출력해야 한다.


이때 URL을 확인해보면, next가 아닌 front로 전혀 URL 변화가 없다.






Servlet & JSP 연동


Servlet은 프로그램 로직이 수행되기에 유리하며 IDE 등에서 지원을 좀 더 잘해준다.

JSP는 결과를 출력하기에 Servlet보다 유리하다. 필요한 html문을 그냥 입력하면 된다.


프로그램 로직 수행은 Servlet에서, 결과 출력은 JSP에서 하도록 한다.

Servlet과 JSP의 장단점을 해결하기 위해서 Servlet에서 프로그램 로직이 수행되고, 그 결과를 JSP에게 포워딩하는 방법이 사용된다.

- 실습 코드

@WebServlet("/LogicServlet")
public class LogicServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public LogicServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int v1 = (int)(Math.random() * 100) + 1;
        int v2 = (int)(Math.random() * 100) + 1;
        int result = v1 + v2;
        
        request.setAttribute("v1", v1);
        request.setAttribute("v2", v2);
        request.setAttribute("result", result);
        
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/result.jsp");
        requestDispatcher.forward(request, response);
    }

}
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
EL표기법으로 출력합니다.<br>
${v1} + ${v2} = ${result} <br><br>

스클립틀릿과 표현식을 이용해 출력합니다.<br>
<%
    int v1 = (int)request.getAttribute("v1");
    int v2 = (int)request.getAttribute("v2");
    int result = (int)request.getAttribute("result");
%>

<%=v1%> + <%=v2 %> = <%=result %>
</body>
</html>

(+) get, post방식에 상관 없이 실행시키고 싶다면 service 메소드를 오버라이드 하면 된다.


servlet에서 jsp로 넘기고 싶다면 servlet에서 request한테 setAttribute 해서 맡겨두어야 한다.

그 후 포워드 하기위해 requestDispatcher 객체를 이용한다. (이동 원하는 주소 적기 - 상대 경로 이용)

request, response 반드시 넘기기 (요청 객체, 응답 객체)


servlet에서 넘긴 값을 jsp에서 찾아올 때는 request.getAttribute 이용한다.

=> 이렇게 로직은 서블릿에서, 응답 결과는 jsp에서 출력하는 것!



'BoostCource > Back-end' 카테고리의 다른 글

#02. BE - Maven으로 프로젝트 만들기  (0) 2018.07.15
#02. BE - JSTL  (0) 2018.07.14
#02. BE - EL  (0) 2018.07.14
#02. BE - Scope  (0) 2018.07.14
[BE] 01. Servlet 기초  (0) 2018.05.20