MIME은 Multipurpose Internet Mail Extensions 의 약자로 메일을 확장한 인터넷 표준이라 할 수 있다.

웹에서 데이터를 상대방에게 보낼 때 헤더에 MIME을 지정하고, 상대방은 받은 데이터를 화면에 보여줄 때 MIME 형식에 따라 처리한다.

자주 사용하는 MIME 형식 종류는 다음과 같다.

 분류

 종류

 설명

 이미지 관련

 image/bmp

 BMP 파일의 MIME

 image/gif

 GIF 파일의 MIME

 image/jpeg

 JPG, JPEG, JPE 파일의 MIME

 image/png

 PNG 파일의 MIME

 image/x-icon

 ICO 파일의 MIME

 ....

 

 응용 프로그램 관련

 application/msword

 워드 파일의 MIME

 application/vnd.ms-excel

 엑셀 파일의 MIME

 application/vnd.ms-powerpoint

 파워포인트 파일의 MIME

 .... 

 기타

 application/octet-stream

 파일 다운로드 MIME

 .... 


예제) 파일 종류 별로 몇 가지 업로드해서 화면에 보여지도록 해본다.

web.xml


FileUploadServlet.java


fileUploadPage.htm


파일 업로드 후, 이미지 파일의 경우 웹 페이지에 보여질 것이고, 

응용프로그램 관련 파일은 '열기'를 선택하면 해당 응용프로그램이 실행되어 파일을 볼 수 있을 것이다. (웹 페이지에 안 열리고??????)

그러나 응용프로그램 관련 MIME 형식을 설정하지 않아도 '열기'가 된다?!?!?!?!?!?!?

기타 파일의 경우 다운로드 할 수 있다.


왜 이러나?????



Posted by 후니아부지
:

웹 프로그램에서는 데이터베이스의 환경 설정과 연결 관리등을 XML 파일이나 속성 파일을 사용하여 관리하고 특정 이름을 사용하여 이 정보를 얻어온다. 

웹에서 불특정 다수의 사용자가 DB연결을 요청한다고 무작정 허용한다면 DBMS는 부하를 감당할 수 없을 것이다.

따라서 연결 개수를 설정하여 현재 연결된 사용자가 더 이상 Connection 객체를 사용하지 않을 경우 해당 Connection 객체를 반환받아서 다른 사용자에게 할당해야 한다. 이런 작업을 Connection Pooling이라 하고 DBCP(Database Connection Pooling)이라 부른다. 


여기서는 톰캣의 DBCP(Database Connection Pool)를 사용하여 DBMS Connection 객체를 생성, 사용하는 방법에 대해 알아본다.


프로젝트의 META-INF 디렉터리 내에 Context.xml을 생성한다.

Context.xml은 해당 Context에서 사용할 리소스를 등록하는 곳이다. 

다음과 같이 작성한다.

<?xml version="1.0" encoding="UTF-8"?>
<Context>
  <Resource name="jdbc/myconn"
            auth="Container"
            type="javax.sql.DataSource"
            factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
            driverClassName="org.gjt.mm.mysql.Driver"
            url="jdbc:mysql://localhost:3306/데이터베이스명?AutoReconnect=true"
            username="계정"
            password="암호"
            maxActive="100"
            maxIdle="30"
            maxWait="60"
            removeAbandoned="true"
            removeAbandonedTiemout="60"/>
</Context>

속성

설명 

 name

 JNDI로 호출될 이름

 auth

 DBCP를 관리할 관리자. Container or Application 

 type

 해당 리소스의 Return Type. DataSource는 Connection 객체를 반환할 수 있다.

 factory

 DBCP를 관리하는 클래스

 driverClassName

 JDBC를 이용하기 위한 드라이버 클래스

 url

 DB 접속 URL. 해당 속성으로 자동 재접속을 설정했다.

 username

 DB 계정명

 password

 계정 비밀번호

 maxActive

 최대 접속 허용 개수

 maxIdle

 DB Pool에 여분으로 남겨질 최대 Connection 개수

 maxWait

 DB 연결이 반환되는 Timeout 최대 시간

 removeAbandoned

 Connection이 잘못 관리되어 버려진 연결을 찾아 재활용할 것인지 여부 설정

 removeAbandonedTimeout

 버려진 연결로 인식할 기본 시간 설정. 초 단위.


