JSP + Servlet | 서블릿의 기초

파과·2022년 7월 12일
0

JSP + Servlet

목록 보기
2/33
post-custom-banner

프로젝트 - New - Servlet 생성

서블릿 클래스

URL Mapping

서블릿 동작을 위해 실제 자바 클래스 이름 대신에 사용.
실제 서블릿 클래스를 공개하지 않기 위해서 사용한다.
항목 선택 후 Edit - Pattern: 입력란에 패턴명(/hello)입력

get방식으로 요청할 경우 doGet만 체크하고 Finish

톰캣 서버의 server.xml파일의 context태그를 사용해 컨텍스트 패스를 추가할 수 있다.

<Context docBase="web-study-02" path="/web-study-02"
	reloadable="true" source="org.eclipse.jst.jee.server:web-study-02" />

Annotation 어노테이션

xml파일을 직접 열어서 환경설정할 필요 없이 주석 형태로 자바 코드에서 환경설정할 수 있도록 함.

서블릿 클래스 정의

  • HttpServlet 클래스 상속받기
  • 브라우저를 통해 외부에서 실행되기 때문에 접근제한자는 반드시 public.

요청 메소드

doGet과 doPost는 모두 HttpServlet클래스의 메소드를 오버라이딩해 사용하는 것이다.

응답 객체에 콘텐트 타입 지정

setContentType()으로 클라이언트에게 응답할 페이지를 환경 설정.

참고
일반적으로 자바클래스는 main메소드가 있는 클래스에서 객체를 생성해 실행하지만, 서블릿은 웹서버가 실행해주는 방식이다.

한글 입력시 인코딩

response.setContentType("text/html;charset=UTF-8");

출력 스트림 얻어오기

반드시 위 setContentType 코드 실행 후 실행해야 한다.

PrintWriter out = response.getWriter();

클라이언트에게 출력하기 위해 HTML태그 형태로 만들어서 보낸다.


출력 스트림 닫기.

out.close();


서블릿 동작 원리

  1. 브라우저에서 서블릿 요청
  2. WAS(Web Application Server) 안의 웹 서버가 서블릿 요청을 인식하여 서블릿 컨테이너에게 서블릿을 수행하도록 넘겨줌
  3. 서블릿이 스레드를 기동하여 해당 서블릿 객체를 생성하고 이를 수행함
  4. 서블릿 객체의 작업이 종료되면 기동되었던 스레드가 종료됨.
  5. 서블릿 수행 결과가 웹 서버에 전송됨
  6. 이를 클라이언트에게 전송

참고 - WAS와 웹 서버
WAS는 웹 서버와 웹 컨테이너가 합쳐진 형태로, 웹 서버가 단독으로 처리할 수 없는 동적 컨텐츠를 제공한다.

서블릿의 라이프 사이클

다른 웹 기술(PHP, ASP등)들은 클라이언트의 요청이 있을 때마다 작업을 새롭게 시작하지만, 서블릿은 그렇지 않다.

처음 요청을 받으면 서블릿 객체(Instance)가 생성되면서 init()메소드가 최초로 단 한번만! 호출된다. 여기서는 주로 초기화 작업을 한다. 그 후 클라이언트 요청이 있을 때 doGet()혹은 doPost() 요청이 실행된다. 여러 클라이언트가 동시에 요청해도 스레드가 생성되어 동시에 실행되므로 수행속도가 빠르다.
서블릿이 더 이상 서비스를 하지 않을 경우 destroy()메소드가 호출되어 자원이 해제된다. 이는 서블릿 컨테이너 종료(톰캣 재가동) 또는 서블릿 내용 수정으로 다시 컴파일해 클래스 파일이 바뀌는 경우이다.




서블릿의 데이터 통신

get방식과 post방식

폼에 입력된 데이터를 서블릿 컨테이너가 받아와서 처리하는 서블릿 프로그램을 작성해 보자.

<form method="get/post" action="호출할 서블릿">
  • get은 사용자가 입력한 결과를 알 수 있도록 그 내용을 공개한다.

  • post는 사용자가 입력한 내용을 발송할 때 그 내용을 공개하지 않는다.

  • submit버튼을 누르면 action속성으로 기술한 URL에 지정된 파일로 이동한다.

get과 post 전송 방식의 폼과 서블릿 테스트

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>

	<form method="get" action="MethodServlet">
		<input type="submit" value="get 방식으로 호출하기">
	</form>
	<br><br>
	<form method="post" action="MethodServlet">
		<input type="submit" value="post 방식으로 호출하기">
	</form>

</body>
</html>

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;

@WebServlet("/MethodServlet")
public class MethodServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.print("<h1>get 방식으로 처리됨</h1>");
		out.close();
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.print("<h1>post 방식으로 처리됨</h1>");
		out.close();
	}

}



쿼리 스트링

서버에서 클라이언트(사용자)가 입력한 값을 얻어오기 위해서는 쿼리 스트링을 사용해야 한다.
이는 사용자가 입력한 데이터를 서버로 전달하는 가장 단순한 방법으로, get방식으로 요청했을 때 URL주소 뒤에 입력 데이터를 함께 제공한다.

리소스?이름1=값1&이름2=값2의 형식을 취한다.

왜 데이터를 쿼리 스트링으로 전송할까?

