Java EE 정리 03
27 Feb 2019
Reading time ~8 minutes
Java EE 정리 03 - HttpServletRequest, HTML Form Control의 입력값 받기, Tomcat 한글처리
HttpServletRequest
-
요청에 대한 처리
- 접속자의 정보, 접속자가 입력하는 값들에 대한 처리
- 웹에서 옮겨다니는 데이터는 String 밖에 없다.
// 요청 URL :http://localhost:8080/servlet_prj/test?이름=값&이름=값...
// http - protocol
// localhost - domain
// 8080 - port
// ? 전까지가 URL, ?뒤는 Query String("이름=값" Parameter들로 이루어짐)
// servlet_prj/test 가 URI(Servlet Path)
// 요청 방식
String method = req.getMethod();
// 요청 URL
StringBuffer url = req.getRequestURL(); // http://localhost:8080/servlet_prj/test
// 요청 URI (ContextPath를 포함)
String uri = req.getRequestURI(); // servlet_prj/test
// 요청 protocol
String protocol = req.getProtocol(); // HTTP/1.1(요청 프로토콜)
// 서버 이름 (도메인)
String serverName = req.getServerName(); // localhost(도메인)
// 서버 포트
int serverPort = req.getServerPort(); // 8080(서버 포트)
// 서블릿 경로 (ContextPath 제외한 하위 경로)
String servletPath = req.getServletPath(); // /test
// 요청한 접속자의 IP얻기
String clientIp = req.getRemoteAddr(); // 211...
// 요청한 접속자의 Port
int clientPort = req.getRemotePort(); // 클라이언트가 연 PORT
// QueryString 얻기 - GET방식만 사용가능, POST방식일 땐 null반환
String queryString = req.getQueryString(); // 이름=값&이름=값...
// Parameter 값 받기 - GET/POST 상관없이 받을 수 있음, 동명 Parameter가 존재해도 첫번째 값만 반환
String paramVal = req.getParameter("이름"); // 값
// 이름이 같은 Parameter 값 받기
String[] pramVals = req.getParameterValues("이름"); // [값, 값,...]
// Parameter의 이름받기
Enumeration<String> paramNames = req.getParameterNames();
- HttpServletRequest 사용 예
...
out.println("\t\t<ul>");
out.print("\t\t\t<li><strong>요청 방식</strong> : ");
out.print(req.getMethod());
out.println("</li>");
out.print("\t\t\t<li><strong>요청 URL</strong> : ");
out.print(req.getRequestURL());
out.println("</li>");
out.print("\t\t\t<li><strong>요청 URI</strong> : ");
out.print(req.getRequestURI());
out.println("</li>");
out.print("\t\t\t<li><strong>요청 프로토콜</strong> : ");
out.print(req.getProtocol());
out.println("</li>");
out.print("\t\t\t<li><strong>요청 서버 이름</strong> : ");
out.print(req.getServerName());
out.println("</li>");
out.print("\t\t\t<li><strong>요청 서버 포트</strong> : ");
out.print(req.getServerPort());
out.println("</li>");
// Servlet Path는 Context Path를 제외한 하위 경로
out.print("\t\t\t<li><strong>요청 서블릿 경로</strong> : ");
out.print(req.getServletPath());
out.println("</li>");
out.print("\t\t\t<li><strong>접속자의 IP</strong> : ");
out.print(req.getRemoteAddr());
out.println("</li>");
out.print("\t\t\t<li><strong>접속자의 PORT</strong> : ");
out.print(req.getRemotePort());
out.println("</li>");
out.print("\t\t\t<li><strong>요청 Query String</strong> : ");
out.print(req.getQueryString());
out.println("</li>");
out.print("\t\t\t<li><strong>Parameter 값 받기</strong> : ");
out.print(req.getParameter("name"));
out.println("</li>");
out.print("\t\t\t<li><strong>이름이 같은 Parameter 값 받기</strong> : ");
String[] ages = req.getParameterValues("age");
if (ages != null) {
for(String age : ages) {
out.print(age+"살 ");
}
} else {
out.print("나이 없음.");
}
out.println("</li>");
out.print("\t\t\t<li><strong>Parameter의 이름받기</strong> : ");
Enumeration<String> paramNames = req.getParameterNames();
while(paramNames.hasMoreElements()) { // 파라미터 이름이 있다면
// 값을 가져오고 다음 요소로 포인터를 이동
out.print(paramNames.nextElement()+" ");
}
out.println("</li>");
out.println("\t\t</ul>");
...
-
print와 println의 차이
- 브라우저 “소스보기”에선 줄이 바뀌고 안바뀌고의 차이
- 소스코드를 잘 보여주기 위해 print와 println을 구분해서 사용해야 한다.
out.print("aaaaa");
out.println("aaaaa");
out.println("bbbbb");
out.print("<a href='");
out.print("test.jsp'>클릭");
out.println("</a>");
out.println("<br/>");
- 접속자 IP를 얻는 메소드(getRemoteAddr)를 이용해서 접속자를 막을 수 있다.
String clientIp = req.getRemoteAddr();
String[] blockIp = { "133","141","149","157","144","152" };
boolean moveFlag = false;
for(String ip : blockIp) {
if (clientIp.endsWith(ip)) {
moveFlag = true;
}
}
if(moveFlag) {
resp.sendRedirect("http://www.police.go.kr/main.html"); // 경찰청으로~
}
HTML Form Control의 입력값 받기
-
Parameter로 처리
- 데이터형은 모두 String으로 전달된다.
-
name 속성이 중요
- name이 틀리면 값을 못 받아온다.
- id 속성은 CSS 디자인 변경 또는 JS, jQuery에서 DOM접근시에 중요
<input name="ooo" ... >
<select name="ooo" ... >
<textarea name="ooo" ... >
- name을 기반으로 QueryString이 만들어진다.
서블릿명?a=입력한값&b=사용자가선택한값&c=입력한값...
-
Parameter명이 유일할 때
- input태그 type이 text, password, hidden, checkbox(1개 선택), radio 등
- select태그, textarea태그
String val = req.getParameter("이름");
-
Parameter명이 중복될 때
- input 태그 type이 checkbox
String[] vals = req.getParameterValues("이름");
- HTML Form Control 입력값 받기 예
...
<!-- jQuery CDN -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#btnGet").click(function() {
// HTML Form Control의 유효성 검증 후
$("#getFrm").submit();
});
$("#btnPost").click(function() {
// HTML Form Control의 유효성 검증 후
$("#postFrm").submit();
})
});
</script>
...
<!-- test_param.html -->
<body>
<div id="getDiv">
<h2>이름이 유일한 HTML Form Control 값 전송</h2>
<form method="get" action="../param_value" id="getFrm">
<table>
<tr>
<td><label>이름</label></td>
<td><input type="text" name="name" class="inputBox"></td>
</tr>
<tr>
<td><label>나이</label></td>
<td><input type="password" name="age" class="inputBox"></td>
</tr>
<tr>
<td><label>메일링여부</label></td>
<!-- checkbox가 하나라면 배열로 처리되지 않는다. -->
<td><input type="checkbox" name="mailing">수신</td>
</tr>
<tr>
<td><label>성별</label></td>
<td>
<input type="radio" name="gender" value="남자" checked="checked">남자
<input type="radio" name="gender" value="여자">여자
</td>
</tr>
<tr>
<td><label>숨김값</label></td>
<td>
<input type="hidden" name="addr" value="서울시 강남구 역삼동 한독빌딩">
</td>
</tr>
<tr>
<td><label>사용메일</label></td>
<td>
<select name="email" class="inputBox">
<option value="gmail.com">---지메일---</option>
<option value="naver.com">---네이버메일---</option>
<option value="daum.com">---다음메일---</option>
<option value="korea.com">---코리아메일---</option>
<option value="hotmail.com">---핫메일---</option>
</select>
</td>
</tr>
<tr>
<td><label>가입인사</label></td>
<td><textarea style="width:300px; height:100px; name=""></textarea></td>
</tr>
<tr>
<td colspans="2">
<input type="button" value="전송" class="btn" id="btnGet">
</td>
</tr>
</table>
</form>
</div>
<div id="postDiv">
<h2>이름이 유일한 HTML Form Control 값 전송 POST</h2>
<form method="post" action="../param_value" id="postFrm">
<table>
<tr>
<td><label>이름</label></td>
<td><input type="text" name="name" class="inputBox"></td>
</tr>
<tr>
<td><label>나이</label></td>
<td><input type="password" name="age" class="inputBox"></td>
</tr>
<tr>
<td><label>메일링여부</label></td>
<!-- checkbox가 하나라면 배열로 처리되지 않는다. -->
<td><input type="checkbox" name="mailing">수신</td>
</tr>
<tr>
<td><label>성별</label></td>
<td>
<input type="radio" name="gender" value="남자" checked="checked">남자
<input type="radio" name="gender" value="여자">여자
</td>
</tr>
<tr>
<td><label>숨김값</label></td>
<td>
<input type="hidden" name="addr" value="서울시 강남구 역삼동 한독빌딩">
</td>
</tr>
<tr>
<td><label>사용메일</label></td>
<td>
<select name="email" class="inputBox">
<option value="gmail.com">---지메일---</option>
<option value="naver.com">---네이버메일---</option>
<option value="daum.com">---다음메일---</option>
<option value="korea.com">---코리아메일---</option>
<option value="hotmail.com">---핫메일---</option>
</select>
</td>
</tr>
<tr>
<td><label>가입인사</label></td>
<td><textarea style="width:300px; height:100px; name=""></textarea></td>
</tr>
<tr>
<td colspans="2">
<input type="button" value="전송" class="btn" id="btnPost">
</td>
</tr>
</table>
</form>
</div>
/**
* HTML Form Control의 값 받기
* UseWebParameter.java
*/
@SuppressWarnings("serial")
public class UseWebParameter extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
...
// Parameter 값 받기 : Tomcat 8.0부터는 GET방식의 Parameter는 한글이 깨지지 않는다.
String name = req.getParameter("name"); // text
String age = req.getParameter("age"); // password
String mailing = req.getParameter("mailing"); // checkbox
String gender = req.getParameter("gender"); // radio
String addr = req.getParameter("addr"); // hidden
String email = req.getParameter("email"); // select
String greeting = req.getParameter("greeting"); // textarea
out.println("\t<div>");
out.println("\t<h2>GET방식으로 요청한 파라미터 값 처리</h2>");
out.println("\t<div>");
out.println("\t\t<ul>");
out.print("\t\t\t<li> 이름 : <strong>");
out.print(name);
out.println("<strong></li>");
out.print("\t\t\t<li> 나이 : <strong>");
out.print(age);
out.println("<strong></li>");
out.print("\t\t\t<li> 메일링 여부 : <strong>");
out.print(mailing); // value 속성이 없는 checkbox는 check되면 on, check되지 않으면 null
out.println("<strong></li>");
out.print("\t\t\t<li> 성별 : <strong>");
out.print(gender);
out.println("<strong></li>");
out.print("\t\t\t<li> 주소 : <strong>");
out.print(addr);
out.println("<strong></li>");
out.print("\t\t\t<li> 이메일 : <strong>");
out.print(email);
out.println("<strong></li>");
out.print("\t\t\t<li> 가입인사 : <strong>");
out.print(greeting);
out.println("<strong></li>");
out.println("\t\t</ul>");
out.println("\t</div>");
out.println("\t<a href='date0227/test_param.html'>뒤로</a>");
out.println("\t</div>");
...
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
...
// Parameter 값 받기 : GET, POST 동일
String name = req.getParameter("name"); // text
String age = req.getParameter("age"); // password
String mailing = req.getParameter("mailing"); // checkbox
String gender = req.getParameter("gender"); // radio
String addr = req.getParameter("addr"); // hidden
String email = req.getParameter("email"); // select
String greeting = req.getParameter("greeting"); // textarea
out.println("\t<div>");
out.println("\t<h2 style='color:blue;'>POST방식으로 요청한 파라미터 값 처리</h2>");
out.println("\t<div>");
out.println("\t\t<ul>");
out.print("\t\t\t<li> 이름 : <strong>");
out.print(name);
out.println("<strong></li>");
out.print("\t\t\t<li> 나이 : <strong>");
out.print(age);
out.println("<strong></li>");
out.print("\t\t\t<li> 메일링 여부 : <strong>");
out.print(mailing);
out.println("<strong></li>");
out.print("\t\t\t<li> 성별 : <strong>");
out.print(gender);
out.println("<strong></li>");
out.print("\t\t\t<li> 주소 : <strong>");
out.print(addr);
out.println("<strong></li>");
out.print("\t\t\t<li> 이메일 : <strong>");
out.print(email);
out.println("<strong></li>");
out.print("\t\t\t<li> 가입인사 : <strong>");
out.print(greeting);
out.println("<strong></li>");
out.println("\t\t</ul>");
out.println("\t</div>");
out.println("\t<a href='date0227/test_param.html'>뒤로</a>");
out.println("\t</div>");
...
}
}
-
요청방식이 잘못 됐을 때 떨어지는 에러는 405
- doGet메소드 주석처리하고 URL로 호출하면 처리할 method를 찾지 못해 에러가 떨어진다.
- 보통 에러페이지를 따로 만들어서 에러가 발생하면 그 페이지를 보여주도록 처리한다.
Tomcat 한글처리
-
세팅되는 Tomcat 버전에 따라 다르게 코딩 해야 한다.
- POST 방식 톰캣 어떤 버전을 사용하든 한글이 깨진다.
- Tomcat 8 이전 버전은 GET방식의 Parameter 값 받으면 한글이 깨진다. * Tomcat 8 버전부터는 GET방식의 Parameter는 한글이 깨지지 않는다.
-
Dynamic Web Project의 장점
- 다양한 서버환경에서 실행해볼 수 있다.
- Tomcat 7, 8 등 등록하고 테스트가 가능
-
한글이 깨지는 이유는 값을 패킷단위로 전송(1byte, 8bit) 하기 때문
-
UTF-8에서 한글 한 글자는 3byte
- 한글을 패킷단위 3개로 분리해서 전달(인코딩)
- 한글자 -> %값%값%값
- 인코딩된 글자를 서버가 전달받고 인코딩된 내용을 그대로 화면에 찍기 때문에 깨져서 보이는 것
-
UTF-8에서 한글 한 글자는 3byte
-
UTF-8
- 한글 한 글자당 3byte
- 한글 한글자를 3개의 byte로 인코딩 후 전송
-
EUC-KR
- 한글 한 글자당 2byte
- 한글 한글자를 2개의 byte로 인코딩 후 전송
- name값으로 “홍길동” 입력 후 GET방식으로 전달했을 때
-
인코딩한 charset에 따라 받는 쪽에서 재조합(인코딩)을 해야 한글이 깨지지 않는다.
- 전체 흐름으로 보면 클라이언트측 인코딩 후 서버측 디코딩
- 개별로 보면 클라이언트는 클라이언트 대로 서버는 서버대로 인코딩을 수행한 것
-
재조합(인코딩)
- 전달받은 값을 byte배열로 만들고 새로운 charset으로 인코딩하여 새로운 문자열을 생성
String s = req.getParameter("name");
// s엔 %값%값... 클라이언트에서 인코딩된 한글이 저장되어 있음
// 1. String클래스 getBytes메소드로 s를 바이트 배열로 바꾼다.
// (8859_1은 영어,숫자, 특수문자를 나타내는 charset)
// 2. String 클래스의 생성자로 바이트배열을 UTF-8로 서버측 인코딩을 수행(3바이트를 1글자로)
new String(s.getBytes("8859_1"), "UTF-8");
- 입력값을 한글로 인코딩하는 클래스
public class HangulConv {
public static String toUTF(String kor) { // UTF-8로 인코딩
// empty를 물어 볼 때 kor.equals("")하면 kor이 null일 경우 NullPointException이 발생
// 따라서 이제 엠티를 비교할 땐 "".equals(kor)로 처리를 한다.
try {
if (kor != null || !"".equals(kor)) { // null이나 empty가 아니면 변환
kor = new String(kor.getBytes("8859_1"),"UTF-8");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return kor;
}
public static String toEUC(String kor) { // EUC-KR로 인코딩
try {
if (kor != null || !"".equals(kor)) {
kor = new String(kor.getBytes("8859_1"),"EUC-KR");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return kor;
}
}
- GET방식일 경우 항목마다 한글처리를 해줘야 한다.
String name = req.getParameter("name");
...
out.print("\t\t\t<li> 이름 : <strong>");
out.print(HangulConv.toUTF(name)); // 이런식으로 필요할 때 한글처리를 해준다.
out.println("<strong></li>");
// Tomcat 8.5로 실행시킨 코드, 자동으로 인코딩해주기 때문에 한글처리 필요가 없다.
// doGet method
...
out.print("\t\t\t<li> 이름 : <strong>");
// out.print(HangulConv.toUTF(name)); Tomcat 8.x 이하 일때는 한글 처리를 해야한다.
out.print(name);
out.println("<strong></li>");
out.print("\t\t\t<li> 나이 : <strong>");
out.print(age);
out.println("<strong></li>");
out.print("\t\t\t<li> 메일링 여부 : <strong>");
out.print(mailing);
out.println("<strong></li>");
out.print("\t\t\t<li> 성별 : <strong>");
// out.print(HangulConv.toUTF(gender));
out.print(gender);
out.println("<strong></li>");
out.print("\t\t\t<li> 주소 : <strong>");
// out.print(HangulConv.toUTF(addr));
out.print(addr);
out.println("<strong></li>");
out.print("\t\t\t<li> 이메일 : <strong>");
out.print(email);
out.println("<strong></li>");
out.print("\t\t\t<li> 가입인사 : <strong>");
// out.print(HangulConv.toUTF(greeting));
out.print(greeting);
out.println("<strong></li>");
...
- 인코딩이 두번되면 모든 문자가 ?가 되버린다.
out.print(HangulConv.toUTF(HangulConv.toUTF(name))); // 두번 인코딩
-
Tomcat 8.5는 GET방식일 경우 자동으로 인코딩을 수행한다.
-
때문에 또 인코딩을 시키면 인코딩이 두번 되어 글자가 ?가 되어버린다.
- Tomcat 8.5에서는 인코딩을 또 수행할 필요가 없다.
-
때문에 또 인코딩을 시키면 인코딩이 두번 되어 글자가 ?가 되어버린다.
POST 방식의 한글처리
-
request객체가 제공하는 method를 사용하기 전에 코딩해야 한다.
- Tomcat 모든 버전에서 동일하게 적용
- 보통 첫줄에 코딩해줌
request.setCharacterEncoding("인코딩할 chatset");
-
주의
- 요청처리 객체가 미리 사용되면 setCharacterEncoding메소드 내용은 수행되지 않는다.
- setCharacterEncoding은 요청처리 객체 request가 사용되기 전에 미리 작업해야 된다.
String name = req.getParameter("name");
String age = req.getParameter("age");
req.setCharacterEncoding("UTF-8"); // req가 사용되고 설정하면 적용되지 않음.
String mailing = req.getParameter("mailing");
String gender = req.getParameter("gender");
String addr = req.getParameter("addr");
String email = req.getParameter("email");
String greeting = req.getParameter("greeting");