이렇게 설정된 정보 객체를 이름으로 얻으려면 자바의 네이밍 API를 사용해야 한다. 이를 JNDI라고 하는데 

JNDI(Java Naming and Directory Interface)는 이름을 사용하여 데이터 및 객체를 찾을 수 있도록 도와주는 디렉토리 서비스에 대한 Java API이다. 


web.xml에 JNDI로 정의할 이름을 등록한다. <welcome-file-list> 태그 위에 작성한다.

  <resource-ref>
    <description>MySQL Resource</description>
    <res-ref-name>jdbc/myconn</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
  </resource-ref>


서블릿을 작성하고 web.xml에 매핑해준다.

ConnectionServlet.java

package com.study;

import java.io.IOException;
import java.sql.Connection;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

public class ConnectionServlet extends HttpServlet {
	public void service(HttpServletRequest _request, HttpServletResponse _response) 
			throws IOException, ServletException {
		try {
			Context context = new InitialContext();
			/* JNDI 이름은 java:comp/env에 등록되어 있다. 
			   따라서 예약어로 "java:comp/env"가 오고 그 다음 
			   Context.xml의 name으로 설정한 내용을 쓰면 된다. */
			DataSource ds = (DataSource)context.lookup("java:comp/env/jdbc/myconn");
			Connection conn = ds.getConnection();
			
			System.out.println("conn: " + conn);			
		} catch(Exception _ex) {
			System.out.println("Error: " + _ex.getLocalizedMessage());			
		}
	}
}

web.xml

  <servlet>
    <servlet-name>ConnectionServlet</servlet-name>
    <servlet-class>com.study.ConnectionServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>ConnectionServlet</servlet-name>
    <url-pattern>/DBConnect.do</url-pattern>
  </servlet-mapping>  


실행해서 Connection 객체 정보를 확인하자.



Posted by 후니아부지
:

<form> 태그는  반드시 POST 방식으로 해야 한다. 

또한 enctype은 "multipart/form-data"로 고정이다. 이 형태에서 벗어나지 않는다.

<form method="POST" enctype="multipart/form-data" action="처리 서블릿">
  <input type="file" name="이름"/>
  <input type="submit" value="업로드"/>
</form>


파일 업로드를 위한 컴포넌트는 몇 가지 있는데, 여기서는 Apache의 Commons 프로젝트의 fileupload를 사용하겠다.


다음 경로로 접속한다.

http://jakarta.apache.org/


Ex-Jakarta의 Commons 프로젝트를 클릭한다.


FileUpload를 클릭하여 최신 버전을 다운로드 한다.


개발 환경의 OS에 따라 맞는 것을 다운로드 한다.

commons-fileupload-1.3-bin.zip

commons-fileupload-1.3.1-bin.zip


압축 풀면 나오는 폴더 내에 commons-fileupload-1.3.1.jar 파일을 프로젝트의 WebContent\WEB-INF\lib 에 복사해준다.

※ 웹 프로젝트의 라이브러리는 프로젝트\WebContent\WEB-INF\lib 에 위치하면 된다.


해당 파일을 Build Path에 추가하자.


Java Build Path에 등록하면 라이브러리에 추가된다.


아파치 Commons 프로젝트의 파일 업로드 라이브러리는 일반적으로 자체적으로 해결하므로 IO 관련 컴포넌트도 같이 등록해주는 것이 좋다. (안넣으니 없다고 오류나더라~)


Commons의 IO를 다운로드한다.


commons-io-2.4-bin.zip


필요한 파일은 commons-io-24.jar 이다. 

FileUpload 컴포넌트와 동일한 작업(lib복사, 빌드패스 추가)을 해준다.


이로써 사용준비는 끝났고 예제로 테스트 해본다.


