Servlet

  • 웹 클라이언트의 요청을 처리하는 클래스
  • HttpServlet을 상속하여 만들어짐
  • jsp파일 → Servlet으로 동작
  • 클라이언트의 요청을 Servlet으로 직접 받을 수 있다.
  • MVC에서 Controller 역할을 Servlet이 한다.

웹 프로젝트 생성 및 실행

웹 프로젝트 생성

이클립스 File - New - Dynamic Web Project

 

MyWeb이라는 Dynamic Web Project를 생성했다.

프로젝트가 생성되면 다음과 같은 폴더 구조가 만들어진다. 이 중에서 src/main/java라는 소스 폴더와 src/main/webapp이라는 일반 폴더를 눈여겨보자.

  • src/main/java: 소스 폴더 → 서블릿을 비롯한 일반적인 자바 클래스 파일 작성
  • src/main/webapp: 일반 폴더 → HTML, 이미지, CSS, 자바스크립트, JSP파일 작성

 

웹 콘텐츠 작성 및 테스트

웹 애플리케이션의 두 가지 형태의 파일

  1. 정적인 파일 (HTML, 이미지 등)
  2. 동적인 파일 (JSP 등)

대표적인 정적 콘텐츠인 HTML 파일을 작성하고 실행해보자. src/main/webapp 폴더에 index.html 파일을 작성한다.

 

[index.html]

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

</head>

<body>

<h1>Hello MyWeb</h1>

<h2>안녕 MyWeb</h2>

<hr color="red">

<ul>

    <li><a href="hi">Get방식 요청-HelloServlet</a></li>

    <li><a href="form.html">POST방식 요청 - form을 통해 요청보내기</a></li>

    <li><a href="member/join.html">회원가입 페이지 이동</a></li>

    <li><a href="member/mypage.html">회원정보 관리 페이지 이동</a></li>

    <li><a href="MemberList">회원목록 페이지 이동</a></li>

</ul>

</body>

</html>

 

실행 결과


1. Get방식 요청-HelloServlet

<li><a href="hi">Get방식 요청-HelloServlet</a></li>

 

src/main/java 소스 폴더에 my라는 하위 폴더를 만들고, 그 안에 또 com이라는 하위 폴더를 만든 뒤, HelloServlet.java 파일을 만들자.

HelloServlet.java

 

서블릿 작성

  1. Servlet이 되기 위해서는 HttpServlet을 상속받는 클래스를 작성해야 한다. (extends HttpServlet)
  2. 메서드 오버라이드
    doGet(), doPost(), doDelete(), doPut(), ...
  3. 작성한 서블릿을 등록한다. <두 가지 방법>
    1. "컨텍스트/WEB-INF/web.xml"에 등록
    2. 어노테이션을 이용해 등록: 매번 web.xml 파일에 서블릿을 등록하는 것이 귀찮으면 @WebServlet을 사용해서 간단하게 매핑해도 된다.

[HelloServlet.java]

 

XML 설정

web.xml은 <web-app>을 루트 엘리먼트로 가지고 있으며, <web-app>에는 디폴트 네임페이스로http://xmlns.jcp.org/xml/ns/javaee가 선언되어 있다.

 

[web.xml]

  • <display-name>은 생략이 가능하며 웹 애플리케이션의 이름을 지정한다.
  • <welcome-file-list>에 <welcome-file>로 등록된 파일은 웹 애플리케이션의 웰컴 파일이 된다. 웰컴 파일은 사용자가 시스템에 접근할 때 시스템이 가장 먼저 제공하는 파일로서 요청 url에 굳이 명시하지 않아도 서버가 자동으로 인식한다.
  • <servlet>은 작성된 서블릿 클래스를 등록할 때 사용하며, <servlet-name>과 <servlet-class>를 자식 엘리먼트로 사용한다.
    • <servlet-name>은 생성된 서블릿 객체에 별칭을 부여하는 것으로, 서블릿 컨테이너는 <servlet-name>으로 설정된 서블릿의 이름을 기준으로 생성된 서블릿 객체들을 식별한다. 따라서 <servlet-name>은 중복을 허용하지 않는다.
    • <servlet-class>에는 서블릿의 전체 경로를 등록한다.
  • <servlet-mapping>은 브라우저의 요청 url과 서블릿을 매핑하는 설정이다.
    • <servlet-name>을 이용하여 등록된 서블릿 중 하나를 고른다.
    • <url-pattern>을 이용하여 url 형식을 지정하면 된다.

