JSP란?


▶ JSP는 Servlet 클래스를 자동 생성할 때 참고하는 파일입니다.


▶ 자동 생성이란?
 
ex) hello.jsp --- [JSP 엔진}을 거치면 ---> hello_jsp.java(서블릿 클래스) 소스 파일 생성됩니다. 이것을 자동 생성이라 합니다.


▶ 언제 생성될까?

웹 브라우저가 요청했을 때,
- JSP에 해당하는 자바 서블릿 파일이 없으면 만듭니다.
- JSP 파일이 변경되었을 경우에 만듭니다.


▶ 자동 생성된 서블릿 파일의 위치

톰캣 서버의 경우 : $톰캣홈/work/폴더에 있습니다.
이클립스의 톰캣 임시 배치 폴더의 경우 : tmpX/work/ 폴더에 있습니다.


▶ 결론!

- 결국 JSP 파일을 가지고 서블릿 클래스를 생성합니다.

JSP가 직접 실행되는 것이 아니라 JSP로 만든 자바 서블릿 클래스가
실행되는 것입니다.

JSP가 직접 실행되지 않습니다.


▶ JSP 기술이 등장한 이유

I 서블릿에서 콘텐츠를 출력하려면 스트림 클래스를 사용하여 출력 함수를
   호출해야 하기 때문입니다.

II 자바에선 복잡한 문자열을 출력하려코드 작성이 번거로워 집니다.

II그래서 자바로 콘텐츠를 출력하는 코드를 자동으로 만들기 위해 등장하였습니다.

IV 또한 자바 언어를 모르는 사람도 쉽게 서버 프로그램을 작성할 수 있게
    도와주기 위해서 등장하였습니다.


_jspService() 메서드?

웹 브라우저에서 요청이 들어오면,
 - 서블릿 컨테이너가 service() 메서드가 호출되고
 - service() 에서 _jspService() 메서드가 호출됩니다.



참고
─ 
JSP 엔진이 JSP 파일을 가지고 서블릿 클래스를 만들 때 반드시 지켜야 하는
규칙이 있습니다.
 - javax.servlet.jsp.HttpJspPage 인터페이스를 구현해야 합니다.


 HttpJspPage 의 구성
 javax.servlet.Servlet
 ㄴ void Init(ServletConfig) - 웹어플리케이션 실행시 jspInit() 호출
 ㄴ void service(ServletRequest, ServletResponse)
 ㄴ void destroy() - 웹어플리케이션 종료시 jspDestroy() 호출
 ㄴ String getServletInfo()
 ㄴ ServletConfig getServletConfig()

 javax.servlet.jsp.JspPage extends Servlet
 ㄴ void jspInit()
 ㄴ void jspDestroy()

 javax.servlet.jsp.HttpJspPage extends JspPage
 -ㄴvoid _jspService(HttpServletRequest, HttpServletResponse)

 결국 서블릿이 되기 위해서 javax.servlet.Servlet 인터페이스를 
 구현해야 하고 JspPage, HttpJspPage의 추가된 메서드까지 구현합니다.



 JSP 구성 요소

▶ 템플릿 데이터
    - 화면에 출력할 콘텐츠
    - 아래에 지정된 문법을 제외한 JSP 파일에 작성하는 모든 텍스트는
      템플릿 데이터입니다.
    - 자바 코드 : 다음과 같이 출력문을 만듭니다.
       out.write("템플릿데이터"); 
  out.print("템플릿데이터");


▶ 스크립트릿(scriptlet) 엘리먼트
    - JSP에 자바 코드를 삽입할 때 사용합니다.
     <% 자바 코드 %>
    - JSP 엔진이 생성하는 서블릿 파일에 그대로 복사됩니다.
    - _jspService() 메서드 안에 순서대로 그대로 복사됩니다.