예제) 파일을 선택하여 지정한 디렉토리로 업로드 해본다.

FileUploadPage.htm


web.xml


FileUploadServlet.java


파일을 선택하여 업로드 후 지정한 디렉터리에 저장되었는지 확인해보자.


저장된 경로를 콘솔에서 확인하고 찾아 가보자. 



※ 이클립스에서 실행하면 저장되는 경로가 복잡하고 길다. 

그러나 실제 톰캣을 사용해 배포하면 %톰캣홈%\webapps\프로젝트\ 아래에 저장될 것이다. 


※ 이클립스의 웹브라우저를 통해 접근했을 때, 업로드 후 다음과 같은 오류가 발생하는 경우가 있다. (반드시 그런 것은 아니다) 


그냥 다른 웹브라우저로 접근하면 잘된다. (ㅡ,.ㅡ)



Posted by 후니아부지
:

서블릿에서 파일 시스템을 사용하여 데이터를 관리할 때 중요한 것이 경로를 관리하는 것이다.

웹에서는 ServletContext 객체를 사용하면 된다. 현재 서블릿이 실행되는 서버의 환경 정보를 관리하기 때문에 원하는 디렉터리까지의 주소를 추출할 수 있다.

ServletContext context = this.getServletContext();
String realPath = context.getRealPath("/");


getRealPath() 메서드의 매개 변수에 "/" 를 사용하면 해당 프로젝트까지의 주소가 반환된다.

해당 프로젝트의 특정 디렉터리에 접근하려면 매개변수에 상대경로를 써주면 된다.

예를 들어 프로젝트 내의 test 디렉터리에 접근하려면 다음과 같이 쓰면 된다.

String realPath = context.getRealPath("/test");



예제) 서버 시작 시 파일로 저장된 카운트를 읽어 표시하고 서버 종료시에 파일에 저장한다.

web.xml


countServlet.java


countView.jsp


서버 시작 시 자동으로 init()이 호출되어(web.xml에 설정됨) count에 저장된다. 

처음 실행 시킨다면 파일이 없으므로 콘솔에 아래와 같이 출력될 것이다.


