국비교육(22-23)

26일차(2)/jsp(2) : servlet, jsp 비교

서리/Seori 2022. 11. 13. 22:51

26일차(2)/jsp(2) : Servlet, jsp 비교

 

Step01_Servlet

 

Dynamic web project 생성

- 생성시 target runtime에 Tomcat server의 버전이 지정되어 있어야 한다.

 

 

- java resources-src 폴더 안에 index.html 생성

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>index.html</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
</head>
<body>
	<div class="container">
		<h1>인덱스 페이지입니다.</h1>
		<ul>
			<li><a href="fortune">오늘의 운세 보기</a></li>
			<li><a href="fortune.jsp">오늘의 운세 보기2</a></li>
			<li><a href="friends/list">친구 목록보기</a></li>
			<li><a href="friends/list.jsp">친구 목록보기2</a></li>			
		</ul>		
	</div>
</body>
</html>

 

- bootstrap에 있는 간단한 css를 추가해주었다. → 링크

 

- 프로젝트 생성 후 프로젝트 설정을 변경하고 싶다면 우클릭-Properties

 

- Target Runtimes에서 현재 설정된 값 확인 가능!

 

(tomcat 9.0으로 바꿈. 9.0 파일을 다시 받아서 eclipse에 넣어주면 된다.)

 

- 폴더를 생성하면 기본 라이브러리 두 개가 있다. 이 안에 필요한 클래스들이 들어있다.

1) JRE System Library : java 기초 라이브러리

2) Server Runtime :서버 관련해서 작업하기 위해 필요한 라이브러리가 들어있다.(웹 프로그래밍용 클래스들)

 


 

- Java resources 폴더 안에 test.servlet 패키지 생성

 

<FortuneServlet> 클래스 생성

package test.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/fortune")
public class FortuneServlet extends HttpServlet {
	
	//생성자
	public FortuneServlet() {
		System.out.println("오잉 생성자가 호출되었네?");
	}
	
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//클라이언트에게 출력할 수 있는 객체의 참조값 얻어오기
		PrintWriter pw=response.getWriter();
		pw.println("<!doctype html>");
		pw.println("<html>");
		pw.println("<head>");
		pw.println("<meta charset=\"utf-8\">");
		pw.println("<title></title>");
		pw.println("</head>");
		pw.println("<body>");
		String[] fortuneToday={"lucky!", "soso~", "unlucky.."};
		Random ran=new Random();
		int ranNum=ran.nextInt(3);
		pw.println("<h1>"+fortuneToday[ranNum]+"</h1>");
		pw.println("</body>");
		pw.println("</html>");
		pw.close();
	}
}

 

 

 

- 우리가 만든 객체가 클라이언트가 /fortune 주소에 대한 요청을 하면 응답하도록 할 것!

 

- <a> 안에 들어가는 경로가 /로 시작하지 않으면 상대경로이다.

- 저 위치에 fortune이 들어간다!

- 앞의 프로젝트 경로를 context path 라고 한다.

 

 

- 클래스에 HttpServlet 을 상속한다.

 

- service를 입력해서 메소드를 override한다.

 

 

- 상단에 @WebServlet 추가!

- 이것을 어노테이션annotation이라고 한다. 요청이 들어왔을 때 이것으로 응답하겠다는 의미이다.

 

 

 

- getwriter 메소드를 지역변수에 담고, printwriter타입으로 받아준다.(import 필요)

 

- 다시 run 해보면 클라이언트가 호출한 페이지에 내가 만든 클래스가 연결되어 응답하는 것을 볼 수 있다.

 

- 해당 페이지의 소스를 열어보면 html 형식은 아니다. 따라서 html 형식으로 맞추어준다.

 

- 출력되는 내용을 html 형식으로 입력하면 소스에서도 이렇게 보인다.

- 맨 위에서 utf-8 형식이라고 알려주었기 때문에 한글도 오류가 발생하지 않는다.

 

- 클래스를 정해진 양식으로 만들기만 했는데, 적정 시점에 호출되어서 중요한 역할을 하고 있다!

 


 

- 객체가 생성되는지 확인하고 싶다면? 파일에 생성자를 만들어준다.

 

//생성자
public FortuneServlet() {
    System.out.println("오잉 생성자가 호출되었네?");
}

 

- 어느 시점에 생성자가 작동하는지 알고싶다면 syso 사용!

 

 

