사용자에게 회원정보를 입력받아 처리페이지(join.itwill)를 POST 방식으로 요청하여 입력값을 전달하는 HTML 문서 생성 (입력페이지 역할)
→ form 태그를 이용하여 서블릿을 POST 방식으로 요청한 경우 사용자 입력값을 리퀘스트 메시지 몸체부(Body)에 저장하여 전달한다.
form 태그 ★
form 태그는 웹프로그램을 요청할 때 사용자로부터 입력받은 값을 전달하기 위한 태그이다.
action 속성 : form 태그를 사용하여 요청할 웹프로그램의 URL 주소를 속성값으로 설정
→ action 속성을 생략한 경우 현재 브라우저의 요청 URL 주소의 웹프로그램을 요청한다.
method 속성 : 웹프로그램 요청방식(GET or POST)을 속성값으로 설정
→ method 속성을 생략한 경우 웹프로그램은 GET 방식으로 요청한다.
GET : 입력값을 URL 주소의 질의문자열(QueryString)로 변환하여 전달한다.
→ 소용량의 보안이 필요없는 값을 전달하기 위해 사용하는 요청방식이다.
POST : 입력값을 리퀘스트 메시지의 몸체부에 저장하여 전달한다.
→ 대용량의 값 또는 보안을 필요로 하는 값을 전달하기 위해 사용하는 요청방식이다.
웹프로그램 요청시 전달되는 값은 [이름=값] 형식으로 전달된다. (이름과 값을 하나로 묶어 전달한다)
이름=값&이름=값&...
<form action="join.itwill" method="post" id="joinForm"></form>
[form.html]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Servlet</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
<style type="text/css">
h1 {
text-align: center;
}
fieldset {
width: 800px;
margin: 10px auto;
}
legend {
font-size: 1.2em;
}
#joinForm ul li {
list-style-type: none;
margin: 15px 0;
}
#joinForm label {
width: 150px;
text-align: right;
float: left;
margin-right: 10px;
}
#btnFs {
text-align: center;
}
.error {
color: red;
margin-left: 10px;
}
</style>
</head>
<body>
<h1>회원가입</h1>
<hr>
<fieldset>
<legend>회원가입정보</legend>
<ul>
<li>
<label>아이디</label>
<input type="text" name="id" id="id"><br>
<label> </label>
<span id="idMsg" class="error"></span>
</li>
<li>
<label>비밀번호</label>
<input type="password" name="passwd" id="passwd"><br>
<label> </label>
<span id="passwdMsg" class="error"></span>
</li>
<li>
<label>비밀번호 확인</label>
<input type="password" name="repasswd" id="repasswd"><br>
<label> </label>
<span id="repasswdMsg" class="error"></span>
</li>
<li>
<label>이름</label>
<input type="text" name="name" id="name"><br>
<label> </label>
<span id="nameMsg" class="error"></span>
</li>
<li>
<label>이메일</label>
<input type="text" name="email" id="email"><br>
<label> </label>
<span id="emailMsg" class="error"></span>
</li>
<li>
<label>성별</label>
<input type="radio" name="gender" class="gender" value="남자">남자
<input type="radio" name="gender" class="gender" value="여자">여자<br>
<label> </label>
<span id="genderMsg" class="error"></span>
</li>
<li>
<label>취미</label>
<input type="checkbox" name="hobby" class="hobby" value="등산">등산
<input type="checkbox" name="hobby" class="hobby" value="낚시">낚시
<input type="checkbox" name="hobby" class="hobby" value="여행">여행
<input type="checkbox" name="hobby" class="hobby" value="독서">독서<br>
<label> </label>
<span id="hobbyMsg" class="error"></span>
</li>
<li>
<label>직업</label>
<select name="job">
<option value="회사원" selected="selected"> 회사원 </option>
<option value="주부"> 주부 </option>
<option value="학생"> 학생 </option>
</select>
</li>
<li>
<label>자기소개</label>
<textarea rows="4" cols="80" name="profile" id="profile"></textarea><br>
<label> </label>
<span id="profileMsg" class="error"></span>
</li>
</ul>
</fieldset>
<fieldset id="btnFs">
<button type="button" id="submitBtn">회원가입</button>
<button type="button" id="resetBtn">다시작성</button>
</fieldset>
</form>
<script type="text/javascript">
$("#id").focus();
$("#submitBtn").click(function() {
var result=true;
$(".error").text("");
var idReg=/^[a-zA-Z]\w{5,19}$/g;
if($("#id").val()=="") {
$("#idMsg").text("아이디를 반드시 입력해 주세요.");
result=false;
} else if(!idReg.test($("#id").val())) {
$("#idMsg").text("아이디는 6~20자의 영문자,숫자,특수기호(_)로만 작성 가능합니다.");
result=false;
}
var passwdReg=/^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[~!@#$%^&*_-]).{6,20}$/g;
if($("#passwd").val()=="") {
$("#passwdMsg").text("비밀번호를 반드시 입력해 주세요.");
result=false;
} else if(!passwdReg.test($("#passwd").val())) {
$("#passwdMsg").text("비밀번호는 6~20자의 영문자,숫자,특수문자가 1번 이상 포함해야만 됩니다.");
result=false;
}
if($("#passwd").val()!=$("#repasswd").val()) {
$("#repasswdMsg").text("비밀번호가 맞지 않습니다.다시 입력해 주세요.");
result=false;
}
if($("#name").val()=="") {
$("#nameMsg").text("이름을 반드시 입력해 주세요.");
result=false;
}
var emailReg=/^([a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+)*$/g;
if($("#email").val()=="") {
$("#emailMsg").text("이메일을 반드시 입력해 주세요.");
result=false;
} else if(!emailReg.test($("#email").val())) {
$("#emailMsg").text("이메일을 형식에 맞게 입력해 주세요.");
result=false;
}
if($(".gender").filter(":checked").length==0) {
$("#genderMsg").text("성별을 반드시 선택해 주세요.");
result=false;
}
if($(".hobby").filter(":checked").length==0) {
$("#hobbyMsg").text("취미를 반드시 선택해 주세요.");
result=false;
}
if($("#profile").val()=="") {
$("#profileMsg").text("자기소개를 반드시 입력해 주세요.");
result=false;
}
if(!result) return;
$("#joinForm").submit();
});
$("#resetBtn").click(function() {
$("#joinForm")[0].reset();
$("#id").focus();
$(".error").text("");
});
</script>
</body>
</html>
입력페이지(form.html)로부터 전달받은 입력값(회원정보)을 반환받아 클라이언트에게 전달하여 출력하는 서블릿 생성
→ 입력페이지의 form 태그를 이용하여 POST 방식으로 요청해야만 실행되는 서블릿
(GET 방식으로 요청하면 전달값이 없기 때문에 사용하면 안된다)
[joinServlet]
서블릿을 GET 방식으로 요청한 경우 비정상적인 요청으로 클라이언트에게 에러코드를 전달하거나 에러페이지로 이동되도록 처리
HttpServletRequest.getMethod() : 서블릿을 요청한 요청방식(GET or POST)를 반환하는 메소드
비정상적인 요청 처리 방식 1)
HttpServletResponse.sendError(int sc) : 클라이언트에게 에러코드(4XX or 5XX)를 전달하여 응답하는 메소드
→ 상태코드(StatusCode)는 HttpServletResponse 인터페이스의 정의된 상수를 사용한다.
//서블릿을 GET 방식으로 요청한 경우 비정상적인 요청으로 클라이언트에게 에러코드를
//전달하거나 에러페이지로 이동되도록 처리
if(request.getMethod().equals("GET")) {//서블릿을 비정상적으로 요청한 경우
//response.sendError(400);
//response.sendError(HttpServletResponse.SC_BAD_REQUEST);//400
//response.sendError(405);
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);//405
return;
}
비정상적인 요청 처리 방식 2)
HttpServletResponse.sendRedirect(String url) : 클라이언트에게 301 상태코드와 URL 주소를 전달하여 응답
→ 클라이언트는 전달받은 URL 주소로 브라우저의 요청 URL을 변경하여 웹프로그램을 요청하여 실행결과를 응답받아 출력한다. - 페이지 이동(리다이렉트 이동)
if(request.getMethod().equals("GET")) {//서블릿을 비정상적으로 요청한 경우
response.sendRedirect("error.html");//에러페이지로 이동
//response.sendRedirect("form.html");//입력페이지로 이동
return;
}
[error.html]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Servlet</title>
</head>
<body>
<h1>에러페이지</h1>
<hr>
<p>비정상적인 방법으로 웹자원을 요청 하였습니다. 정상적인 방법으로 사이트를 이용해 주세요.</p>
<div><a href="form.html">페이지 이동</a></div>
</body>
</html>
비정상적인 요청 처리 방식 3)
클라이언트에서 자바스크립트를 전달하여 응답
if(request.getMethod().equals("GET")) {//서블릿을 비정상적으로 요청한 경우
//클라이언트에서 자바스크립트를 전달하여 응답
out.println("<script type='text/javascript'>");
out.println("alert('비정상적으로 페이지를 요청하였습니다.');");
out.println("location.href='form.html';");
out.println("</script>");
return;
}
서블릿을 POST 방식으로 요청한 경우 사용자 입력값을 리퀘스트 메세지 몸체부에 저장하여 전달한다.
→ 리퀘스트 메세지 몸체부에 저장되어 전달되는 값은 기본적으로 문자형태를 서유럽어(ISO-8859-1)의 문자형태로 반환받아 사용된다.
따라서 리퀘스트 메세지 몸체부에 저장되어 전달되는 값에 대한 캐릭터셋을 변경해주어야 한다.
HttpServletRequest.setCharacterEncoding(String encoding) : 리퀘스트 메세지 몸체부에 저장되어 전달되는 값에 대한 문자형태를 변경하는 메소드
주의할 점은, GET 방식으로 요청한 경우 리퀘스트 메세지 몸체부를 사용하지 않으므로 메소드 사용이 불필요하다는 것이다.
request.setCharacterEncoding("utf-8");
클라이언트 서블릿을 요청할 때 전달된 값을 반환받아 저장
HttpServletRequest.getParameter(String name) : 매개변수로 전달된 이름의 전달값을 문자열(String 객체)로 반환하는 메소드
→ 매개변수의 이름으로 전달된 값이 없는 경우[null]을 반환한다.
String id=request.getParameter("id");
String passwd=request.getParameter("passwd");
String name=request.getParameter("name");
String email=request.getParameter("email");
String gender=request.getParameter("gender");
//String hobby=request.getParameter("hobby");
String job=request.getParameter("job");
String profile=request.getParameter("profile");
동일한 이름으로 전달되는 다수의 값이 있는 경우에는 첫번째 전달값만 반환받아 저장된다.
String hobby=request.getParameter("hobby");//첫번째 전달값만 반환받아 저장
모든 전달값을 반환받아 저장하기 위해서는 getParameterValues() 메소드를 호출해야 한다.
HttpServletRequest.getParameterValues(String name) : 매개변수로 전달받은 이름의 모든 전달값을 문자열 배열(String)로 반환하는 메소드
String[] hobby=request.getParameterValues("hobby");
실행결과를 저장한 응답파일 생성
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<meta charset='UTF-8'>");
out.println("<title>Servlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>회원가입확인</h1>");
out.println("<hr>");
out.println("<p>아이디 = "+id+"</p>");
out.println("<p>비밀번호 = "+passwd+"</p>");
out.println("<p>이름 = "+name+"</p>");
out.println("<p>이메일 = "+email+"</p>");
out.println("<p>성별 = "+gender+"</p>");
out.println("<p>취미 = ");
for(int i=0;i<hobby.length;i++) {
out.println(hobby[i]);//배열의 요소값을 HTML 문서에 포함하여 응답
if(i < hobby.length-1) {
out.println(",");
}
}
out.println("</p>");
out.println("<p>직업 = "+job+"</p>");
//전달값의 엔터(Enter)를 <br> 태그로 변환해야만 줄바꿈 처리 가능
out.println("<p>자기소개 = <br>"+profile.replace("\n", "<br>")+"</p>");
out.println("</body>");
out.println("</html>");
[전체 소스코드]
package xyz.itwill.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("/join.itwill")
public class JoinServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
//서블릿을 GET 방식으로 요청한 경우 비정상적인 요청으로 클라이언트에게 에러코드를
//전달하거나 에러페이지로 이동되도록 처리
if(request.getMethod().equals("GET")) {//서블릿을 비정상적으로 요청한 경우
/*
//HttpServletResponse.sendError(int sc) : 클라이언트에게 에러코드(4XX or 5XX)를
//전달하여 응답하는 메소드
// => 상태코드(StatusCode)는 HttpServletResponse 인터페이스의 정의된 상수 사용
//response.sendError(400);
//response.sendError(HttpServletResponse.SC_BAD_REQUEST);//400
//response.sendError(405);
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);//405
return;
*/
/*
//HttpServletResponse.sendRedirect(String url) : 클라이언트에게 301 상태코드와
//URL 주소를 전달하여 응답
// => 클라이언트는 전달받은 URL 주소로 브라우저의 요청 URL를 변경하여 웹프로그램을
//요청하여 실행결과를 응답받아 출력 - 페이지 이동(리다이렉트 이동)
//response.sendRedirect("error.html");//에러페이지로 이동
response.sendRedirect("form.html");//입력페이지로 이동
return;
*/
//클라이언트에서 자바스트립트 전달하여 응답
out.println("<script type='text/javascript'>");
out.println("alert('비정상적으로 페이지를 요청 하였습니다.');");
out.println("location.href='form.html';");
out.println("</script>");
return;
}
request.setCharacterEncoding("utf-8");
//서블릿을 요청할 때 전달된 값을 반환받아 저장
String id=request.getParameter("id");
String passwd=request.getParameter("passwd");
String name=request.getParameter("name");
String email=request.getParameter("email");
String gender=request.getParameter("gender");
//동일한 이름으로 전달되는 값이 여러개 있는 경우 getParameterValues() 메소드 호출
//String hobby=request.getParameter("hobby");//첫번째 전달값만 반환받아 저장
//HttpServletRequest.getParameter(String name) : 매개변수로 전달받은 이름의 모든
//전달값을 문자열 배열(String[])로 반환하는 메소드
String[] hobby=request.getParameterValues("hobby");
String job=request.getParameter("job");
String profile=request.getParameter("profile");
//클라이언트 요청에 대한 처리 명령 작성 및 출력스트림을 이용한 응답파일 생성
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<meta charset='UTF-8'>");
out.println("<title>Servlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>회원가입확인</h1>");
out.println("<hr>");
out.println("<p>아이디 = "+id+"</p>");
out.println("<p>비밀번호 = "+passwd+"</p>");
out.println("<p>이름 = "+name+"</p>");
out.println("<p>이메일 = "+email+"</p>");
out.println("<p>성별 = "+gender+"</p>");
out.println("<p>취미 = ");
for(int i=0;i<hobby.length;i++) {
out.println(hobby[i]);//배열의 요소값을 HTML 문서에 포함하여 응답
if(i < hobby.length-1) {
out.println(",");
}
}
out.println("</p>");
out.println("<p>직업 = "+job+"</p>");
//전달값의 엔터(Enter)를 <br> 태그로 변환해야만 줄바꿈 처리 가능
out.println("<p>자기소개 = <br>"+profile.replace("\n", "<br>")+"</p>");
out.println("</body>");
out.println("</html>");
}
}