Servlet3.0의 서브렛 사용

자세히 보기
Servlet3.0의 서브렛 사용
카탈로그
1. 메모 구성
2. 비동기 호출
3. 파일 업로드
 
이전 버전에 비해 서브렛3.0의 서브렛은 다음과 같이 향상되었습니다.
l 은 메모 구성을 지원합니다.
l 비동기 호출을 지원합니다.
l 파일 업로드에 대한 지원이 직접 있습니다.
 
이 문장에서 나는 주로 이 세 방면의 응용 예시를 말할 것이다.
 
1. 메모 구성
이전에 우리의 서브렛은 웹에서 필요했다.xml 파일에서 설정(서브렛 3.0은 지원되지만 서브렛 3.0에 주석이 도입되었습니다. 대응하는 서브렛 클래스에 @WebServlet 주석을 사용하여 표시하기만 하면, 프로그램이 시작된 후에 이 서브렛에 접근할 수 있습니다.@WebServlet의 경우 액세스 경로가 필요한 속성이 있습니다. @WebServlet에는 value와 urlPatterns 등 서브렛의 접근 경로를 나타내는 두 가지 속성이 있습니다.value와 urlPatterns는 하나의 서브렛을 여러 접근 경로에 비출 수 있지만,value와 urlPatterns는 동시에 사용할 수 없습니다.value와urlPatterns를 동시에 사용하면 서브렛에 접근할 수 없습니다.다음은 @WebServlet을 사용하는 간단한 서브렛의 예입니다.
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 *
 * Servlet3.0        Servlet。     Servlet       @WebServlet    ,
 *          Servlet ,      web.xml       。@WebServlet urlPatterns
 *  value         Servlet     ,           。
 */
@WebServlet(name="exampleServlet", urlPatterns="/servlet/example")
public class ExampleServlet extends HttpServlet {
 
   private static final long serialVersionUID = 1L;
 
   @Override
   protected void doGet(HttpServletRequest request,
         HttpServletResponse response) throws ServletException, IOException {
      this.doPost(request, response);
   }
 
   @Override
   protected void doPost(HttpServletRequest request,
         HttpServletResponse response) throws ServletException, IOException {
      response.getWriter().write("Hello User.");
   }
 
}

  
초기화 매개 변수
@WebServlet을 사용할 때도 초기화 파라미터를 설정할 수 있습니다. @WebServlet의 initParams 파라미터를 통해 지정합니다.initParams는 @WebInitParams의 그룹입니다. @WebInitParams는 초기화 매개 변수를 대표합니다.
 
import java.io.IOException;
import java.util.Enumeration;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 *        Servlet
 * WebServlet   initParams        Servlet      ,      ,
 *      @WebInitParam      。
 */
@WebServlet(value="/servlet/init-param", initParams={@WebInitParam(name="param1", value="value1")})
public class WebInitParamServlet extends HttpServlet {
 
   /**
    *
    */
   private static final long serialVersionUID = 1L;
 
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
         throws ServletException, IOException {
      this.doPost(req, resp);
   }
 
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
         throws ServletException, IOException {
      Enumeration paramNames = this.getServletConfig().getInitParameterNames();
      String paramName;
      while (paramNames.hasMoreElements()) {
         paramName = paramNames.nextElement();
         resp.getWriter().append(paramName + " = " + this.getServletConfig().getInitParameter(paramName));
      }
      resp.getWriter().close();
   }
  
}

 
2. 비동기 호출
서브렛 3.0에서는 서브렛 내부에서 비동기 처리를 지원합니다.그것의 논리는 우리가 서브렛을 요청할 때, 우리의 서브렛은 클라이언트에게 일부 내용을 되돌려줄 수 있다는 것이다.그리고 서브렛 내부에서 다른 논리를 비동기 처리하고 비동기 처리가 끝난 후에 비동기 처리의 결과를 클라이언트에게 되돌려줍니다.이것은 우리의 서브렛이 비교적 시간이 걸리는 업무 논리를 처리할 때, 우리는 먼저 일부 정보를 클라이언트에게 되돌려주고, 그 다음에 시간이 걸리는 업무를 비동기적으로 처리할 수 있으며, 클라이언트가 모든 업무 논리가 끝날 때까지 기다릴 필요가 없다는 것을 의미한다.비동기 처리가 끝난 후에 대응하는 처리 결과를 클라이언트에게 되돌려줍니다.
비동기 호출은 현재 HttpServletRequest의 startAsync () 방법으로 시작되며, AsyncContext로 되돌아옵니다.이후에 우리는 AsyncContext의 start () 방법을 호출해서 비동기 호출을 할 수 있습니다.새 루틴 내부 프로그램의 마지막 부분에서 현재 AsyncContext의complete () 방법을 호출하는 것이 좋습니다. 그렇지 않으면 비동기적으로 호출된 결과는 설정된 시간 초과가 지나야 클라이언트로 돌아갑니다.또한 비동기 호출이 시간을 초과한 후에 비동기 작업, 즉 새로 시작한 라인을 계속 호출합니다.
 
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 *        Servlet
 *   Servlet     ,        @WebServlet asyncSupported   true(   false),       Filter
 *  asyncSupported      true,       request          。
 *
 */
@WebServlet(value="/servlet/async", asyncSupported=true)
public class AsyncServlet extends HttpServlet {
 
   /**
    *
    */
   private static final long serialVersionUID = 1L;
 
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
         throws ServletException, IOException {
      this.doPost(req, resp);
   }
 
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
         throws ServletException, IOException {
      resp.setContentType("text/plain;charset=UTF-8");
      final PrintWriter writer = resp.getWriter();
      writer.println("         。");
      writer.flush();
      //      ,     AsyncContext。
      final AsyncContext asyncContext = req.startAsync();
      //      ,                  ,        。
      asyncContext.setTimeout(10*1000L);
      //          ,start        ,           Runnable  ,          
      asyncContext.start(new Runnable() {
 
         @Override
         public void run() {
            try {
                Thread.sleep(5*1000L);
                writer.println("           。");
                writer.flush();
                //      ,            complete()    ,                
                //              。
                asyncContext.complete();
            } catch (Exception e) {
                e.printStackTrace();
            }
         }
        
      });
      writer.println("          ,            ,             。");
      writer.flush();
   }
 
}

 
서브렛에서 비동기 호출을 지원하려면 asyncSupported 속성을true (기본값false) 로 지정해야 합니다.@WebServlet 메모 치수의 서브렛을 사용하여 다음과 같은 asyncSupported 속성의 값을 true로 직접 지정할 수 있습니다.
@WebServlet(value=”/servlet/async”, asyncSupported=true).웹에서xml 파일에서 설정된 서브렛의 경우, 설정할 때 asyncSupported 속성을true로 지정해야 합니다.
   
      xxx
      xxx
      true
   
   
      xxx
      xxx
   

 
서브렛의 비동기 호출 프로그램의 관건은 현재 Http서브렛 Request의 startAsync () 방법을 호출하는 것입니다.되돌아오는 AsyncContext를 이용하여 새로운 라인을 만들어서 비동기 처리를 하는 것은 필수적이지 않습니다. HttpServlet Request startAsync () 이후에 우리는 스스로 새로운 라인을 만들어서 비동기 처리를 할 수 있기 때문입니다.
@WebServlet(value="/servlet/async", asyncSupported=true)
public class AsyncServlet extends HttpServlet {
 
   /**
    *
    */
   private static final long serialVersionUID = 1L;
 
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
         throws ServletException, IOException {
      this.doPost(req, resp);
   }
 
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
         throws ServletException, IOException {
      resp.setContentType("text/plain;charset=UTF-8");
      final PrintWriter writer = resp.getWriter();
      writer.println("         。");
      writer.flush();
      //      ,     AsyncContext。
      final AsyncContext asyncContext = req.startAsync();
      //      ,                  ,        。
      asyncContext.setTimeout(10*1000L);
      Runnable r = new Runnable() {
         @Override
         public void run() {
            try {
                Thread.sleep(5*1000L);
                writer.println("           。");
                writer.flush();
                //      
                asyncContext.complete();
            } catch (Exception e) {
                e.printStackTrace();
            }
         } 
      };
      Thread t = new Thread(r);
      //             
      t.start();
      writer.println("          ,            ,             。");
      writer.flush();
   }
  
}

 
비동기 호출 감청기
비동기 호출에 대한 상세한 감청이 필요할 때, 예를 들어 시간 초과 여부를 감청할 때, 우리는 AsyncContext에 대응하는 감청기 AsyncListener를 설정해서 이 기능을 실현할 수 있다.AsyncListener는 인터페이스로 비동기 호출의 시작, 끝, 오류와 시간 초과에 대한 네 가지 방법을 정의했다.
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 *        Servlet
 *   Servlet     ,        @WebServlet asyncSupported   true(   false),       Filter
 *  asyncSupported      true,       request          。
 *
 */
@WebServlet(value="/servlet/async2", asyncSupported=true)
public class AsyncServlet2 extends HttpServlet {
 
   /**
    *
    */
   private static final long serialVersionUID = 1L;
 
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp)
         throws ServletException, IOException {
      this.doPost(req, resp);
   }
 
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
         throws ServletException, IOException {
      resp.setContentType("text/plain;charset=UTF-8");
      final PrintWriter writer = resp.getWriter();
      writer.println("         。");
      writer.flush();
      //      ,     AsyncContext。
      final AsyncContext asyncContext = req.startAsync();
      //              
      asyncContext.addListener(new MyAsyncListener());
      //      ,                  ,        。
      asyncContext.setTimeout(10*1000L);
      //          ,start        ,           Runnable  ,          
      asyncContext.start(new Runnable() {
 
         @Override
         public void run() {
            try {
                Thread.sleep(5*1000L);
                writer.println("           。");
                writer.flush();
                //      
                asyncContext.complete();
            } catch (Exception e) {
                e.printStackTrace();
            }
         }
        
      });
      writer.println("          ,            ,             。");
      writer.flush();
   }
 
   /**
    *           
    * @author Yeelim
    * @date 2014-2-8
    * @mail [email protected]
    */
   private class MyAsyncListener implements AsyncListener {
 
      @Override
      public void onComplete(AsyncEvent event) throws IOException {
         System.out.println("      ……");
         event.getSuppliedResponse().getWriter().println("      ……");
      }
 
      @Override
      public void onError(AsyncEvent event) throws IOException {
         System.out.println("      ……");
         event.getSuppliedResponse().getWriter().println("      ……");
      }
 
      @Override
      public void onStartAsync(AsyncEvent event) throws IOException {
         System.out.println("      ……");
         event.getSuppliedResponse().getWriter().println("      ……");
      }
 
      @Override
      public void onTimeout(AsyncEvent event) throws IOException {
         System.out.println("      ……");
         event.getSuppliedResponse().getWriter().println("      ……");
      }
     
   }
  
}

  
참고:
정상적으로 실행되는 비동기 호출에 대해 말하자면 상술한 코드에서 시작은 감청하지 않은 것이고, 비동기 호출이 시간을 초과하여 다시 비동기 임무를 수행할 때만 비동기 호출을 감청하는 시작이 있다.그러나 비동기 감청이 처음 시작되어야 한다면 우리는 비동기 호출이 시작될 때 해당하는 감청기를 통해 비동기 호출이 시작될 때 필요한 내용을 감청할 수 있다.
 