countServlet 서블릿이 불러지도록 해보면 (http://*********/count.do) 뷰 페이지에 카운팅 될 것이다.

페이지를 계속 갱신해보면 카운트가 올라갈 것이다.


그 다음, 서버를 종료하면 콘솔에 최종 카운트가 보이면서 파일로 저장될 것이다.


다시 서버를 구동시키면 앞서 기록한 내용과 동일함을 확인할 수 있을 것이다.


  


Posted by 후니아부지
:

[Servlet] 쿠키 (Cookie)

앎/web 2014. 3. 8. 23:57 |

1. 쿠키 데이터 저장하는 프로세스는 다음과 같다.

Cookie cookie = new Cookie(키, 값);
cookie.setMaxAge(유지시간_초단위);
response.addCookie(cookie);


2. 클라이언트의 Cookies 폴더에 파일로 저장된다.


3. 저장한 쿠키 데이터를 적용 시킬 페이지에서 쿠키를 불러온다.

Cookie[] cookies = request.getCookies();

for(int i=0; i<cookies.length; i++) {
  String key = cookies[i].getName();
  if (key.equals(키)) {
    String value = cookies[i].getValue();
  }
}


예제ID를 입력 받고 ID저장 체크 박스를 클릭 시 쿠키에 기록되는 것을 확인한다.

LoginProcess.java


web.xml


login.jsp


main.htm


Posted by 후니아부지
:

데이터 저장 영역

request

 연결이 유지되는 동안은 유지될 수 있는 데이터 영역을 가진다.

 Class

 ServletRequest    /     HttpServletRequest

 Set

 request.setAttribute(키, 값)

 Get

 request.getAttribute(키)

 Delete

 request.removeAttribute(키, 값)


 session

 웹 브라우저가 종료되기 전까지 유지될 수 있는 데이터 영역을 가진다.

 Class

 HttpSession

 Set

 session.setAttribute(키, 값)

 Get

 session.getAttribute(키)

 Delete

 session.removeAttribute(키, 값)


 application

 서버가 종료되기 전까지 유지될 수 있는 데이터 영역을 가진다.

 Class

 ServletContext

 Set

 application.setAttribute(키, 값)

 Get

 application.getAttribute(키) 

 Delete

 application.removeAttribute(키, 값)


예제폼에서 넘긴 데이터가 각 데이터 저장 영역에 저장되는 상태를 확인한다.

SetDataServlet.java


viewData.jsp


web.xml


setData.htm


결과를 확인해보자.


Posted by 후니아부지
:

웹 컨테이너로부터 RequestDispatcher 인터페이스를 얻어 현재 페이지 내에 다른 URL이나 페이지를 포함 시킬 수 있고, 또한 특정 페이지로 현재 request 정보를 유지하며 이동할 수 있다.


예제는 이전 포스팅(에러 처리 and URL 이동 )에 사용한 소스를 수정하여 작성한다.

추가: successPage.jsp

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>

<%
  String val1 = request.getParameter("val1");
  String val2 = request.getParameter("val2");
  String sum = request.getParameter("sum");
%>    
    
    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
    <title>Success</title>
  </head>
  <body>
    <center>
      계산이 완료되었습니다. <br/>
      <%= val1 %> + <%= val2 %> = <%= sum %>
    </center>
  </body>
</html>


calcServlet.java

package com.study;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CalcServlet extends HttpServlet {
	public void init() {
	}
	
	public void service(HttpServletRequest _request, HttpServletResponse _response) 
			throws IOException, ServletException {
		String val1 = _request.getParameter("val1");
		String val2 = _request.getParameter("val2");
		int sum = 0;
		
		try {
			int iVal1 = Integer.parseInt(val1);
			int iVal2 = Integer.parseInt(val2);
			sum = iVal1 + iVal2;
			System.out.println("합: " + sum);
			
			// ServletContext 객체 얻음
			ServletContext context = this.getServletContext();
			
			// RequestDispatcher 객체 얻음
			RequestDispatcher dispatcher = context.getRequestDispatcher("/successPage.jsp?sum=" + sum);
			
			// request, response 값을 가지고 페이지 이동
			dispatcher.forward(_request, _response); 
			
			// request, response 값을 가지고 페이지 포함
			//dispatcher.include(_request, _response); 
			
		} catch(Exception _ex) {
			_response.sendError(588, "숫자로 변환할 수 없는 데이터가 입력되었습니다.");
			return;
		}
	}
	
	public void destroy() {
	}
}


정상적으로 계산되었을 경우 아래와 같이 나타난다.


 

Posted by 후니아부지
:

에러 처리 (sendError)

에러 발생시 HttpServletResponse 클래스의 sendError 메서드를 사용하여 사용자에게 에러 페이지를 보여줄 수 있다.

Method

 void

 sendError(int sc) 

 Sends an error response to the client using the specified status code and clearing the buffer.
 void

 sendError(int sc, String msg)

 Sends an error response to the client using the specified status.

응답 코드는 일반적으로 500번대의 서버 에러를 출력한다.


예제)

web.xml

  .... 
  <servlet>
    <servlet-name>CalcServlet</servlet-name>
    <servlet-class>com.study.CalcServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>CalcServlet</servlet-name>
    <url-pattern>/calc.do</url-pattern>
  </servlet-mapping>
  .... 


calcPare.htm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
    <title>sendError 테스트</title>
  </head>
  <body>
    <form name="myForm" method="post" action="/SendErrorTest/calc.do">
      값1 = <input type="text" name="val1"/><br/>
      값2 = <input type="text" name="val2"/><br/>
      <input type="submit" value="계산"/>   
    </form>
  </body>
</html>


CalcServlet.java