▶ 지시어(directive) 엘리먼트
     ▷ <%@ page %>
        language 속성 : 
          스크립트릿 등에서 사용하는 프로그래밍 언어가 무엇인지
          지정합니다. 현재 java만 지정할 수 있습니다. 
     ex) page language="java"

 contentType 속성 : 
    response.setContentType() 코드를 생성합니다.
    ex) contentType="text/html; charset=UTF-8"
 
 pageEncoding 속성 : 
    JSP 파일이 어떤 인코딩으로 저장되었는지 지정합니다.
    JSP 엔진이 JSP 파일을 읽을 때 사용합니다.
    ex) pageEncoding="UTF-8"

 trimDirectiveWhitespaces 속성 : 
    JSP 태그를 사용한 후 줄바꿈 코드가 있을 때의 제거 여부를 결정합니다.
    ex) trimDirectiveWhitespaces="true"
 
 buffer 속성 :
    출력 스트림의 기본 버퍼 크기를 지정합니다. 기본이 8kb입니다.
    ex) buffer="8kb"
 
 autoFlush 속성 :
    버퍼가 찼을 때 자동으로 출력할지의 여부를 지정합니다. 기본이 true입니다.
    ex) autoFlush="true"

 import 속성 :
    import 문을 추가할 때 사용합니다. 콤마(,)로 여러 개의 패키지를 지정할 수 
    있습니다. 또는 여러 개의 <%@ page import="..."%> 태그를 작성할 수 있습니다.
    그러나 여러 개의 import 속성을 둘 수는 없습니다.
    ex) import="java.util.ArrayList.java.net.Socket"   


     ▷ <%@ include %>
         file 속성 :
           지정된 파일을 그대로 읽어서 JSP 파일 안 include 태그가 있는 자리에
           그대로 포함시킨다. 그 후 자바 서블릿 클래스를 만든다.
           참고로 <jsp:include>는 RequestDispatcher의 include()를 호출한 것과 같다.
           지정된 파일이 JSP라면 실행할 것이고, 일반 텍스트라면 그 내용을 출력할 것이다.
           

     ▷ <%@ taglib %>
        JSP에서 기본으로 제공하지 않는, 외부에서 제공하는 태그를 사용할 때 선언합니다.
        prefix 속성 :
          외부 태그를 사용할 때 태그명 앞에 붙이는 접두어입니다. (=태그의 패키지명)
        url 속성 :
          외부 태그의 라이브러리 이름을 넣습니다. 자바의 패키지 명과는
          다르게 URL 주소 형태로 되어 있습니다. 개발자가 직접 만든 태그나
          외부에서 만든 태그를 사용하려면 /WEB-INF/classes 또는 /WEB-INF/lib에
          태그를 처리하는 라이브러리를 두어야 합니다.
       ex) <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
     
            
▶ 표현식(expression) 엘리먼트
    - 어떤 결과를 출력하는 코드를 만들고 싶을 때 사용합니다.
     <% 표현식 %>
      자바 코드 : out.println()

▶ 선언문(declaration) 엘리먼트
     - JSP 파일을 이용하여 만든 서블릿 클래스에 필드나 메서드를 추가하고        싶을 때 사용합니다.
     - <%! 자바 코드 %>
       자바 서블릿:
       class 서블릿 extends .... {
         자바 코드
       }
     - _jspService() 메서드 안에 놓여지는 것이 아니라,
       class 블록 안에 놓여집니다.
       따라서 클래스 블록 안에 작성할 수 있는 것은 모두 가능합니다.
     - 그래서 태그를 선언하는 순서는 상관 없습니다.

expression element와 declaration element의 예제

<%@ page language="java" 
contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    trimDirectiveWhitespaces="true"
    %>
<html>
<%! int age = 20; %>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP</title>
</head>
<body>
<%plus(10, 20); %>
10 + 20 = <%= result %><br>
</body>
</html>

<%!
int result;
void plus(int a, int b) {
    this.result = a + b;
}
%>  


▶ JSP 액션 태그
    - JSP에서 기본으로 제공하는 태그이다. 이 태그를 사용하기 위해 따로
      라이브러리를 가져오는 taglib를 선언할 필요가 없다.
  ▷ jsp:useBean
   => Serlvet 
   - id 속성 : 
     값을 보관소에 저장할 때 사용할 이름. 변수명으로도 사용합니다.
   - class 속성 : 
     변수의 타입. 보관소에 객체가 없으면 이 클래스의 인스턴스를 생성합니다. 
      import를 했는지의 여부와 상관없이 반드시 전체 클래스 이름을 적어야 합니다.
   - scope 속성 : 
     객체를 꺼내는 보관소를 가리킵니다. 기본이 pageContext입니다. 
     만약 보관소에 객체가 없다면 생성합니다.
   
  ex) <jsp:useBean id="list" class="java.util.ArrayList" scope="page">
       </jsp:useBean> 이 코드는 다음과 비슷한 자바 코드를 생성합니다.
  
   → java.util.ArrayList list = (java.util.ArrayList)pageContext.getAttribute("list");
        if (list == null) { 
          list = new java.util.ArrayList();
          pageContext.setAttribute("list", list);
        }
    
    - type 속성 :
      변수의 타입을 지정할 때 사용합니다. type 속성이 없으면 class 속성의 값이
       변수의 타입이 됩니다. 

    ▷ jsp:include
     - 다른 서블릿/JSP로 실행을 위임할 때 사용하는 태그입니다.
     - include는 RequestDispatcher.include()와 같습니다.
        ex) <jsp:include page="b.jsp"/>

     ▷ jsp:param
     - 다른 서블릿/JSP를 요청할 때 넘겨주는 파라미터 값입니다.