web.xml 파일을 수정하고 서버를 재구동한다. 그리고 브라우저에서 index.html화면을 새로고침한 후, Get방식 요청-HelloServlet을 클릭하면 정상적으로 HelloServlet 객체가 실행되는 것을 확인할 수 있다.

실행 결과


2. POST방식 요청 - form을 통해 요청보내기

<li><a href="form.html">POST방식 요청 - form을 통해 요청보내기</a></li>

 

src/main/webapp 소스 폴더에 form.html 파일을 만들자.

 

[form.html]

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>form.html</title>

</head>

<body>

<div>

    <h1>POST방식</h1>

    <form method="post" action="PostServlet">

        아이디: <input type="text" name="id"><br><br>

        비밀번호: <input type="password" name="pw"><br><br>

        <button>Login</button>

        <button type="reset">Reset</button>

    </form>

</div>

</body>

</html>

 

 

서블릿 작성

[PostServlet.java]

  • 이번에는 web.xml에 서블릿을 등록하는 방법 대신에 어노테이션(@WebServlet)을 사용해보자.
  • @WebServlet("/url-pattern"): [주의] url-pattern은 유니크한 값을 설정해야 한다.

PostServlet 클래스에 @WebServlet을 추가하여 "/PostServlet" 요청에 대해서 PostServlet 객체를 실행하도록 매핑했다. 서버를 재구동하고 아이디, 비밀번호를 입력해서 Login 버튼을 누르면 환영 메시지가 뜬다.

실행 결과

아이디: kim, 비밀번호: 123 입력

웹페이지 환영 메시지 / 콘솔창


3. 회원가입 페이지 이동

<li><a href="member/join.html">회원가입 페이지 이동</a></li>

 

src/main/webapp 소스 폴더 하위에 member 폴더를 만들고, 거기에 join.html 파일을 만들자.

 

[join.html]

  • <form>태그의 속성
    • name: form의 이름. 서버로 제출된 폼 데이터(form data)를 참조하기 위해 사용됨
    • method: 서버 페이지를 기술. form을 전송할 서버 쪽의 script 파일을 지정
      전송되는 서버 url 또는 html 링크
    • action: 전송 방식을 기술 (get[default], post, delete, put, options)
      • GET방식: 서버에 전달한 uri 뒤에 물음표(?)를 추가하고 키(key)=값(value) 형태로 사용자가 입력한 정보를 전달하는데, 외부에 노출되기 때문에 로그인 같은 기능에서 절대 사용해서는 안된다. 사용자가 입력한 정보가 외부에 노출돼도 상관없는 경우는 GET 방식을 사용할 수 있다.
      • POST방식: GET과 달리 쿼리 문자열이 uri가 아닌 message-body에 포함되어 전달되기 때문에 브라우저 uri에 사용자가 입력한 정보가 노출되지 않는다. 아이디, 비밀번호, 계좌번호 같은 중요한 데이터는 반드시 POST 방식으로 처리해야 한다.
  • action = "../Signup"
    • 상대경로: 지금 작업중인 파일인 join.html 파일에서 한 번 상위(밖으로) 나와 java 폴더 내의 SignupServlet으로 form을 전송
    • SignupServlet.java에 @WebServlet("/Signup")으로 전송됨

실행 결과

URL: http://localhost:9090/MyWeb/member/join.html

HTTP 요청 URL
  1. http: => 프로토콜: 서버에 파일을 요청할 때 사용한 프로토콜
  2. // => 프로토콜 구분자: 프로토콜과 호스트 이름을 구분하는 구분자
  3. localhost => 호스트(도메인): 웹 서버가 설치된 컴퓨터(호스트) → localhost는 현재 사용 중인 컴퓨터를 의미
  4. 9090 => 호스트 컴퓨터에서 9090 포트를 사용하는 서버
  5. MyWeb => 웹 애플리케이션: MyWeb 웹 애플리케이션
  6. member => 디렉터리: MyWeb 애플리케이션의 member 디렉터리
  7. join.html => 파일: member 디렉터리에 있는 join.html 파일

