。゚(*´□`)゚。

코딩의 즐거움과 도전, 그리고 일상의 소소한 순간들이 어우러진 블로그

[네이버클라우드] 클라우드 기반의 개발자 과정 7기/웹프로그래밍

[NC7기-80일차(8월21일)] - 웹프로그래밍 61일차 서블릿 공부 .. -3-

quarrrter 2023. 8. 21. 17:08

*서블릿 프로그래밍 - component

 

*서블릿 구현하는 방법

1. servlet 인터페이스 구현하여 - Myservlet 만들 수 있음.

재정의 해야하는 메서드 

init() 서블릿 객체 생성될때 생성된다., 클라이언트가 최초로 요청했을 때 , 한번 요청하면 다음부턴 생성된 객체를 계속사용. 

service() 클라이언트가 서블릿 실행을 요청할때마다 생성된다. 

destroy() 서블릿을 reload, stop 할 때 생성된 서블릿에 대해 destroy 호출. 

getServletInfo() 리턴값 문자열

getServletConfig() 리턴값 서블릿컨피그 

 

2. servlet 인터페이스 구현한 추상클래스 GenericServlet을 상속받아 Myservlet 만들 수 있음

제너럴을 상속받는다면,, 나머지는 다 재정의 되어있기때문에

service만 재정의하면 됨. 

 

3. 제너럴을 상속받은 http 서블릿 클래스(추상클래스) 

service() 재정의 되었음. (httpservlet request, response도 재정의 같이 되어있음)

get요청이 들어오면 doget, post는 dopost, head는 dohead 호출되도록 짜여있음

http서블릿클래스 사용한다면, get 쓸거면 doget 오버라이딩 해야함. (?) 미리 되어있는지, 내가 해야하는지 확인하기

 

 

//

https://central.sonatype.com/artifact/net.coobird/thumbnailator/0.4.20

 

Maven Central: net.coobird:thumbnailator:0.4.20

Discover thumbnailator in the net.coobird namespace. Explore metadata, contributors, the Maven POM file, and more.

central.sonatype.com

// multipart/form-data 처리 라이브러리
implementation 'commons-fileupload:commons-fileupload:1.5' // Servlet API로 대체

// thumbnail 이미지 생성기
implementation 'net.coobird:thumbnailator:0.4.20'

 

 

///작업디렉토리를 app으로 설정

/// url 형식 

/// type conversion(형변환)도 쓰지만 type casting 원래 타입으로 부른다.

 

** 필터 :  서블릿이랑 서블릿컨테이너 사이에 작업을 삽입하는 기술

filter라는 인터페이스를 구현해서 myfilter라고 만들면됨.

메서드 3개: 

init()

destroy()

doFilter()

 

// 서블릿 컨테이너가 관리하는 컴포넌트
// => 서블릿, 필터, 리스너
//
// 필터 만들기
// => javax.servlet.Filter 인터페이스 규칙에 따라 작성한다.
//
// 필터 배포하기
// => DD 파일(web.xml)에 설정하기
//      <!-- 필터 등록 -->
//      <filter>
//          <filter-name>f01</filter-name>
//          <filter-class>com.eomcs.web.ex02.Filter01</filter-class>
//      </filter>
//
//      <!-- 필터를 적용할 URL 설정 -->
//      <filter-mapping>
//          <filter-name>f01</filter-name>
//          <url-pattern>/ex02/*</url-pattern>
//      </filter-mapping>
// => 애노테이션으로 설정하기
//      @WebFilter(URL)
//
// 필터의 용도
// => 서블릿을 실행하기 전후에 필요한 작업을 수행
// => 서블릿 실행 전
// - 웹브라우저가 보낸 암호화된 파라미터 값을 서블릿으로 전달하기 전에 암호 해제하기
// - 웹브라우저가 보낸 압축된 데이터를 서블릿으로 전달하기 전에 압축 해제하기
// - 서블릿의 실행을 요청할 권한이 있는지 검사하기 *****
// - 로그인 사용자인지 검사하기
// - 로그 남기기
// => 서블릿 실행 후
// - 클라이언트로 보낼 데이터를 압축하기
// - 클라이언트로 보낼 데이터를 암호화시키기
//

 

 

필터는 언제 시작됩니까?

생성 요청 따로 안 해도
    // 웹 애플리케이션을 시작할 때 필터 객체를 생성한다.
    // 이 메서드는 필터 객체를 생성한 후 자동으로 호출된다.
    // 필터가 사용할 자원을 이 메서드에서 준비한다.
    // => 웹 애플리케이션을 시작할 때 필터는 자동 생성된다.
destroy
// 웹 애플리케이션을 종료할 때 호출된다.
// init()에서 준비한 자원을 해제한다.

ex02/s1

public void doFilter(
    ServletRequest request,
    ServletResponse response,
    FilterChain chain)
        throws IOException, ServletException {
  // 요청이 들어 올 때 마다 호출된다.
  // => 단 필터를 설정할 때 지정된 URL의 요청에만 호출된다.
  // => 서블릿이 실행되기 전에 필터가 먼저 실행된다.
  // => 서블릿을 실행한 후 다시 필터로 리턴한다.

  // 다음 필터를 실행한다.
  // 만약 다음 필터가 없으면,
  // 요청한 서블릿의 service() 메서드를 호출한다.
  // service() 메서드 호출이 끝나면 리턴된다.
  chain.doFilter(request, response);

  // 체인에 연결된 필터나 서블릿이 모두 실행된 다음에
  // 다시 이 필터로 리턴될 것이다.
  System.out.println("Filter01.doFilter() : 종료");
}

**필터구동과정

life cycle(점선)

do필터에서 바로 서블릿 찍고 응답하는게 아니라 메서드 호출의 과정들이 쭉~있음.

필터가 2개이상일때

 

**리스너 : 옵저버 패턴임 . => 서블릿 컨테이너나, 세션 등이 특별한 상태일 때 필요한 작업을 수행한다.

url을 붙이지 않음.

옵저버 패턴임 . => 서블릿 컨테이너나, 세션 등이 특별한 상태일 때 필요한 작업을 수행한다.

ServletContextListener : 웹 앱을 시작 또는 종료할 때 어떤 작업을 준비 & 해제하는 작업

ServletRequestListener : 요청이 들어올때 로그 남기기 

ServletContextListener
//    - 웹 애플리케이션을 시작할 때 Spring IoC 컨테이너 준비하기
//    - 웹 애플리케이션을 시작할 때 DB 커넥션 풀 준비하기
//    - 웹 애플리케이션을 종료할 때 DB 커넥션 풀에 들어 있는 모든 연결을 해제하기
-contextInitialized() // 웹 애플리케이션이 시작될 때 호출된다.
-contextDestroyed()  // 웹 애플리케이션이 종료될 때 호출된다.

sql세션 팩토리, dao 객체를 리스너에서 생성

 

ServletRequestListener

 @Override
  public void requestInitialized(ServletRequestEvent sre) {
    // 요청이 들어 왔을 때 호출된다.
    System.out.println("Listener02.requestInitialized()");
    HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
    System.out.println("클라이언트 IP: " + request.getRemoteAddr());
    System.out.println("요청 URL: " + request.getServletPath());
  }

  @Override
  public void requestDestroyed(ServletRequestEvent sre) {
    // 요청 처리를 완료할 때 호출된다. 필터까지 실행완료되어야 완료한거임 
    System.out.println("Listener02.requestDestroyed()");
  }

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

GenericServlet

// 출력 스트림을 꺼내기 전에
// 출력할 때 사용할 문자표(charset)를 지정하지 않으면
// 리턴 받은 출력 스트림은 기본 문자표 ISO-8859-1 을 사용한다.
// 즉 자바의 유니코드 문자를 ISO-8859-1 문자표에 따라 변환하여 출력한다.
// 자바(Unicode2;UTF-16) ===> 출력문자(ISO-8859-1)
PrintWriter out = res.getWriter();

// 다음 영어 유니코드 문자는 ISO-8859-1 문자표에 있기 때문에 제대로 변환된다.
out.println("Hello!");

// 그러나 다음 유니코드 문자는 ISO-8859-1 문자표에 없기 때문에
// 없다는 의미에서 '?' 문자표 바뀌어 출력된다.
out.println("안녕하세요!");
out.println("こんにちは");
out.println("您好");
out.println("مع السلامة؛ إلى اللقاء!");

물음표 뜨면 서버 문제라 브라우저 문제 절대 아님

// 한글 깨짐 처리하기
// => 출력 스트림을 꺼내기 전에
//    출력 스트림이 사용할 문자표(charset)를 지정하라.
// => 반드시 출력 스트림을 얻기 전에 설정해야 한다.
//      res.setContentType("MIME Type;charset=문자표이름");
//
res.setContentType("text/plain;charset=UTF-8"); // UCS2(UTF-16) ==> UTF-8
PrintWriter out = res.getWriter();
// MIME Type : Multi-purpose Internet Mail Extension
// => 콘텐트의 형식을 표현
// => 콘텐트타입/상세타입
// => 예) text/plain, text/css, text/html 등
// => 웹 브라우저는 콘텐트를 출력할 때 서버가 알려준 MIME 타입을 보고
//    어떤 방식으로 출력할 지 결정한다.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types

mime type - plain

mime type- html

// 클라이언트로 출력하기 - 바이너리 데이터 출력하기

    // photo.jpeg 파일의 실제 경로 알아내기

**GET 요청

// GET 요청
// - 웹 브라우저에 URL을 입력한 후 엔터를 치면 GET 요청을 보낸다.
// - 웹 페이지에서 링크를 클릭하면(자바스크립트 처리하지 않은 상태) GET 요청을 보낸다.
// - 웹 페이지의 폼(method='GET' 일 때)에서 전송 버튼을 클릭하면 GET 요청을 보낸다.

// 웹브라우저에서 웹서버의 자원을 요청하는 방법
// 1) 서블릿 클래스를 실행하고 싶을 때
// => 서블릿 클래스의 실제 위치:
// 톰캣배치폴더/wtpwebapps/eomcs-java-web/WEB-INF/classes/com/eomcs/web/ex04/Servlet01.class
// => 요청:
// 해당 서블릿을 서버에 등록할 때 사용한 URL을 지정해야 한다.
// http://localhost:9999/eomcs-java-web/ex04/s1
//
// 2) HTML, CSS, JavaScript, JPEG 등 정적 파일을 받고 싶을 때
// => 정적 파일의 실제 위치:
// 톰캣배치폴더/wtpwebapps/eomcs-java-web/ex04/test01.html
// => 요청:
// http://localhost:9999/eomcs-java-web/ex04/test01.html
//
// 3) /WEB-INF/ 폴더에 있는 정적 파일을 받고 싶을 때
// => 정적 파일의 실제 위치:
// 톰캣배치폴더/wtpwebapps/eomcs-java-web/WEB-INF/ex04/test01.html
// => 요청:
// /WEB-INF 폴더 아래에 있는 파일은 클라이언트에서 요청할 수 없다!
// 웹 애플리케이션의 정보를 두는 폴더이기 때문이다.
// GET 요청 HTTP 프로토콜 예)
// => GET 요청은 데이터를 request-URI에 붙여서 보낸다.
// => request-URI
// 예) /java-web/ex04/s1?name=%ED%99%8D%EA%B8%B8%EB%8F%99&age=20
// 서블릿 URL : /java-web/ex04/s1
// 데이터(Query String) : ?name=%ED%99%8D%EA%B8%B8%EB%8F%99&age=20
// => 데이터 형식
// 이름=값&이름=값&이름=값
// => request-URI는 URI 규칙에 따라 인코딩되어야 한다.
//
// URL 인코딩(=퍼센트 인코딩)
// - URI 작성 규칙에 따라 데이터를 변환하는 것.
// - 문법
// 원래 코드를 4비트 단위로 짤라서 문자로 간주하고 문자 코드로 인코딩 한다.

URI 작성규칙 : URI 작성규칙 (tistory.com)

 

**POST 요청    // - 웹 페이지의 폼(method='POST' 일 때)에서 전송 버튼을 클릭하면 POST 요청을 보낸다.

 

**요청 데이터 encoding/decoding 

윈도우는 홍길동 치면 내부로 ms949 코드로 인코딩되고 그 다으므에 utf-8로 인코딩하고 url 인코딩하고 이걸 웹서버어ㅔ 전송함. url 인코딩 전인 상태로 돌리는 url 디코딩하고 , utf-8 로 나온걸  request get parameter 규칙(utf-8) 에 따라  utf-8 이군아! 하고 알아먹고, 규칙에 따라 utf-16으로 디코딩

(영어일땐 앞에 00을 붙임. )
req.setCharacterEncoding("UTF-8"); 막았더니 이렇게 출력됨.

클라이언트에서 제대로 문자 출력이 안 되면, 클라이언트에서 출력하지말고 서버에서 sysout 해서 인코딩, 디코딩이 제대로 됐는지 확인 하기 . 

요새 왠만하면 ms949잘 안 씀. utf-8 씀

자바에서 스트링은 utf 16 ucs2가 리턴값임. 그래서 출력해서 보려면 바꿔줘야함. 

getparameter 꺼낼 때 제대로 넣어야 db에도 제대로 넣을 수 있음 

출력할 때 깨진다면: content 타입 확인. 

 

파일보내기 

GET, POST 요청으로 보내면 파일 데이터는 안 보내고 파일 이름만 보냄. 

파일이름만 넘어감 . 인코딩 타입을 바꿔야함

파일을 업로드 하려면, 반드시 multipart/form-data 형식으로 POST 요청해야 한다.
그래야 파일의 이름 뿐만아니라 파일 데이터도 전송한다.

 

꺼내기 

@MultipartConfig(maxFileSize = 1024 * 1024 * 10)


// 일반 폼 데이터를 꺼낼 때는 원래 하던 방식대로 값을 꺼낸다.
out.printf("이름=%s<br>\n", httpReq.getParameter("name"));
out.printf("나이=%s<br>\n", httpReq.getParameter("age"));

// 파일 데이터는 getPart()를 이용한다.
Part photoPart = httpReq.getPart("photo");
if (photoPart.getSize() > 0) {
  // 파일을 선택해서 업로드 했다면,
  String filename = UUID.randomUUID().toString();
  photoPart.write(this.uploadDir + "/" + filename);
  out.printf("사진=%s<br>\n", filename);
  out.printf("<img src='../upload/%s' height='50'><br>\n", filename);
  out.printf("<img src='../upload/%s'><br>\n", filename);
}
out.println("</body></html>");

 

checkbox

get방식

url에 다 나옴 ,. 밸류 지정 전
밸류 지정 후

*/*/

입력상자는 안 적으면 빈문자열이 넘어감 . 

체크박스는 체크 안 하면 getparameter가 null이 넘어감. , 체크하면 기본 값 on 이 넘어감 

 

*/*/ 

서버리스 

내 서버 구축 안 하고 네이버 클라우드에 function 올려놓고 사용하는 것 ~ 

ncloud

ex05

http client & http프로토콜 

// HTTP 프로토콜로 통신을 하는 서블릿 컨테이너는
// service() 메서드를 호출할 때
// ServletRequest의 파라미터 값으로 HttpServletRequest를 만들어 전달한다.
// ServletResponse의 파라미터 값으로 HttpServletResponse를 만들어 전달한다.
// 따라서 service() 메서드의 파라미터 값은 원래
// HttpServletRequest와 HttpServletResponse이다.
// 이들 객체에는 HTTP 프로토콜을 다루는 메서드가 추가되어 있다.
// 따라서 HTTP 프로토콜을 다루고 싶다면 파라미터 값을
// 원래의 타입으로 변환하라!
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpServletResponse httpRes = (HttpServletResponse) res;

기본은 service의 파라미터는 servletrequest & response임. http프로토콜로 요청 받으면 httpservletrequest *& response 객체를 만들어서 파라미터로 사용함.

대부분 http 프로토콜로 통신함.

서블릿에서 겟메서드의 리턴값으로  get요청인지 post요청인지 구분함. 

// HttpServletRequest에는 HTTP 프로토콜의 요청 방식을 리턴하는 메서드가 있다.
// => HttpServletRequest.getMethod()
//
if (httpReq.getMethod().equals("GET")) {
  out.println("GET 요청입니다.");

} else if (httpReq.getMethod().equals("POST")) {
  out.println("POST 요청입니다.");

 

그 밖에는 모름 (ex put요청 )

} else {
  out.println("이 서블릿이 다루지 못하는 요청 방식입니다.");
}

*service() 오버로딩

servlet 인터페이스를 구현한 generic service(추상클래스) 를 상속받아 myHttpservlet 클래스 생성 (얘도 추상클래스)

myHttpservlet 에서 service 오버로딩함. 

@WebServlet("/ex05/s4")
public class Servlet04 extends HttpServlet {

  private static final long serialVersionUID = 1L;

  // HTTP GET 요청에 응답하고 싶다면
  // 상속 받은 메서드 중에서 doGet()을 오버라이딩 한다.
  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // 테스트
    // - http://localhost:8080/web/ex05/test04.html 실행
    //
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("GET 요청입니다.");
  }

  // HTTP POST 요청에 응답하고 싶다면
  // 상속 받은 메서드 중에서 doPost()을 오버라이딩 한다.
  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // 테스트
    // - http://localhost:8080/java-web/ex05/test04.html 실행
    //
    response.setContentType("text/plain;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("POST 요청입니다.");
  }
}