JSP 확장 태그(JSTL)
   - JSP에서 기본으로 제공하는 액션 태그만으로는 프로그래밍
     하기에 부족함이 많습니다. JSTL은 액션 태그에 덧붙혀 공식적으로 
     추가한 확장 태그(JSTL, JSP Standard Tag Library)입니다.
   - 이 태그를 사용하려면 이 태그를 처리하는 클래스들, 즉 JSTL 구현
     라이브러리를 다운로드 받아야 합니다. 서블릿 컨테이너가 기본으로
     제공하지 않습니다. 
   - 여러 JSTL 구현 라이브러리가 있지만, 대부분 apache.org 에서 만든
      것을 사용합니다.
   - 그리고 JSP 페이지에서 이 라이브러리를 사용하려면
      1) 웹 애플리케이션 라이브러리로 포함시켜야 합니다.
         - /WEB-INF/lib/ 폴더에 라이브러리 파일을 두어야 한다는 것입니다.
      2) JSP 페이지에서 이 라이브러리의 어떤 태그를 사용할 것인지 선언
         해야 합니다.
         - <%@ taglib %> 태그를 사용하여 라이브러리 정보를 선언해야
           쓸 수 있습니다.
           ex) <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 

   - JSTL에서 제공하는 주요 라이브러리


EL (Expression Language)
   - 보관소에서 값을 꺼낼 때 사용하는 문법입니다.
   - OGNL(Object Graph Navigation Language) 형식을 값이 들어있는
     객체의 경로로 지정합니다. 
     예) pageScope.member.name
   - EL에서 사용할 수 있는 기본 객체
     pageContext : pageContext 객체
     servletContext : servletContext 객체. 
      ex) ${pageContext.servletContext.객체명}
     session: HttpSession 객체 
      ex) ${pageContext.session.프로퍼티명}
     request: ServletRequest 객체
      ex) ${pageContext.request.프로퍼티명}
     response: ServletResponse 객체
     param: 요청 파라미터 값 조회 
      ex) ${param.파라미터명}
     paramValues: 요청 파라미터 값의 배열 조회
      ex) ${paramValues.파라미터명}
     header: HTTP 헤더 값 조회
      ex) ${header.헤더명}
     headerValues: HTTP 헤더 값의 배열을 조회
      ex) ${headerValues.헤더명}
     cookie: 쿠키 값 조회
      ex) ${cookie.쿠키명}
     pageScope: PageContext 객체
      ex) ${pageScope.프로퍼티명}
     requestScope: ServletRequest 보관소
     ex) ${requestScope.프로퍼티명}
         => ${request.servletContext} == request.getServletContext();
         => ${requestScope.servletContext} == request.getAttribute("servletContext");
     sessionScope: HttpSession 보관소
     ex) ${sessionScope.프로퍼티명}
         => ${session.creationTime} == session.getCreationTime();
         => ${sessionScope.creationTime} == session.getAttribute("creation Time");
     applicationScope: ServletContext 보관소
     ex) ${applicationScope.프로퍼티명}


JSP 주석


블로그 이미지

필로그래머

,

■ 서블릿 생명주기 메소드 종류 



init()

- 딱 한 번만 호출됩니다.

- 서블릿 컨테이너가 서블릿 객체를 생성한 후 호출합니다.

- 서블릿이 작업하는데 필요한 자원을 준비시키는 코드를 넣습니다.


destroy()

- 딱 한 번만 호출됩니다.

- 웹 어플리케이션의 실행이 멈출 때,

  서블릿이 사용한 자원을 초기화시킬 수 있도록 이 메서드를 호출합니다.

- 서블릿이 사용한 자원을 초기화 시키는 코드를 넣습니다.


service()

- 해당 서블릿에 대해 요청이 들어올 때마다 호출됩니다.

- 클라이언트가 요청한 작업을 처리하는 코드를 넣습니다.



──━━━

# 참고! : servlet-api 설정하기


▶ servlet-api 라이브러리는 서블릿 컨테이너에 포함되어 있습니다.

    따라서 $tmp/wtpwebapps/웹프로젝트명/WEB-INF/lib 폴더에 배치할 필요가 

    없습니다. 단지 서블릿을 만들 때 컴파일 단계에서만 사용하면 됩니다.



만약 특정 라이브러리 정보를 배치에서 제외하고 싶다면?


▶ build.gradle 파일의 dependencies {} 블록에 라이브러리 정보를 등록할 때, 

    'complie' 명령 대신 'providedCompile' 명령을 사용하면 됩니다.