- 서버를 종료했다가 index.html 을 다시 실행하고 콘솔창을 보면 생성자는 아직 사용되지 않은 상태.
- '오늘의 운세보기' 링크를 누르는 순간 객체가 생성되는 것을 볼 수 있다.(콘솔창에 출력됨)
- /fortune 요청이 오는 순간 응답하기 위해서 생성자가 만들어지는 것!

 

- 링크를 누를 때마다 객체가 생성되지는 않는다. 하나만 생성해두고 사용한다.

 

- 메인메소드도 만들지 않았지만 필요한 시점에 객체가 생성되어 사용된다.
- 이미 어플리케이션은 만들어져 있고, 그중 일부 동작만 프로그래밍하는 것이다.
 부분 프로그래밍에 익숙해지기!


 

 

 

- html 형식으로 작성하는 것은 불편하지만, 어떤 logic을 섞을 수가 있다.

- servlet으로 만들었다면 java 프로그래밍이 들어갈 여지가 있다.

 java 배열을 만들 수도 있고, DB에서 불러와서 랜덤하게 나오도록 할 수도 있다.

 

- 상속, override, @WebServlet 은 반드시 들어가야 하지만, 

 우리가 만드는 java 객체의 기능은 마음대로 정의할 수 있기 때문에 그 안에서는 자유롭게 코딩할 수 있다.

 

 

- 여러가지 운세 내용 값이 랜덤하게 나오게 하고 싶다.

- 운세 몇 종류를 배열[ ] 에 담아놓고 배열 안의 값이 랜덤하게 출력되도록 하기!

 

package test.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

//3. 어떤 경로 요청을 처리할 것인지 경로 설정(반드시 /로 시작해야한다***)
@WebServlet("/fortune")
public class FortuneServlet extends HttpServlet {//1.HttpServlet 클래스 상속
	
	//2. service() 메소드 오버라이드
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//여기에서 원하는 내용을 응답해 준다.
		
		//응답 인코딩 설정
		resp.setCharacterEncoding("utf-8");
		//응답 컨텐트 설정
		resp.setContentType("text/html; charset=utf-8");
		//클라이언트의 웹브라우저에 문자열을 출력할수 있는 객체의 참조값 얻어내기
		PrintWriter pw = resp.getWriter();
		pw.println("<!doctype html>");
		pw.println("<html>");
		pw.println("<head>");
		pw.println("<meta charset=\"utf-8\">");
		pw.println("<title>오늘의 운세 페이지</title>");
		pw.println("</head>");
		pw.println("<body>");
		
		//오늘의 운세 5개를 미리 준비해 둔다.
		String[] fortunes={"동쪽으로 가면 귀인을 만나요", 
				"오늘은 집에만 계세요", 
				"너무 멀리가지 마세요",
				"오늘은 뭘해도 되는 날이에요",
				"로또가 당첨돼요"};
		
		Random ran=new Random();
		//0~4 사이의 랜덤한 정수 얻어내기
		int ranNum=ran.nextInt(5);
				
		pw.println("<p> 오늘의 운세: "+fortunes[ranNum]+" </p>");
		pw.println("</body>");
		pw.println("</html>");
		pw.close();//닫아주기
		
	}
}

 

- 경로는 반드시 / 로 시작해야 한다!★★★
- /로 시작하지 않으면 아예 열리지도 않는다.

- 안에 어떤 작업을 해두면 객체의 참조값(req, resp)은 알아서 전달된다.
 전달된다는 가정 하에 작성하면 된다.
- 객체의 설계도를 납품하는 느낌이라고 생각하면 된다! 적절한 시점에(호출되었을 때) 실행될 수 있도록.

- req 요청에 관련된 객체
- resp 응답에 관련된 객체

- printwriter 문자열을 출력해주는 기능을 가지는 객체
- java의 syso를 사용하면 콘솔창에 출력됐는데, printwriter는 웹서버에 요청을 한 클라이언트에게 출력된다.

- 이 메소드에 전달되는 값을 printwriter가 출력해주는 구조이다.

 

 

- run 하고 우클릭-페이지 소스보기 에서 새로고침하면

 <p> 부분의 문자만 계속 달라지는것을 볼 수 있다.

 

- 클래스로 생성한 객체가 준비작업을 하고 응답을 해준다.
 그때그때 다른 내용을 로딩하는 로직을 넣어준 것. (fortunes[ranNum])

 


 

** 같은 내용을 .jsp 로 만들어보기

 

 

- jsp 파일 생성! jsp : java server page

 

 

<fortune.jsp>

<%@page import="java.util.Random"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/fortune.jsp</title>
</head>
<body>
<%
	//오늘의 운세 5개를 미리 준비해 둔다.
	String[] fortunes={"동쪽으로 가면 귀인을 만나요", 
		"오늘은 집에만 계세요", 
		"너무 멀리가지 마세요",
		"오늘은 뭘해도 되는 날이에요",
		"로또가 당첨돼요"};

	Random ran=new Random();
	//0~4 사이의 랜덤한 정수 얻어내기
	int ranNum=ran.nextInt(5);
	
%>
	<p>오늘의 운세: <%=fortunes[ranNum]%></p>
	<p>오늘의 운세: <%out.print(fortunes[ranNum]); %></p>
</body>
</html>

 

 

- 여기서는 또 emmet이 작동하지 않는데, window-preference 들어가면 jsp에서도 작동하도록 설정할 수 있다.

- Emmet에 들어가면 emmet이 작동할 파일 확장자들이 들어있는 칸이 있는데, 여기에 .jsp 를 입력해주면 된다.

 

 

- <% %> 으로 처리된 맨 위의 한줄은 안 보이고, 나머지는 html servlet 파일과 같다.

 

 

<% %> : 자바 코딩을 할수있는 공간을 만들어준다. 이 <> 안은 java 문법의 영역!

 

 

- 이전에 작성한 java 내용을 가져오고, 필요한 부분은 import 해준다.

- <%@ @> 형태로 특이하게 import 되는것을 볼수있음

 

<p>오늘의 운세: <%=fortunes[ranNum] %> </p> 로 넣어준다.

 

 

 

- servlet과 동일하게 작동한다. jsp의 내용도 그대로 클라이언트한테 온다.

 

- Servlet은 여러 로직을 섞을 수 있지만 html 작성이 너무 번거롭다.

- jsp는 상대적으로 java 문법으로 코딩하기도 쉽고 사용이 간편하다.

 

<% %> 의 작성법을 배우는것이 jsp, 서버 프로그래밍을 배우는 것이다.

 

- jsp는 대체 뭐지? html도 아니고 java class도 아니고...

→ 모양은 이렇지만, java class로 바뀌어 작동하는 것이다.

 

\web_work\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\Step01_Servlet\org\apache\jsp

 

- 탐색기에서 위 경로로 들어가보면 두개의 파일이 있다.

- fortune.jsp 파일만 만들었는데 fortune_jsp.java 라는 java class 파일이 자동으로 생성된 것이 보인다.

 

- 클래스로 바뀌었을 때 어떤 모양을 가지는지 확인하기!

 

 

- fortune_jsp.java 파일을 열어서 비교해본 것! java 문법으로 쓰여진 일반 클래스이다.

 

- 이 클래스에서 상속하고 있는 HttpJspBase 는 HttpServlet과 비슷한 것이다.

- jsp로 만든 페이지도 결국 servlet역할으로 변환된다는 의미이다.

 

- 생성자와 필드가 있다.

 

- _jspService 메소드는 servlet의 service() 메소드와 비슷하다.

 

- 더 아래로 내려보면 jsp에서 작성한 내용을 servlet 으로 만든것과 동일하게 변환해놓은 것을 볼 수 있다!

- out 은 jsp 에서의 출력 객체. printwriter 역할을 한다.

 

- <% %>에 작성한 코드는 고스란히 클래스 안으로 옮겨진다.

- 그렇기 때문에 java 문법에 맞추어 작성해야 하는 것!

 

- <%= %> 은 더 변환되지 않고 클라이언트한테 그대로 출력된다.

 

1) <p>오늘의 운세: <%=fortunes[ranNum]%></p>
2) <p>오늘의 운세: <%out.print(fortunes[ranNum]); %></p>

- out.print를 넣어 이렇게 작성할 수도 있는데, 당연히 1번이 더 편하다...

- 클래스에서 열어보면 위와 같은 차이가 있다. 결과적으로는 같다!

 

- 딱 어떤 위치에 어떤 값(참조값)을 출력해주고 싶을 때 <%= 이라는 문법을 사용한다.

 

- 이렇게 클래스파일과 비교하면서 학습하면 jsp파일에 대한 이해도가 높아진다.

 

- 자동완성 앞의 작은 원형 L은 로컬 변수를 가리킨다.

 

- jsp페이지 영역의 <% %> 이 영역 안에서 그냥 . 찍어서 호출해 사용할 수 있는 객체들이 있다.

- 8개의 기본 객체가 들어있다. 웹프로그래밍 하는데에 필요한 객체들이 편한 개발을 위해 기본으로 들어있다.

 

- servlet 안에서는 req, resp라고 정의된 변수밖에 사용할 수 없는데,

 jsp에는 8개의 미리 정의된 변수를 사용할 수 있다.

 


 

** 친구 목록 추가하기

 

- 연결되는 페이지가 404가 아니게 하려면 무엇을 만들어야하는가?  : Servlet

 (jsp 파일은 경로의 끝이 .jsp가 되어야 한다.)

 

- /friend/list 로 된 Servlet을 만들면 된다!

 

 

<FriendServlet> 클래스 생성

package test.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/friends/list")
public class FriendServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//친구목록 (sample data)
		List<String> names=new ArrayList<>();
		names.add("바나나");
		names.add("딸기");
		names.add("복숭아");
		
		//응답 인코딩 설정
		resp.setCharacterEncoding("utf-8");
		//응답 컨텐트 설정
		resp.setContentType("text/html; charset=utf-8");
		//클라이언트의 웹브라우저에 문자열을 출력할수 있는 객체의 참조값 얻어내기
		PrintWriter pw = resp.getWriter();
		pw.println("<!doctype html>");
		pw.println("<html>");
		pw.println("<head>");
		pw.println("<meta charset=\"utf-8\">");
		pw.println("<title>친구 목록 페이지</title>");
		pw.println("</head>");
		pw.println("<body>");

		//names에 들어있는 친구 목록을 활용해서 친구 목록을 출력해 보세요.(ul, li 요소 활용)
		pw.println("<ul>");
		for(String tmp:names) {
			pw.println("<li>"+tmp+"</li>");
		}
		//for(i=0, i<names.size();, i++){
		//pw.println("<li>"+names.get(i)+"</li>")}
		pw.println("</ul>");
		
		pw.println("</body>");
		pw.println("</html>");
		pw.close();//닫아주기
	}
}

 

- <> 제너릭타입을 확인한 뒤 확장 for문으로 돌면서 list를 출력해 준다.

- 출력하면서 <li> 요소 안에 넣어주기!

 

for(타입종류 변수명:배열명){  }

 


 

같은 내용 jsp 파일로 만들기

<list.jsp>

<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<%
	//친구목록 (sample data)
	List<String> names=new ArrayList<>();
	names.add("바나나");
	names.add("딸기");
	names.add("복숭아");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>/friend/list.jsp</title>
</head>
<body>
	<ul>
	<% 
		for(String tmp:names){
			out.println("<li>"+tmp+"</li>");
		}
	%>	
	</ul>
	
	<ul>
		<% for(String tmp:names){ %>
			<li><%=tmp %></li>
		<%} %>
	</ul>
</body>
</html>

 

 

- /friends/list.jsp 이라면 friends 폴더를 만들고 그 안에 list.jsp파일 만들어주기!
- jsp는 해당 경로에 물리적으로 위치시켜주면 된다.

 

 

 

- 작성한 HTML 요소들은 out.write 로 출력된다.

- <% %> 안에 있는 내용은 그대로 옮겨준다.

- 개행, 공백기호도 인식되어 그대로 출력된다.

 

 

 

- 분리한 내용도 각각 나누어져서 출력됨!

- <%= tmp 도 그대로 그 자리에 출력된다.(out.print로 바뀌어서)

 


 

- jsp 페이지로 만든 홈페이지는 홈페이지 주소에서도 발견된다.

 

- 웹페이지에 업로드되는 내용이 기본 틀은 같지만 상세내용은 조금씩 달라지기 때문에,

 DB에서 읽어와 정보를 수정할 수 있도록 jsp 페이지로 만드는 경우가 많다.

 

 


 

 

참고) eclipse 템플릿 만들기

 

 

- Windows-Preferences-Templates-New에서 저장해두면

 

- 작성할 때 저장한 템플릿의 이름만 입력하면 템플릿을 불러와 쓸 수 있다.