Clean Code that Works.


OKJSP 여비님 글 펌입니다.

아래서부터 시작.

------------------------------------------------------------------------------------------------------


오랫동안 검색되고 또 문의 받아온 부분인데 정리해서 올린다 올린다 하다가 이제서야 올리네요 ^^;

 내용은 현재 Tomcat 5.5 까지에서도 해결이 되지 않았던 한글첨부 파일 다운로드 문제에 대한 해결책중 하나 입니다.

 java/jsp 입문이나 실무에서 사용하시라고 올립니다.

테스트환경은 windows2003/SU linux kernel 2.6.x 에서 모두 정상 동작했으며 JDK 1.5.11 에서 돌렸습니다.

도움이 되시길 바랍니다 ^^;

소스 내려갑니다~

 import java.io.*;
import java.sql.*;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.*;
import com.mpage.util.db.*;

/**
 * Servlet implementation class for Servlet: FileDownHelper
 *
 */
 public class FileDownHelper extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
    /**
  *
  */
 private static final long serialVersionUID = 1L;

 /* (non-Java-doc)
  * @see javax.servlet.http.HttpServlet#HttpServlet()
  */
 public FileDownHelper() {
  super();
 }    
 
 /* (non-Java-doc)
  * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
  */
 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  Connection con = null;
  Statement st = null;
  ResultSet rs = null;
 
  String idx = request.getParameter("idx");
 
  ServletContext sc = getServletContext();
 
  OutputStream out = null;
 
  try{
   File file = null;
   FileInputStream fis = null;
   byte[] buffer = null;
   String fileName = "";
   String ext = "";
   
   con = DBConnector.getConnection("mysql");
   st = con.createStatement();
   rs = st.executeQuery("select file_name, org_file from board where id=" + idx); // DB 에서 파일명을 가지고 온다.
   
   if(rs != null && rs.next()){
    String seper = "";
    if(System.getProperty("os.name").startsWith("Windows")){ // OS를 구분하여 구분자를 가지고 온다. -- 귀찮아서 프로퍼티에서 가져오기로 수정안함
     seper = "\\";
    }else{
     seper = "/";
    }
    String filePath = sc.getRealPath("/fileUpload") +seper+ rs.getString(1); // 현재 context의 실제 경로 하위의 경로를 설정
    fileName = rs.getString(2);
    ext = rs.getString(2).substring(rs.getString(2).lastIndexOf("."));
   
    file = new File(filePath);
    int size = 0;       // File available size 를 구해서 Buffer 의 크기 설정
   
    fis = new FileInputStream(file);
    size = fis.available();  // 파일의 사이즈를 가져온다
    buffer  = new byte[size];
    fis.read(buffer);
   
    fis.close();
   }
   /*
    * MIME type 설정하는 구문 (필요하면 더 추가하면 됨
    */
   if("zip".equals(ext)){
    ext = "application/zip";
   }else if("ppt".equals(ext)){
    ext = "application/vnd.ms-powerpoint";
   }else if("xls".equals(ext)){
    ext = "application/vnd.ms-excel";
   }else if("doc".equals(ext)){
    ext = "application/msword";
   }else if("txt".equals(ext)){
    ext = "text/plain";
   }else if("html".equals(ext)){
    ext = "text/html";
   }else if("htm".equals(ext)){
    ext = "text/html";
   }else if("jpg".equals(ext)){
    ext = "image/jpeg";
   }else if("jpeg".equals(ext)){
    ext = "image/jpeg";
   }else if("gif".equals(ext)){
    ext = "image/gif";
   }else if("psd".equals(ext)){
    ext = "image/x-photoshop";
   }else{
    ext = "application/zip";
   }
   response.setContentType(ext);
   out = response.getOutputStream();
   
   fileName = fileName.replaceAll(" ", "");
   
   // Browser 설정에 영향이 미치는 부분 처리
   if (request.getHeader("User-Agent").indexOf("MSIE 5.5") > -1) {
    response.setHeader("Content-Disposition", "filename=" +java.net.URLEncoder.encode(fileName, "euc-kr") + ";");
   }else if (request.getHeader("User-Agent").indexOf("MSIE 6.0") > -1) {
    response.setHeader("Content-Disposition", "filename=" +java.net.URLEncoder.encode(fileName, "UTF-8") + ";");
   }else{
    response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(fileName, "euc-kr") + ";");
   }
   
   if(buffer != null && buffer.length > 0){
    out.write(buffer);
   }
   out.close();
  }catch(Exception e){
   //e.printStackTrace();
  }finally{
   if(out != null){try{out.flush();out.close();}catch(Exception e1){}}
  }
 }   
 
 /* (non-Java-doc)
  * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
  */
 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  // TODO Auto-generated method stub
 }          
}

1. 생성자는 파라미터가 없어야 한다.

2. 자바 빈즈 컴포넌트의 속성(Property)들은 읽기, 쓰기 중 적어도 하나 이상의 기능을 수행 할 수 있어야 한다.

3. getXXX()는 파라미터를 받지 않은 구조이어야 한다.

4. setXXX()는 반다시 하나의 파라미터를 받는 구조이어야 한다.

JSP 공부중..

먼저 교환권을 가져가세요

문맥 : 쓰레드(Client)가다른 쓰레드에 처리를 의뢰하고 있어 Client는 처리의 실행 결과도 얻고 싶다고 합시다.

문제 : 처리를 의뢰한 때에 실행 결과를 기다리고 있어 응답성이 저하되어 버리고 맙니다.

해결법
  우선 처리 결과와 같은 인터페이스(API)를 가진 Future를 만듭시다. 그리고 처리 개시의 시점에서 Future를 반환값으로 합니다. 처리 결과는 나중에 Future에 set합니다. 이렇게 하면 Client는Future를 경유해서 처리 결과를 좋아하는 타이밍으로 얻는(기다리는)것이 가능합니다. 이것이 Future 패턴입니다.

관련
  Client가 처리 결과를 기다리는 부분에서는 Guarded Suspention 패턴을 사용합니다.
  Future 패턴은 Thread-Per-Message 패턴으로 처리 결과를 얻고 싶을 때 사용합니다.
  Future 패턴은 Worker Thread 패턴으로 처리 결과를 얻고 싶을 때에 사용합니다.


- 자바로 배우는 디자인 패턴 입문 -

일이 올 때까지 기다리고 일이 오면 일한다.

별명 : Thread Pool, Background Thread

문맥 : 쓰레드(Client)가 인스턴스(Host)의 메소드를 호출하고 있다고 합시다.

문제
  메소드의 처리에 시간이 걸리면 응답성이 낮아지게 됩니다. 응답성을 높이기 위해서 새로운 쓰레드를 기동해서 메소드를 처리시키면 쓰레드 기동의 시간만큼 스루풋은 저하됩니다. 또 다수의 리퀘스트를 내면 다수의 쓰레드가 기동하게 되어 버려서 용량을 저하시킵니다.

해결법
  우선 처리를 실행하는 쓰레드(워커 쓰레드)를 사전에 기동해 둡시다. 그리고 리퀘스트를 표현하는 인스턴스를 워커 쓰레드에 건네는 것입니다. 그렇게 하면 새로운 쓰레드를 매회 기동할 필요가 없게 됩니다.

관련
  워커 쓰레드의 처리 결과를 호출하는 측에 건내줄 때에는 Future 패턴을 사용합니다.
  리퀘스트를 표현하는 인스턴스를 워커 쓰레드에 건내줄 떼에는 Producer-Consumer 패턴을 사용합니다.

- 자바로 배우는 디자인 패턴 입문 -