package com.study;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CalcServlet extends HttpServlet {
	public void init() {
	}
	
	public void service(HttpServletRequest _request, HttpServletResponse _response) 
                   throws IOException, ServletException {
		String val1 = _request.getParameter("val1");
		String val2 = _request.getParameter("val2");
		try {
			int iVal1 = Integer.parseInt(val1);
			int iVal2 = Integer.parseInt(val2);
			System.out.println("합: " + (iVal1 + iVal2));
			
		} catch(Exception _ex) {
			_response.sendError(588, "숫자로 변환할 수 없는 데이터가 입력되었습니다.");
		}
	}
	
	public void destroy() {
	}
}


입력 폼에서 숫자가 아닌 문자를 입력하고 '계산' 버튼을 누르면 예외 처리로 빠지게 되어 다음과 같은 오류 페이지가 나타난다.

예외 처리 시 설정한 에러 코드와 메시지가 보일 것이다.


URL 이동 (sendRedirect)

HttpServletResponse 클래스의 sendRedirect 메서드로 특정 URL이나 페이지로 이동할 수 있다.

이동 시 현재 페이지까지 전달된 request의 파라미터는 리셋되고 웹 브라우저의 URL도 이동하는 경로로 변경된다.


앞서 작성한 CalcServlet.java 내에 try 마지막 부분에 다음 내용을 추가한다. 

계산이 완료된 후 successPage.htm 페이지로 이동하라는 의미이다.

			_response.sendRedirect("successPage.htm");


successPage.htm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
    <title>sendRedirect 테스트</title>
  </head>
  <body>
    <center> 계산이 완료되었습니다.</center>
  </body>
</html>


계산이 완료되면 다음과 같이 페이지가 이동하게 된다.


Posted by 후니아부지
:

web.xml 에 서블릿 등록시 <init-param> 태그를 사용해 초기화 매개변수를 등록할 수 있다.

....

    서블릿 이름
    서블릿 클래스
    
        초기화 매개변수 명
        초기화 매개변수 값
    

....

서블릿 클래스(GenericServelt or HttpServlet)의 getInitParameter("매개변수명") 을 통해 값을 가져올 수 있다.

또는 ServletConfig를 상속 받은 다른 클래스나 ServletConfig 객체 생성 후 매개변수를 가져올 수 도 있다.


예제)

web.xml

....
  <servlet>
  	<servlet-name>InitParam</servlet-name>
  	<servlet-class>com.study.InitParamTest</servlet-class>

  	<init-param>
  		<param-name>nick</param-name>
  		<param-value>hoya</param-value>
  	</init-param>

  	<init-param>
  		<param-name>age</param-name>
  		<param-value>18</param-value>
  	</init-param>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>InitParam</servlet-name>
  	<url-pattern>/InitParam.do</url-pattern>
  </servlet-mapping>
....


InitParamTest.java

package com.study;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class InitParamTest extends HttpServlet {
	public void service(HttpServletRequest _request, HttpServletResponse _response) {
		System.out.println("nick: " + this.getInitParameter("nick"));				
		System.out.println("age: " + this.getInitParameter("age"));				
	}
}


Posted by 후니아부지
:

GET 방식 요청의 한글 처리

방법1. WAS 환경 설정 파일 수정 (여기는 톰캣) 한다.

server.xml 파일 내용 중 <connector> 태그port 8080 인 태그에 URIEncoding="EUC-KR" 이라고 추가 해주면 된다.

[톰캣 폴더]\conf\server.xml

<connector port="8080" 
           protocol="HTTP/1.1" 
           connectiontimeout="20000" 
           redirectport="8443" 
           URIEncoding="EUC-KR">
</connector>


방법2. 받아온 데이터를 String 클래스를 통해 문자셋을 변환한다.

그러나 넘어온 데이터 개수가 많다면 모두 이 적용을 해야하므로 WAS 설정을 변경하는 방법이 낫다.

String data = _request.getParameter("data");
data = new String(data.getBytes("ISO8859_1"), "EUC-KR");


POST 방식 요청의 한글 처리

데이터를 가져오기(getParameter) 전에 넘어온 ServletRequest 객체의 문자 셋을 변경한다. 

_request.setCharacterEncoding("EUC-KR");
String data = _request.getParameter("data");


Posted by 후니아부지
: