• Home
  • About
    • Young's Github Pages photo

      一日不作一日不食

    • About
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

Java EE 정리 03

27 Feb 2019

Reading time ~8 minutes

Java EE 정리 03 - HttpServletRequest, HTML Form Control의 입력값 받기, Tomcat 한글처리


HttpServletRequest

01

  • 요청에 대한 처리
    • 접속자의 정보, 접속자가 입력하는 값들에 대한 처리
  • 웹에서 옮겨다니는 데이터는 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+"살&nbsp;");
     }
} 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()+"&nbsp;"); 
}
out.println("</li>");

out.println("\t\t</ul>");
...

02

  • print와 println의 차이
    • 브라우저 “소스보기”에선 줄이 바뀌고 안바뀌고의 차이
    • 소스코드를 잘 보여주기 위해 print와 println을 구분해서 사용해야 한다.
out.print("aaaaa");
out.println("aaaaa");
out.println("bbbbb");

03

out.print("<a href='");
out.print("test.jsp'>클릭");
out.println("</a>");
out.println("<br/>");

04

  • 접속자 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>

05

06

/**
* 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>");
          
          ...
     }
}

08

  • 요청방식이 잘못 됐을 때 떨어지는 에러는 405
    • doGet메소드 주석처리하고 URL로 호출하면 처리할 method를 찾지 못해 에러가 떨어진다.
    • 보통 에러페이지를 따로 만들어서 에러가 발생하면 그 페이지를 보여주도록 처리한다.

07

Tomcat 한글처리

  • 세팅되는 Tomcat 버전에 따라 다르게 코딩 해야 한다.
    • POST 방식 톰캣 어떤 버전을 사용하든 한글이 깨진다.
    • Tomcat 8 이전 버전은 GET방식의 Parameter 값 받으면 한글이 깨진다. * Tomcat 8 버전부터는 GET방식의 Parameter는 한글이 깨지지 않는다.
  • Dynamic Web Project의 장점
    • 다양한 서버환경에서 실행해볼 수 있다.
    • Tomcat 7, 8 등 등록하고 테스트가 가능

09

10

11

  • 한글이 깨지는 이유는 값을 패킷단위로 전송(1byte, 8bit) 하기 때문
    • UTF-8에서 한글 한 글자는 3byte
      • 한글을 패킷단위 3개로 분리해서 전달(인코딩)
      • 한글자 -> %값%값%값
      • 인코딩된 글자를 서버가 전달받고 인코딩된 내용을 그대로 화면에 찍기 때문에 깨져서 보이는 것
  • UTF-8
    • 한글 한 글자당 3byte
    • 한글 한글자를 3개의 byte로 인코딩 후 전송
  • EUC-KR
    • 한글 한 글자당 2byte
    • 한글 한글자를 2개의 byte로 인코딩 후 전송
  • name값으로 “홍길동” 입력 후 GET방식으로 전달했을 때

12

  • 인코딩한 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");

13

  • 입력값을 한글로 인코딩하는 클래스
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>");
...

14

  • 인코딩이 두번되면 모든 문자가 ?가 되버린다.
out.print(HangulConv.toUTF(HangulConv.toUTF(name))); // 두번 인코딩

15

  • Tomcat 8.5는 GET방식일 경우 자동으로 인코딩을 수행한다.
    • 때문에 또 인코딩을 시키면 인코딩이 두번 되어 글자가 ?가 되어버린다.
      • Tomcat 8.5에서는 인코딩을 또 수행할 필요가 없다.

16

POST 방식의 한글처리

  • request객체가 제공하는 method를 사용하기 전에 코딩해야 한다.
    • Tomcat 모든 버전에서 동일하게 적용
    • 보통 첫줄에 코딩해줌
request.setCharacterEncoding("인코딩할 chatset");

17

  • 주의
    • 요청처리 객체가 미리 사용되면 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"); 

18



Java EEServlet