MyWeb - member폴더 - join.html

 

서블릿 작성

src/main/java 소스 폴더에 member라는 하위 폴더를 만들고, SignupServlet.java 파일을 만들자.

 

1. 어노테이션

[join.html]

<form name="mf" method="post" action="../Signup">

[SignupServlet.java]

@WebServlet("/Signup")

SignupServlet 클래스에 @WebServlet을 추가하여 "/Signup" 요청에 대해서 SignupServlet 객체를 실행하도록 매핑

 

2. PrintWriter out = res.getWriter();

  • Servlet에서 클라이언트의 요청(Request)에 대한 응답(Response) 형태는 문자(character) 또는 바이트(byte)가 될 수 있다.
  • 클라이언트의 요청에 문자 형태로 응답하려면 데이터의 흐름(Stream)을 컨트롤 해야 한다. 즉 텍스트(==문자) 형태로 응답을 보내도록 설정해야 한다.
  • HttpServletResponse 인터페이스의 상위 인터페이스인 ServletResponse의 getWriter() 메서드를 호출하면 스트림에 텍스트를 기록하는 것이 가능하다.
  • getWriter() 메서드를 통해 응답으로 내보낼 출력 스트림을 얻어낸 후, out.print(HTML 태그) 형태로 작성하여 스트림에 텍스트를 기록할 수 있다.

3. 요청 처리 메서드

사용자가 입력한 정보를 추출하기 위해서는 HttpServletRequest 객체가 제공하는 메서드를 사용해야 한다. 다음은 사용자 입력 정보를 추출할 때 사용하는 메서드들이다.

  • getQuertyString();
  • getParameter(String name);
  • getParameterValues(String name);

[SignupServlet.java]

 

[MemberVO.java]

package member.model;
//VO(Value Object): 값을 담는 객체,  도메인 객체 ==> MVC 중 Model에 해당
//java_member테이블
import java.sql.*;
public class MemberVO {
	
	private String id;
	private String pw;
	private String name;
	private String tel;
	private java.sql.Date indate;
	
	//기본 생성자
	public MemberVO() {
		
	}
	
	//인자 생성자
	public MemberVO(String id, String pw, String name, String tel, Date indate) {
		this.id = id;
		this.pw = pw;
		this.name = name;
		this.tel = tel;
		this.indate = indate;
	}
	
	//setter, getter
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getPw() {
		return pw;
	}

	public void setPw(String pw) {
		this.pw = pw;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public java.sql.Date getIndate() {
		return indate;
	}

	public void setIndate(java.sql.Date indate) {
		this.indate = indate;
	}
	
	
}

 

 

[MemberDAO.java]

package member.model;
import java.sql.*;
import java.util.*;
import common.db.DBUtil;
//DAO (Data Access Object): Database에 접근하여 CRUD로직을 수행하는 객체
//==> Data Layer (Persistence Layer)
//MVC 중 Model에 해당
//java_member에 INSERT
public class MemberDAO {
	
	private Connection con;
	private PreparedStatement ps;
	private ResultSet rs;
	
	/** 회원가입 처리 - C (INSERT) */
	public int insertMember(MemberVO user) throws SQLException{ //화면으로 넘기기 위해 throws
		try {
			con=DBUtil.getCon(); //드라이버 로드, 커넥션
			String sql ="INSERT INTO java_member(id, name, pw, tel, indate)";
			sql+=" VALUES(?, ?, ?, ?, SYSDATE)";
			ps = con.prepareStatement(sql);
			ps.setString(1, user.getId());
			ps.setString(2, user.getName());
			ps.setString(3, user.getPw());
			ps.setString(4, user.getTel());
			
			int n = ps.executeUpdate();
			return n;
			
		} finally {
			close(); //자원 반납
		}
	}

 

실행해보기

김재선 / kim / 123 / 123 입력
java_member 테이블에 id가 "kim"인 사람 이미 존재


강하나 / kang / 123 / 010-1111-1111 입력
java_member 12번째에 회원이 추가됨

 

 

+ Recent posts