20211123 서블릿, JSP

DUUUPPAAN·2021년 11월 23일
0

20211122 WAS(TOMCAT), JSP

목록 보기
2/10

·어제 수업의 설명

-먼저 어제 진행했던 localhost:8088을 쳤을 때,(8080으로 해야하지만, 오라클때문에 8088로 설정하셨다.) c\windows\system32\drivers\etc\hosts를 읽어온다. 그 후에, 8088포트 번호를 찾아(톰캣을 8088로 설정했다.) 톰캣으로 가서, conf폴더에 server.xml을 읽어온다. 여기서 host이름이 localhost면 appBase로 들어가야 하는데, 해당 부분을 어제 ""처리해줬기 때문에, 환경설정으로 만들어놓은 CATALINA 폴더의 localhost인 폴더의 ROOT.xml파일을 찾아간다. 그러면 해당 파일에 설정해놓은 경로인 docBase의 경로를 찾아가게 된다. 그리고 다시 톰캣의 conf폴더에서 web.xml에 있는 호출될 파일을 뿌려준다. 나의 경우 웰컴파일로 되어있는 index.jsp 파일이 localhost:8088의 브라우저 링크에 띄워진다.

·웹 서버와 WAS

-웹 서버는 기본적으로 html, 이미지, 동영상 등을 클라이언트인 웹브라우저의 요청에 의해서 보여주는 역할을 한다. 정적이며 WAS를 거치지 않고 바로 클라이언트에게 요청한 사항을 전달해 줄 수 있다. 여기서 만약, 클라이언트의 요청이 동적이라면, 예를 들면, JSP나 Servlet에 대한 부분을 요청한다면, 해당 부분을 WAS에게 넘기고, WAS에서 응답한 부분을 다시 클라이언트에게 넘겨준다.
-WAS는 동적인 로직이나, DB에 접속해서 데이터를 읽어오는 등의 기능을 할 수 있는 서버라고 보면 된다. 지금 내가 듣는 수업 기준으로는 오라클의 데이터를 읽어오거나 자바의 로직을 이용해서 뭔가를 처리하거나 하는 등의 기능을 수행할 수 있다. 단, 이 때, WAS에는 웹 컨테이너가 존재하고, 이 컨테이너가 각각의 서블릿을 쓰레드를 통해 호출한다. 이때, 서블릿을 호출할 때는, init()메소드를 반드시 한번 호출하고, 그 다음 service()메소드를 통해 요청 방식이 get인지 post인지 여부를 확인하고 다시 해당 메소드를 호출한 후, 결과를 넘긴다. 그렇다면 WAS는 웹서버의 역할을 할 수 없나? 그것은 아니다! WAS도 웹서버처럼 정적인 컨텐츠를 제공할 수 있다. 다만, 동시접속에 의한 업무 분배를 통해 더 효율적으로 요청에 대한 응답을 할 수 있도록 나눠있다고 보는 것이 좋다.

-서블릿 서블릿, 계속 얘기하는데, 서블릿이란 자바를 사용해서 웹을 만들기 위해 필요한 기술이며, 동적인 페이지를 구성할 수 있다. 또한, 자바의 장점인 운영체제와 하드웨어의 영향을 받지 않는 것을 그대로 갖추고 있다. 단, 화면에 표현될 html코드를 프로그램적으로 작성해야하고, 서비스 하기 전에 반드시 컴파일 해야 한다는 단점도 존재한다.

서블릿의 실행방법: 서블릿 클래스 정보에 따라 서버에 매핑된 uri정보에 따라 실행하며, 컨테이너에 적재된 상태에서 처리한다.
특징, 웹서버와 병행하는 것이 권장된다. 기본적인 웹 기능이 있지만, 성능이 떨어지거나 느리기 때문이다.

서블릿은 개발자가 소스 작성-> 컴파일->컨테이너에 배치-> 컨테이너에 의해 실행 관리
->사용자 요천에 따라 스레드 단위로 실행->데이터베이스 연동 등 필요한 작업 수행
->처리 결과를 사용자에게 html 형식으로 전달하는 구조로 동작.

서블릿은 버튼을 누르면 시작되고, 처리를 마치면 종료되는 구조가 아니다.
서버에서 컨테이너에 의해 실행되면서 생명주기를 가지고 특정 이벤트와 상태가 존재하는 구조이다.

init()메소드는 서블릿 실행시 한번만 실행되는 메서드
service() 사용자 요청시 매번 호출되는 메소드
destroy()는 서블릿 종료 시 실행
  1. 컨테이너 ->서블릿 클래스 로딩
  2. 서블릿 클래스 .class -> 서블릿 인스턴스 생성, 서블릿 생성자가 호출
  3. init() 인스턴스->서블릿 클래스에서 단 한번만 실행되는 메서드, 초기화 작업을 수행
  4. service() 스레드 사용자 요청을 처리, 사용자 요천에 따라 service메서드가 반복 호출

서블릿 개발이 되려면, 특정 클래스를 상속받아야만 구현할 수 있는 구조이다.
서블릿은 javax.servlet.HttpServlet 클래스를 상속해서 구현한다. 예를 들면, get방식의 request가 오면, 어떻게 처리할 지에 대한 서블릿을 구현하려면, 우선 javax.servlet.HttpServlet이 클래스를 상속받고 doGet()이라는 메소드를 오버라이딩하여 사용해야 한다.

HelloWorld서블릿 작성

package com.icia.web.servlet;

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 HelloWorld
 */
@WebServlet("/HelloWorld")
public class HelloWorld extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public HelloWorld() {
        super(); //자식 클래스가 다 사용할 수 있는데, 생성자는 호출해줘야 함.
        		//부모의 생성자를 호출하지 않으면, 부모의 메서드들은 사용할 수 없음.
        
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
    //거의 보통 request와 response는 같이 다님.
    //response는 클라이언트한테 보낼 것. setContentType은 text고 html형태고, 문자형은 utf-8이란 것을 알려주는 것.
    //브라우저가 해석하기 용의하게 해주는 것.
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.setContentType("text/html;charset=utf-8");
		//response는 응답에 대한 객체를 만들어 주는 것,
		//request 는 서버에서 요청했을 때 header정보.
		PrintWriter out = response.getWriter();
		//앞이 부모고, 뒤의 response.getWriter()가 자식임.
		out.println("<html>"+
					"<head>"+
					"<title>Servlet Test</title>"+
					"Servlet Test"+
					"</head>"+
					"<body>" +
					"<h1>서블릿 간단한 작성 예제 입니다.</h1>"+
					"</body>"+
					"</html>"
					);
		
	}
	