ex) providedCompile 예제!


dependencies {

//complie: 빌드할 때도 사용하고, 배치에도 포함시킨다.

compile group: 'com.google.code.gson', name: 'gson', version: '2.8.0'

compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.42'


//providedCompile: 빌드할 때만 사용한다. 배치에는 제외시킨다.

providedCompile group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'

}




■ javax.servlet.Servlet 인터페이스, Servlet이란?



▶ 서블릿 컨테이너가 클라이언트 요청을 처리하기 위해 

    객체에 대해 호출하는 메서드의 규칙!


▶ 클라이언트 요청을 처리하는 클래슬르 만들 때는

    반드시 이 규칙에 따라 만들어야 합니다. 


▶ 이 규칙에 따라 만든 클래스를 '서블릿(Servlet)'이라고 부릅니다.

블로그 이미지

필로그래머

,

[Java] 자바 이클립스 서블릿 (Servlet) 만들기


서블릿 만들기


 1) 서블릿을 만드는 데 필요한 라이브러리를 가져온다.

- mvnrepository.com 에서 'servlet-api'를 검색한다.

- 3.1.x 버전의 gradle 라이브러리 정보를 복사한다.



- 프로젝트 폴더에 있는 build.gradle 파일의 dependencies {} 블록에 추가한다.





- 터미널(명령창)에서 'gradle eclipse'를 실행하여 

  이클립스 설정 파일 (.classpath, .project)을 갱신한다.




- 이클립스 설정 파일을 갱신하였다면, 프로젝트를 'Refresh(F5)' 해야 한다.



2) javax.servlet.Servlet 규칙에 따라 클래스를 작성해본다.


임의의 HelloServlet 클래스 예제


import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloServlet implements Servlet {
 
  public HelloServlet() {
    System.out.println("HelloServlet()");
  }
 
  @Override
  public void init(ServletConfig config) throws ServletException {
    System.out.println("init()");
  }
  @Override
  public ServletConfig getServletConfig() {
    System.out.println("getServletConfig()");
    return null;
  }
  @Override
  public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    System.out.println("service()");

res.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = res.getWriter();
    out.println("Hello, world");
   
  }
  @Override
  public String getServletInfo() {
    System.out.println("getServletInfo()");
    return null;
  }
  @Override
  public void destroy() {
    System.out.println("destroy()");
   
  }
}




서블릿 배포하기


 1) 톰캣 서버에 웹 애플리케이션 폴더를 만든다.

=> $톰캣홈/webapps/만들고싶은폴더명/

 2) 클래스 파일을 배치한다.

=> $톰캣홈/webapps/만든폴더명/WEB-INF/classes/폴더명/HelloServlet.class

 3) 서블릿 정보를 DD 파일에 등록한다.

=> $톰캣홈/webapps/ROOT/WEB-INF/web.xml 파일을 복사한다.

=> $톰캣홈/webapps/만들었던폴더명/WEB-INF/ 아래에 위에서 복사한 파일을 옮긴 후 이클립스로 다음과 같이 파일을 편집한다.


----------------------------------------------------------------------------------------

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee

                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"

  version="3.1"

  metadata-complete="true">


  <display-name>Welcome to Tomcat</display-name>

  <description>

     Welcome to Tomcat

  </description>

  

  <!-- 서블릿의 클래스 정보를 등록한다. -->

  <servlet>

    <servlet-name>hello</servlet-name> <!-- 서블릿 클래스 별명 -->

    <servlet-class>step24.HelloServlet</servlet-class> <!-- 서블렛 경로 설정 -->

  </servlet>

  

  <!-- HelloServlet에 URL을 부여한다. -->

  <servlet-mapping>

    <servlet-name>hello</servlet-name>

    <url-pattern>/hi</url-pattern> <!-- 반드시 /로 시작해야 한다. -->

  </servlet-mapping>

</web-app>       

----------------------------------------------------------------------------------------


  4) C:\apache-tomcat-8.5.11\bin 경로에서 startup.bat 파일을 실행시켜 톰캣을 켠다.

  5) 웹브라우저를 켜고 url 주소에 "http://www.localhost:8080/test/hi" 를 입력한다.
  6) 화면 창에 out.println("Hello, world"); 결과가 뜬 것을 확인한다.

 맥에서 설정 정보 바꿔주기
     bin./logs 
     > cat catalina.out            : 서블릿 생성자가 호출될 때 메서드를 실행시켜준다.
     > tail -f catalina.out    : 웹브라우저로부터의 요청 정보가 바뀔 때마다 
  위 메서드를 지속적으로 호출시켜줄 수 있도록 설정한다.







블로그 이미지

필로그래머

,