3. 파일 업로드
서브렛 3.0에서 파일을 업로드하는 것은 매우 간단합니다.리퀘스트의 get Part (String partName) 를 통해 업로드된 파일에 대응하는 Part를 얻거나 get Parts () 방법으로 업로드된 파일에 대응하는 Part를 얻기만 하면 됩니다.그런 다음 파트의 write (String fileName) 방법으로 해당 파일을 디스크에 쓸 수 있습니다.또는 파트의 getInputStream () 방법으로 파일에 대응하는 입력 흐름을 가져와 이 입력 흐름을 조작합니다.리퀘스트의 getpart () 또는 getparts () 방법으로 업로드된 파일을 조작하려면 두 가지 주의해야 할 점이 있습니다.먼저 파일을 업로드하는 form 폼에 사용되는enctype는multipart/form-data이어야 합니다.둘째, 주석 선언을 사용하는 서브렛의 경우 해당 클래스에 @MultipartConfig을 사용하여 태그를 지정하고 웹에 대해 태그를 지정해야 합니다.xml 파일을 구성하는 서브렛의 multipart-config 속성도 다음과 같이 지정해야 합니다.
   
      xxx
      xxx.xxx
      
   
   
      xxx
      /servlet/xxx
   

 
주석 기반 @MultipartConfig 또는 웹 기반xml 파일이 설정한 멀티파트-config, 우리는 그것들에게 몇 가지 속성을 설정할 수 있습니다.
l file-size-threshold: 파일 크기가 지정한 크기를 초과하면 하드디스크에 기록됩니다.기본값은 0이며 모든 크기의 파일이 업로드되면 하드 드라이브에 임시 파일로 기록됩니다.
l location: 업로드 파일을 저장할 디렉토리를 지정합니다.location을 지정하면 Part의 write (String fileName) 방법으로 파일을 하드디스크에 쓸 수 있습니다. 파일 이름은 경로를 가져오지 않아도 됩니다. 그러나 fileName이 절대 경로를 가지고 있다면 fileName이 가지고 있는 경로를 기준으로 파일을 디스크에 쓸 것입니다.
l max-file-size: 하나의 파일의 최대 크기를 나타내는 수치 형식입니다.기본값은 -1이며 제한 없음을 나타냅니다.하나의 파일 크기가 max-file-size가 지정한 값을 초과할 때 Illegal State Exception 이상을 던집니다.
l max-request-size: 업로드 파일의 최대 크기를 나타내는 수치 형식입니다.기본값은 -1이며 제한 없음을 나타냅니다.업로드할 때 모든 파일의 크기가 max-request-size를 초과할 때도 Illegal State Exception 이상을 던집니다.
 