//C:\project\webapps\localhost\src\main\webapp\WEB-INF\classes\com\icia\web\servlet 경로

	/**
	 * @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);
		//보통 구현을 get에서 하고 doPost는 doGet을 호출하게 하는 방식으로 작성함.
	}
}

단, 이때, 반드시 톰캣의 conf파일에 있는 web.xml에 해당 서블릿을 매핑시켜줘야 한다.

	<!-- 컨테이너에 .java 등록, 경로 찍어주기. -->
	<servlet>
	<servlet-name>HelloWorld</servlet-name>
	<servlet-class>com.icia.web.servlet.HelloWorld</servlet-class>
	</servlet>
	
	<!-- 서블릿 매핑 -->
	<servlet-mapping>
		<servlet-name>HelloWorld</servlet-name>
		<!-- url 맵핑. -->
		<url-pattern>/HelloWorld</url-pattern>
	</servlet-mapping>

위의 과정을 거쳐야 비로소 localhost:8088/HelloWorld를 찍었을 때 위의 서블릿을 호출할 수 있게 된다.

·JSP

-기본적으로 servlet의 불편한 점을 보완하기 위해서 나온 것이 JSP라고 보면 된다. 서블릿은 기본적으로 java기반이여서 html을 화면에 보여주려면 굉장히 까다로웠고, css나 자바 스크립트를 적용하기가 힘들었다. 반면에 JSP는 html 기반에 java언어를 사용할 수 있게 되어있는 구조여서 html에서 자바의 모든 기능을 사용할 수 있었다.

-간단하게 자바의 문법을 사용한 test JSP를 만들어보았다

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%
		int i = 0;
		while(true)
		{
			out.println(i+"번째 줄 ");
			i++;
	%>
	<br>=================<br>
	<%
			if(i > 5) {break;}
		}
		//http://localhost:8088/test.jsp 이렇게 하면 브라우저에서 볼 수 있음.
	%>
</body>
</html>

여기서 눈여겨 볼 점은, 바로 반복문을 <% %>태그로 둘로 나누고 중간에 html태그를 써서 반복문 안에 넣을 수 있다는 것이다.

-JSP에서 자바를 사용하는 사용법은 다음과 같다

지시자: 자바의 임포트라고 보면 됨. <%@ %> 페이지 속성 지정
주석: <%-- --%>
변수 메소드 선언: <%! %>
변수 값 : <%= %>
스크립트릿: <% %>

·JSP 실습

-카페 메뉴들을 radio로 만들고, 수량과 지불 금액을 넣으면 해당 주문한 메뉴와 개당 금액, 총금액 등등이 출력되는 order.jsp와 result.jsp를 만들었다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>커피주문</title>
</head>
<body>
	<h1>커피메뉴</h1>
	<form action="result.jsp"><!-- 메소드 명시하지 않았기 때문에 get방식 -->
	<input type="radio" name="coffee" value="1">아메리카노(3000원)<br>
	<input type="radio" name="coffee" value="2">카페라떼(3300원)<br>
	<input type="radio" name="coffee" value="3">에스프레소(2500원)<br>
	<input type="radio" name="coffee" value="4">얼그레이티(3500원)<br>
	수량: <input type="text" name="su" size="3"><br>
	지불액: <input type="text" name="money" size="10">
	<input type="submit" value="주문처리">
	</form>			
</body>
</html>

-여기서 form 태그에 따로 method=무엇을 주지 않았기 때문에, 기본 default값인 get방식으로 요청한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
	int coffee = Integer.parseInt(request.getParameter("coffee"));
	//커피라는 이름으로 받을건데, 해당 부분이 String이니까 int형으로 변환시켜야됨.
	//웹에서 넘어오면 전부 문자로 넘어옴.
	
	int su = Integer.parseInt(request.getParameter("su"));
	int money = Integer.parseInt(request.getParameter("money"));
	
	String menu = ""; //메뉴명을 받을 변수
	int dan = 0; //개당 가격
	int total = 0; //총 금액
	int change = 0; //거스름돈
	
	if( coffee == 1)
	{
		menu = "아메리카노";
		dan = 3000;
	}else if(coffee == 2)
	{
		menu = "카페라떼";
		dan = 3300;
	}else if(coffee == 3)
	{
		menu = "에스프레소";
		dan = 2500;
	}else if(coffee == 4)
	{
		menu ="얼그레이티";
		dan = 3500;
	}
	
	//총금액
	total = dan * su;	
	//거스름돈
	change = money - total;

%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>커피주문 내역</title>
</head>
<body>
	<h2>주문계산 내역</h2>
	<ul>
		<li>커피 종류 : <%= menu %></li>
		<li>개당 가격 : <%= dan %></li>
		<li>주문 수량 : <%= su %></li>
		<li> 총 금액 : <%= total %></li>
		<li>  지불액 : <%= money %></li>
		<li> 거스름돈 : <%= change %></li>
	</ul>	
</body>
</html>

-여기서 request는 HttpServletrequest 객체의 인스턴스로 .getParameter()메소드를 통해 http 요청 파라미터의 값을 구할 수 있다. 단, 해당 메소드의 리턴타입은 String이기 때문에 Integer.parseInt()로 형변환을 해준다. 이렇게하면, order.jsp에서 값들을 넣은 후에, 버튼을 눌러 submit하면 result.jsp에 원하는 값이 출력된다. 단, 만약 지불 가격보다 상품가격이 높다면, 마이너스로 표기되는 것이 굉장히 보기 싫었다. 그래서 나는 추가적으로 각각 상황에 따라서 출력이 되도록 조금 추가해봤다. 물론, 나중에는 수량이나 가격에 아무것도 입력되지 않으면 예외처리를 하는 것도 추가해봐야겠지만 오늘은 여기까지다!

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%
	int coffee = Integer.parseInt(request.getParameter("coffee"));
	//커피라는 이름으로 받을건데, 해당 부분이 String이니까 int형으로 변환시켜야됨.
	//웹에서 넘어오면 전부 문자로 넘어옴.
	
	int su = Integer.parseInt(request.getParameter("su"));
	int money = Integer.parseInt(request.getParameter("money"));
	
	String menu = ""; //메뉴명을 받을 변수
	int dan = 0; //개당 가격
	int total = 0; //총 금액
	int change = 0; //거스름돈
	int less = 0; //부족한 금액에 대한 변수
	
	int swch = 0; //상황별 스위치 변수: 1:낸 금액이 더 많은 경우 0:지불금액이 부족한 경우.
	
	if( coffee == 1)
	{
		menu = "아메리카노";
		dan = 3000;
	}else if(coffee == 2)
	{
		menu = "카페라떼";
		dan = 3300;
	}else if(coffee == 3)
	{
		menu = "에스프레소";
		dan = 2500;
	}else if(coffee == 4)
	{
		menu ="얼그레이티";
		dan = 3500;
	}
	
	//총금액
	total = dan * su;	
	//거스름돈
	if(total > money)
	{
		less = total - money;
		swch = 0;
	}else
	{
		change = money - total;
		swch = 1;
	}
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>커피주문 내역</title>
</head>
<body>
<% if(swch == 1){ %>
	<h2>주문계산 내역</h2>
	<ul>
		<li>커피 종류 : <%= menu %></li>
		<li>개당 가격 : <%= dan %></li>
		<li>주문 수량 : <%= su %></li>
		<li> 총 금액 : <%= total %></li>
		<li>  지불액 : <%= money %></li>
		<li> 거스름돈 : <%= change %></li>
	</ul>
<%
}else if(swch == 0){
%>
<h1>금액이 <%= less %>원 부족합니다.^^</h1>
<% 
}
%>
	
</body>
</html>

-swch 변수에 각 상황에 따른 숫자 1이나 0을 넣어서 해당 값일 경우 출력을 다르게 해보았다. 아마 굉장히 많은 코딩이 있겠지만, 오늘은 이정도에서 끝내려고 한다.

·내일은 대망의 시험날

-내일은 지금까지 배웠던 여러 것들에 대한 평가를 보기로 했다. 또한 지금 교수님의 교육으로 인해 전 교수님이 오셔서 수업을 조금 진행하신다고 한다. 내일의 수업을 통해 그동안 했던 것들을 다시 복습할 수 있는 계기가 되었으면 좋겠다. 오늘은 조금 공부를 하다 자야겠다!

profile
비전공자란 이름으로 새로운 길을 가려 하는 신입

0개의 댓글