웹 프로그램에서는 현재 페이지의 정보를 바로 다음 페이지에서 전혀 알 수 없다. 페이지가 이동하면 이전 페이지의 값들은 모두 잃게 된다. 하지만 프로그램을 만들다 보면 페이지 사이에 정보교환이 필요한 경우가 있는데, 이를 위해 웹 프로그래밍에서 제공하는 것이 쿼리 스트링이다.

  • 공백은 +, 한글은 %기호와 함께 16진수로 변환되어 전달.
  • form의 name속성에 이름을 정해주고 구분 가능하게 한다. 여러 name=value는 &로 구분된다.

요청 객체(request)와 파라미터 관련 메소드(getParameter)

폼 태그 (안의 input 태그)에 기술한 name값을 getParameter()의 매개변수로 넣는다.

사용자가 name="id"인 input태그에 "pinksung"이란 아이디를 적는다면,
String id=req.getParameter("id");에서 name값을 통해 pinksung이란 값을 가져와 id변수에 저장하게 된다.

getParameter()는 파라미터를 항상 문자열로만 얻어온다. 따라서 숫자형식일 경우 받은 값을 Integer.parseInt()로 변환한다.

참고: Servlet API
🔗 Servlet API(Tomcat 8.0)

텍스트 박스에 입력된 값 얻어오기

  • param.jsp : 아이디와 나이 입력받는 폼. submit 버튼 클릭시 입력된 값이 서블릿으로 전송되고, 값을 서블릿에서 받아 처리한다.
  • ParamServlet.java : 입력받은 값을 처리하는 서블릿 클래스. 하이퍼링크 "다시" 클릭시 HTML문서로 되돌아가서 새로운 데이터를 입력받는다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>서블릿</title>
</head>
<body>

	<form method="get" action="ParamServlet">
		아이디:			 <input type="text" name="id"><br>&nbsp;: <input type="text" name="age"><br>
		<input type="submit" value="전송">
	</form>
</body>
</html>

전송 버튼 클릭시 ParamServlet 서블릿이 get방식으로 요청된다.

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;

@WebServlet("/ParamServlet")
public class ParamServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html;charset=EUC-KR");
		
		//name이 id인 태그의 입력값을 읽어와 id변수에 저장.
		String id=request.getParameter("id");
		int age = Integer.parseInt(request.getParameter("age"));
		
		PrintWriter out = response.getWriter();
		out.print("<html><body>");
		out.println("당신이 입력한 정보입니다. <br>");
		out.println("아 이 디: ");
		out.println(id);
		out.println("<br>나이: ");
		out.println(age);
				
        
        //자바스크립트로 이전페이지로 이동하는 링크를 만들어줌
        out.println("<br><a href='javascript:history.go(-1)'>다시</a>");
		out.print("</body></html>");
		out.close();
		
	}

}

이대로 입력값 없이 제출하면 HTTP Status 500에러가 발생한다. 이는 나이를 정수형으로 변환하기 때문인데, 공백문자를 정수형태로 변환하려고 하면 예외가 발생하기 때문이다.

유효성 체크

유효성 체크 작업은 HTML이나 JSP로는 불가능하고 자바스크립트로만 가능하다.
param.jsp의 폼에 입력된 정보가 올바른지 판단하는 자바스크립트 파일 param.js를 만들어 HTML문서에 포함시켜 사용해보자.

File - New - JavaScript Source File 생성

function check(){
	if(document.frm.id.value == ""){
		alert("아이디를 입력해주세요");
		document.frm.id.focus();
		return false;
	}else if(document.frm.age.value == ""){
		alert("나이를 입력해주세요");
		document.frm.age.focus();
		return false;
	}else if(isNaN(document.frm.age.value)){
		alert("숫자로 입력해주세요");
		document.frm.age.focus();
		return false;
	}else{
		return true;
	}
}

jsp파일에 아래 코드로 param.js파일 포함시키기

<script type="text/javascript" src="param.js"></script>

출력이 아닌 입력 폼에서 한글 깨지는 것 방지

POST방식으로 한글 읽기

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>
	<h3>get방식에서 한글 깨짐 방지</h3>
	<form method="get" action="InfoServlet">
		이름: <input type="text" name="name"><br>
		주소: <input type="text" name="addr"><br>
		<input type="submit" value="전송">
	</form>
	
	<h3>post방식에서 한글 깨짐 방지</h3>
	<form method="post" action="InfoServlet">
		이름: <input type="text" name="name"><br>
		주소: <input type="text" name="addr"><br>
		<input type="submit" value="전송">
	</form>
</body>
</html>

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;

@WebServlet("/InfoServlet")
public class InfoServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		response.setContentType("text/html;charset=UTF-8");
		String name = request.getParameter("name");
		String addr = request.getParameter("addr");
		
		PrintWriter out = response.getWriter();
		out.print("<html><body>");
		out.println("당신이 입력한 정보입니다.<br>");
		out.println(name);
		out.println(addr);
		
		out.println("<br><a href='javascript:history.go(-1)'>다시</a>");
		out.print("</body></html>");
		out.close();
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

get방식은 잘 나오고 post방식은 깨져서 나옴.
아래 코드를 doPost()의 맨 윗줄에 추가해야 한다.

request.setCharacterEncoding("UTF-8");
post-custom-banner

0개의 댓글