위의 속성은 웹에 대한 것입니다.xml에서 서브렛을 설정합니다. 이 속성들은 멀티파트-config 요소 아래의 하위 요소에 대응합니다.주석 설정을 기반으로 한 서브렛의 경우 @MultipartConfig의 속성은 유형입니다. 상기 대응하는 속성 사이의 줄을 제거하고 대응하는 알파벳을 대문자로 쓰면 됩니다. 예를 들어maxFileSize입니다.
 
다음은 서브렛 3.0에서 파일 업로드의 예입니다.
Html:

 

Servlet

@WebServlet("/servlet/upload")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {
 
   /**
    *
    */
   private static final long serialVersionUID = 1L;
 
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp)
         throws ServletException, IOException {
      req.setCharacterEncoding("UTF-8");
      Part part = req.getPart("upload");
      //   :form-data; name="upload"; filename="YNote.exe"
      String disposition = part.getHeader("content-disposition");
      System.out.println(disposition);
      String fileName = disposition.substring(disposition.lastIndexOf("=")+2, disposition.length()-1);
      String fileType = part.getContentType();
      long fileSize = part.getSize();
      System.out.println("fileName: " + fileName);
      System.out.println("fileType: " + fileType);
      System.out.println("fileSize: " + fileSize);
      String uploadPath = req.getServletContext().getRealPath("/upload");
      System.out.println("uploadPath" + uploadPath);
      part.write(uploadPath + File.separator +fileName);
   }
  
}

 
서브렛의 경우 3.0의 파일 업로드에 주의해야 할 점이 하나 더 있다. 우리가 Part를 하드디스크에 쓴 후에 원래의 Part(즉 이전의 임시 파일)는 삭제되었을 수도 있다. 이때 우리가 Part의 내용을 다시 방문하면 비어 있고 시스템은 대응하는 파일을 찾을 수 없다고 이상을 던진다.
 
 

좋은 웹페이지 즐겨찾기