본문 바로가기
05_Server (04. JSP 프로그래밍 구현)

[Servlet] 서블릿(1) - 프로젝트 세팅(만들기)

by moca7 2024. 8. 26.

 

 

 

프로젝트를 처음부터 만드는 경우가 아니고 깃에서 내려받은 프로젝트에 대한 세팅은

"CTRL + F"로 "프로젝트 세팅 확인"을 찾으세요. ★

 

 

 

 

 

[프로젝트 만들기] 

 

ㅁ dynamic web project 생성

- package Explorer - 빈 곳 우클릭 -  dynamic web project를 만든다.

- 이제는 일반적인 자바 프로젝트는 안 된다.

dynamic web project라는 웹 어플리케이션을 개발할 수 있는 프로젝트를 생성한다.

 

- 이제부터는 프로젝트 생성도 신중하게 해야 한다. 무작정 만들면 안된다. 작성하는 이름 하나하나가 굉장히 중요하다. 

 

 

 

 

 

- 프로젝트 명으로 "01_servlet" 입력한다.

- 바로 엔터치지 마시고 프로젝트를 처음에 잘못 만들면 나중에 뒤늦게 변경할 수는 있지만

흔적이 남기 때문에 아예 삭제했다가 다시 만드는 것이 좋다.

- target runtime - 이 프로젝트를 어떤 서버 환경에서 실행시킬건지. Apache Tomcat v9.0

- dynamic web module version - 4.0 버전이어야 한다.

- finish가 아닌 next를 누른다.

 

 

 

 

 

 

- default output foler를 기본값 build\classes에서 src/main/webapp/WEB-INF/classes로 바꾼다.

자바코드가 컴파일돼서 컴파일된 파일들이 보관된다.

 

 

 

 

 

※ 참고

 

(1) src\main\java 폴더에는 .java 파일을 보관

- 이클립스에서 동적 웹 프로젝트를 만들게 되면 내부적으로 src\main에 java라는 폴더가 만들어진다.

이 폴더는 소스 폴더의 경로다. Java 소스코드 파일을 저장하는 용도다. 

이 폴더는 단순한 일반폴더가 아니고 소스 폴더로 만들어진다. 즉 소스코드를 포함할 수 있는 폴더다.

이 자바 폴더 안에서 클래스라던가 작업을 할 예정이다.

(?)프로젝트의 Java 클래스 파일은 모두 이 폴더 안에서 작업할 예정이다.(?)

우리가 클래스 작업을 하면 .java 확장자의 파일로 저장이 된다.

(?) 우리가 Java 클래스를 작성하게 되면, 이 파일들은 .java 확장자를 가지게 된다. 작성된 .java 파일은 컴파일을 통해 바이트 코드인 .class 파일로 변환되고, 이 파일이 실제로 JVM에서 실행되는 것이다.(?)

 

 

 

(2) src/main/webapp/WEB-INF/classes 폴더에는 .class 파일을 보관

- default output foler 경로가 의미하는 것은 소스폴더 안에서 작업한 클래스를 컴파일시켜서 어느 폴더에 보관시킬건지 그 컴파일한 파일을 보관할 폴더의 경로이다.

그게 기본적으로 build라는 폴더 안에 classes라는 폴더가 만들어지면서 여기에 컴파일된 파일들을 보관한다.

이 경로를 항상 수정한다. 

 

 

 

 

 

 

※ (참고) 프로젝트 폴더 구조 

 

 

- 프로젝트를 만들게 되면 src 폴더가 생기고, 그 안에 main 폴더가 생긴다.

main 폴더 안에는 java 폴더와 webapp 폴더가 생긴다.

- java 폴더 안에는 자바코드를 작성한다. (클래스, 인터페이스 등을 java라는 소스 폴더 안에서 작업한다)

- webapp 폴더에서는 화면 구현 관련해서 진행한다. 

화면 구현(HTML, CSS, JAVASCRIPT) 아니면 정적요소

- 어떤 폴더에서 작업을 하는지가 다르다.

 

 

 

- 그리고 webapp이라는 폴더 안에는 WEB-INF라는폴더가 만들어진다.

이 안에 classes라는 이름의 폴더는 없는데 경로를 저렇게 주면 classes라는 폴더가 만들어지면서 여기에 파일들을 보관하겠다는 것이다. 

- 여기에는 java 코드가 컴파일된 파일들이 이 안에 보관된다.

- 굳이 경로를 이렇게 수정하는 이유는 프로젝트 작업이 다 끝난 후에 실제 서버에 배포를 진행하게 될 때는 어느 어느 부분만 내보내냐면, webapp 폴더만 압축해서 내보낸다. 이게 서버에 배포된다.

- 그래서 webapp 폴더 안에 화면도 있어야 하고 자바코드도 있어야만 한다.

근데 자바코드는 지금 webapp의 바깥 쪽에 java라는 폴더 안에 만들어진다.

- 사실 컴파일된 파일만 있으면 되기 때문에 그 컴파일된 파일이 webapp이라는 폴더 내에 저장이 될 수 있게끔 경로를 수정하는 것이다.

- 만약 build\classes로 냅두면 webapp 폴더 안에 컴파일된 파일이 보관이 안 된다. 

그러면 실제 서버에 배포할 때 문제가 생길 수 있다. 

- 지금 우리가 구축한 서버는 개발용 서버다. 실 서버는 아니다. 

회사가면 서버가 많다. 개발서버, 테스트 서버, 실서버 이렇게 단계별로 나눠진다.

그래서 곧바로 실서버에 배포하면 안되고, 개발 서버에서 개발을 진행하고 테스트도 하고 테스트 서버에 배포하고 다시 테스트하고 완벽하다고 승인이 떨어지면 실서버에 배포를 하는 흐름이다. 

- 그래서 그 때를 대비해서 경로를 미리 수정을 하는 연습을 하는게 좋다.

 

 

 

 

 

 

ㅁ default output foler 경로 설정 후 next 화면

 

 

 

- next누르고 Content directory 경로를 보면 src/main/webapp다.

이게 프로젝트 작업이 다 끝나고 실제 서버에 배포되는 폴더의 경로다.  Content directory 경로는 수정하지 않는다.

- Context root를 servlet으로 수정한다. 

- Generate web.xml deployment descriptor는 항상 체크한다. 체크하고 finish

 

 

 

 

※ 참고

- webapp 폴더를 웹 컨테이너라고 부른다.

이 폴더 내에 화면단이라던가 정적인 요소들 그리고 이제 컴파일된 작업 파일들 그런것들이 다 있어야만 한다.

Context root는 이 어플리케이션을 지칭하는 고유한 이름이다. context path라고도 한다.

- 여기에 작성된 context path명이 이제부터 url에 매번 작성될 예정이다.

url로 서버에 요청해서 페이지를 받아볼 때, 서버 위에 어떤 어플리케이션을 요청할건지 그 어플리케이션을 지칭해야만 한다. 어플리케이션을 지칭하는 이름이 context root에 작성되어있는 이름이다.

- contextPath는 애플리케이션의 고유한 이름으로 식별자같은 존재다. 다른 어플리케이션 이름이랑 겹쳐서는 안된다.

- 기본적으로 프로젝트 명과 똑같이 작성되어있는데 수정하는 것을 권장한다. 

왜냐면 프로젝트명이 url에 노출이되면 폴더 구조가 노출되어 버린다. 

보통 프로젝트명을 따거나 팀명 등을 딴다.

 

 

 

 

 

- finish 누르면 프로젝트가 만들어진다. 패키지 익스플로러에 보여진다.

dynamic web project는 아이콘 왼쪽 상단에 지구본 모양이 뜬다.

 

 

 

 

 

 

- 원래는 노란색 느낌표가 안뜨는데, 지금 이 워크스페이스에 수업자료를 다운받아 놓았다. 

이름이 똑같아서 그런지 열어보니까 파일들이 다 연결되어 있다. 

- file - open projects from file system으로 02_jsp 가져오니까 그건 빨간 느낌표가 뜬다. 그렇게는 안되나 봄.

 

 

 

 

 

 

 

- src랑 src/main/java가 둘이 따로 보여지는데 실제로는 하나의 폴더다. 

src/main/java는 소스폴더, src/main/webapp은 일반 폴더기 때문에 나뉘어 보여진다. 

- 초기에는 src/main/java에는 아무 것도 없다.

src/main/webapp에는 META-INF 폴더와 WEB-INF 폴더만 있다.

- WEB-INF에는 web.xml이라는 파일이 있다.

(동적 프로젝트 생성시 마지막에 generate web.xml 파일을 체크했다)

- WEB-INF의 lib 폴더는 라이브러리 폴더다. 어플리케이션 개발을 하면서 다른 외부 라이브러리를 가져다 쓰게될 경우 lib이라는 폴더 안에 가져다 두면 된다. 

대표적으로 ojdbc6 파일 등을 이 폴더 안에 가져다 놓을 예정이다. 

- META-INF 폴더는 볼 필요 없다. 항상 만들어지는 폴더다. 

 

- 탐색기에서도 C:\workspaces\05_jspServlet-workspace\01_servlet를 가서 확인해 본다.

 

 

 

 

 

 

[프로젝트 세팅 확인]

 

 

동적 웹프로젝트 생성 후 프로젝트가 잘 세팅됐는지 확인

- 항상 프로젝트를 생성한 후에 바로 작업하려고 하지 말고, 잘 생성됐는지 확인해주시고 하는게 좋다.

- 깃으로 프로젝트를 내려받고 오픈 프로젝트하고 프로젝트 세팅을 해줘야 한다.

- 패키지 익스플로러에서 생성된 프로젝트 우클릭 - properties를 누르면 이 프로젝트에 대한 환경설정 창이 뜬다.

 

 

 

 

프로젝트 우클릭 - properties

 

 

 

 

(1) Project Facets

- dynamic web module이 체크되어 있는지, 4.0버전인지 확인한다.

- 오른쪽에서 details 탭에서 Runtimes 탭으로 이동해서 Apache Tomcat v9.0이 체크되어 있는지 확인한다. 

- 자바도 체크되어 있는지, "17"버전인지 확인한다.  (1.7버전 아님)

- 자바스크립트는 체크 유무 별 상관 없다. 위의 2개가 중요. 

 

 

 

(2) Web Project Settings

- 왼쪽 Web Project Settings - Content root가 servlet인지 확인하고 apply and close.

(context root가 팀끼리 정한 게 맞는지 확인)

- 'Web Project Settings'은 Project Facets에서 설정을 마치고 apply and close를 하고 다시 열어야 보인다.

 

 

 

(3) java build path

- 왼쪽 java build path에서 default output folder를 src/main/webapp/WEB-INF/classes 으로 한다.

 

- 이때 apply버튼이 비활성화되어 눌리지 않는다면, Browse로 "프로젝트명/src/main/webapp/WEB-INF"에서 create new folder로 "classes"를 만들고 OK한다.

 

 

 

 

 

※ 동적 웹 프로젝트 불러오기

- 일단 file - open project from file system으로 불러오면 빨간 느낌표가 뜸.

- file - import 한다.

 

- 여기서 Existing Projects into Workspace 누르고 next.

 

 

 

 

 

ㅁ '01_servlet'은 new - 동적 웹 프로젝트로 같은 이름의 프로젝트명을 했더니 됐고,

'02_jsp'와 'Servers' 프로젝트도 가져오고 설정한다.

 

 

(1) '02_jsp'와 'Servers' 디렉토리를 Browse로 찾고 바로 finish 눌렀더니 빨간 느낌표 없이 import 되었다.

(아래의 다른 체크사항들은 하나도 선택 x. 이게 아마 맞는듯 폴더를 불러온 경우.)

- 그런데 아이콘이 일반 프로젝트로 되어 있다.

프로젝트에 우클릭하고 위에서 한 환경 설정들을 했다. 

- Web Project Settings 는 목록 자체가 안보여서 일단 apply and close 하고, 다시 켜서 세팅했다.

02_jsp로 되어있어서 jsp로 바꿨다. (내려 받으면 context root가 아닌 프로젝트 이름으로 되어있다.)

- 그런데 선생님은 집에가서 open project로 연다고 말함. 

 

  • Open Project는 이미 이클립스 워크스페이스에 있는 프로젝트를 열 때 사용합니다.
  • Import는 워크스페이스 외부에 있는 프로젝트를 가져와서 새롭게 추가할 때 사용합니다.

 

- Open Project이미 이클립스 워크스페이스에 존재하는 프로젝트를 닫았다가 다시 열때 사용한다. 

반면에, Git에서 받은 수업 자료는 이클립스 워크스페이스 밖의 외부 프로젝트이므로, Import 기능을 사용해야 합니다.

 

 

(2) 학원에선 됐는데, 집에서는 import를 먼저 했더니 02_jsp를 browse에서 선택해도 아무 프로젝트도 보여지지 않는다.

이럴 땐 file - open project from file system에서 directory로 선택하고 바로 finish했다. 

여기서는 그 안에 칸에 뭐가 보여졌다. import 때는 가운데 칸에 아무것도 없었다.

그랬는데 빨간 느낌표가 뜬다. 지우고 import했더니 이번엔 됐다. 근데 이번에도 빨간 느낌표가 떴다.

그냥 위의 "프로젝트 환경설정" 해주니 빨간 느낌표는 사라지고 노란 느낌표가 됐다. 

 

 

 

 

 

 

ㅁ 이러면 서버도 생성했고 프로젝트도 생성했다.

- 서버에 프로젝트를 올려서 구동이 잘 되는지 확인하기.

그래야 클라이언트가 url로 서버에 요청해서 페이지를 볼 수 있다. 

 

 

 

 

 

- 하단의 Servers 뷰에서 서버 우클릭 - Add and Remove.. 를 클릭한다

 

 

 

- 이 서버 위에서 어떤 어플리케이션을 구동할건지 선택하라는 창이 뜬다.

왼편에 지금 현재 이 서버 위에서 구동 가능한 프로젝트 목록이 뜬다.

(지금은 깃으로 02_jsp 프로젝트도 가져와서 import해서 이렇게 보인다.)

 

- 참고로 하나의 서버에 여러개의 웹 어플리케이션을 올려서 구동이 가능하다.

- 왼쪽의 01_servlet 선택하고 add 버튼 누르고 finish.

 

 

 

 

- 이러면 Servers 뷰에서 서버가 확장 가능하다. 눌러보면 01_servlet이 있다.

 

 

 

 

- 서버를 더블클릭한다.

하단의 Modules 탭을 눌러보면 현재 올라가 있는 웹 애플리케이션을 볼 수 있다. 여기에 떠야 한다.

 

 

 

 

 

ㅁ Servers 뷰 - 서버를 클릭하고  초록색 재생버튼으로 서버를 start.

 

 

- 마지막에 "정보: 서버가 [693] 밀리초 내에 시작되었습니다." 가 떠야 정삭장동한 것이다.

- 이제 이 서버에 어플리케이션 요청을 보낼 수 있다.

 

 

 

[프로젝트 세팅 끝!!]

 

 

 

 

 

 

ㅁ 지금까지 한 환경설정 모음

 

### Workspace 환경설정 (한 PC에서 최초에 한번만 하면됨) ###
  
1. 웹 애플리케이션 개발을 위해 Java EE 환경으로 설정 
   ㄴ 이클립스 오른쪽 상단 Open Perspective 에서 선택
2. 보여질 UI 탭 세팅
   ㄴ [Window] - [Show View]
      - Project Explorer
      - Package Explorer
      - Console
- Problems
- Servers
3. 우클릭 New 목록 커스터마이징 (선택사항)
   ㄴ [Window] - [Perspective] - [Customize Perspective] - Shortcuts 탭
      - General > File, Folder
      - Java    > Class, Interface, Package, Source Folder
      - Web > CSS File, HTML File, JSP File, Dynamic Web Project, Servlet 
      - XML     > XML File
4. Preferences 세팅
   ㄴ [Window] - [Preferences]
      ㄴ 인코딩 UTF-8로 설정 
       - General > Workspace, Spelling
       - Web     > CSS Files, HTML Files, JSP Files
       - XML     > XML Files
      ㄴ Code Templates 수정 (선택사항)
         ㄴ Java > Code Style > Code Templates - Code
           - Method Body      : 주석없애기
           - Catch block Body : 주석없애기
      ㄴ Tab Size 수정
         ㄴ General > Editors > Text Editors
            - Displayed tab width : 2로 수정
      ㄴ 개발 Font 수정
         ㄴ General > Apperance > Colors and Fonts 
            - Basic - Text Font - Edit 버튼 : D2Coding 폰트로 수정

### Server 설정 (이클립스에 연동) ###

1. Apache Tomcat 사이트 접속 후 사용할 버전 다운로드 받기 (zip으로 받아 압축풀기)
2. 압축 풀린 폴더를 C:\dev 에 가져다 두기 (찾기 편한 위치)
3. 이클립스 Servers 탭에 새로운 Server 생성 
   1) Apache - Tomcat *.* 선택
   2) Server's host name : 수정하면안됨 
      Server name : 수정가능 (아무이름이나 가능)
   3) Tomcal installation Direction 경로 : 2번 과정으로 가져다둔 Tomcat의 경로로 설정
   4) Finish
4. 생성된 Server 추가 설정 (생성된 서버 더블클릭)
   1) Server Options : Serve modules without publishing 체크
   2) Ports : HTTP/1.1 포트번호 사용하지 않는 포트번호로 수정 
   
### Dynamic Web Project 생성 (웹 애플리케이션) ###

1. 프로젝트명 작성
2. Dynamic web module version : 서버에 맞게 선택 (수업시간은 Tomcat 9 사용이므로 4.0으로 선택)  > Next
3. Default output folder : src/main/webapp/WEB-INF/classes 로 수정 > Next
4. Context Root : 기본 프로젝트명, 수정하는걸 권장 
ㄴ 해당 애플리케이션의 ContextPath로 지정되어 URL에 매번 작성될 예정 
ㄴ 즉, 해당 애플리케이션을 가리키는 고유한 이름이여야됨 (애플리케이션의 식별자)
5. Content Directory (src/main/webapp) : 수정하면 안됨 
    ㄴ 프로젝트 작업이 다 끝난 후에 서버에 배포되는 폴더의 경로 
    ㄴ 웹 컨테이너라고 지칭함 
6. Generate Web.xml deployment descriptor : 반드시 체크 
7. Finish

8. 프로젝트가 잘 세팅되었는지 확인하기 (후에 Git에서 내려받아 Project 오픈 후에도 마찬가지)
   [프로젝트 우클릭] > [Properties]
   
   1) Project Facets
  ㄴ Dynamic Web Module : 체크되어있는지, 버전 4.0인지 확인
  ㄴ Java : 체크되어있는지, 현재 설치한 자바 버전(17)인지 확인 
  ㄴ Runtimes 탭 : 생성해둔 서버 체크 (체크 안해둘 경우 간헐적으로 빨간줄 오류 발생)
 2) Web Project Settings 
    ㄴ Context Root : 프로젝트 생성시 지정한 이름이 맞는지 확인 (URL에서 사용됨)
    

 


※  생성된 프로젝트 폴더 구조 <- 이정도가 있어야 한다.
    src
     ㄴ main
       ㄴ java (Source Folder) : 자바 파일(.java), 쿼리문 파일(.xml), db환경설정(.properties) 문서 등 작성
       ㄴ webapp (일반 Folder) : 화면(.html, .jsp), 환경설정 문서(.xml), 정적자원(assets) 등 작성
         ㄴ WEB-INF/lib  : 애플리케이션 구현시 필요한 라이브러리(.jar)
         ㄴ WEB-INF/classes : src/main/java 에서 작업한 파일들이 컴파일되서 보관되는 폴더
         ㄴ WEB-INF/web.xml : 애플리케이션 배포서술자(DD) 문서

 

 

 

[src/main/java]

- jdbc를 하면 쿼리문을 작성한다. 쿼리문을 자바 파일에 작성하지 않고 외부의 xml 파일에 작성한다.

이 쿼리문 파일들(xml 파일)을 src/main/java에 보관한다.

- db환경설정. 어떤 db를 쓰고 있고 접속할 계정명은 뭐고 url 주소는 뭔지 그런것들을 properties 확장자 파일로 저장했었다.

이것들(driver.properties)도 src/main/java에 보관한다.

 

 

[src/main/webapp]

- html, css, javascript로 화면 작업을 할 텐데 이때 저장되는 파일의 확장자는 html이다.

jsp를 배우면 .jsp 파일로도 화면작업을 한다. 

- 그 밖에 이 프로젝트의 환경설정 관련된 문서들.

- 정적자원은 이미지 파일이나 영상 등을 assets 폴더로.

 

 

[src/main/WEB-INF]

- classes는 탐색기에서는 보이지만 이클립스에선 안보인다.

- web.xml은 어플리케이션의 설정들을 담고 있다. 배포서술자(deployment descriptor)라고 한다.

 

 

 


### 생성된 프로젝트를 서버에 올려서 구동하기 ###

1. [생성된 서버 우클릭] - [Add and Remove]
2. 프로젝트 선택 후 Add 버튼 > Finish
3. 서버 더블클릭 > Modules 탭에서 프로젝트 잘 올라가있는지 확인 (Context Path 명도 확인)
4. Server Start 
5. 애플리케이션 요청을 위한 URL 
   ㄴ http://host:port/contextPath/URLMapping
      - http://host:port  : 가동중인 서버를 가리킴
      - /contexPath : 가동중인 서버 위에서 구동되는 웹 애플리케이션을 가리킴
      - /URLMapping : 웹 애플리케이션 내부의 경로를 의미

 

 

 

 

 

 

=======================================================================================

 

 

 

ㅁ 서버 start도 정상적으로 됐으니 이제 이 어플리케이션을 url 요청을 보내볼 수 있다. 

- 근데 그 url 작성하기 전에 url 형식을 먼저 학습한다.

 

 

ㅁ 애플리케이션 요청을 위한 URL

- http://host:port/contextPath/URLMapping 

- http://host:port     :   가동중인 서버를 가리킴.

- /contextPath        :   가동중인 서버 위에서 구동되는 웹 애플리케이션을 가리킴.

- /URLMapping      :   웹 애플리케이션 내부의 경로를 의미.

 

 

- http:// 하고 어떤 서버에 어떤 어플리케이션 요청을 할 건지 쓴다.

 

- 어플리케이션을 구동하고 있는 서버를 먼저 쓴다. 서버의 ip 주소를 host라고 한다. 

 

- 지금은 서버에 어플리케이션을 하나만 올려놨지만 이 서버에 여러 어플리케이션이 구동될 수 있다.

그래서 이 서버 내의 어떤 어플리케이션에 요청을 보낼건지 그 어플리케이션을 지칭하는 이름인 contextPath를 써준다. 

= 어플리케이션에 요청을 보낸다는 말은 "클라이언트가 서버로 요청을 보낸다는 의미"이다.

사용자가 웹 브라우저에서 example.com/home 페이지를 요청하면, 

웹 애플리케이션이 해당 페이지의 정보를 제공하기 위해 응답을 반환합니다.

 

- 네이버나 구글 접속할 때 서버의 IP 주소나 포트번호를 치진 않는다. 걔네가 도메인을 돈주고 샀기 때문.

우리는 도메인을 구매하지 않았다. 그래서 서버의 IP주와 포트번호를 직접 입력해야만 한다.

 

 

 

 

 

 

ex) http://localhost:8888/servlet를 주소창에 입력하면 메인 페이지를 찾을 수 없기 때문에 404 오류가 뜬다.

요청을 해도 띄울만한 페이지가 만들어있지 않다.

 

 

- 나중에는 저것만 쳐도 아래와 같이 메인 페이지가 나옴.

- 현재는 메인페이지를 만들지 않아서 메인페이지를 찾을 수 없어서 404 오류가 발생한다. 

- 이제부터는 페이지를 확인할 때는 html 문서를 더블클릭해서 보지 않고, 주소창에 이렇게 쳐서 열어본다.

 

 

 

 

ㅁ 메인페이지 제작

- 그런데 메인페이지는 이름을 마음대로 정하면 안되고 아무 폴더에 저장해도 안 된다.

- 메인 페이지는 위치해야 하는 곳과 이름이 정해져 있다. 그 정보는 web.xml에 적혀있다.

- WEB-INF의 web.xml을 키고 source 탭에서 확인한다.

 

 

- 여기서 welcome-flile-list가 메인페이지다. 

이 파일들을 다 둬야 되는게 아니고, 이 중에서 하나의 이름으로만 두면 된다.

- 메인페이지 이름은 수정해도 된다.

- 주로 index.html 또는 index.jsp 2가지 이름을 사용한다. 

필요한 것만 남겨두고 지워도 된다.

- 메인페이지 파일은 src\main\webapp\ 폴더에 바로 위치해야 한다.

- http://host:port/contextPath 까지만 입력하고 요청하면 파일명까지 쓸 필요 없이 메인페이지가 보여진다.

웰컴페이지로 등록되어있기 때문이다.

물론 http://host:port/contextPath/index.html 해도 메인페이지가 보여진다. 

- contextPath 까지의 URL이 곧 webapp 폴더를 가리킨다.

contextPath가 webapp 폴더라고 생각하면 된다.

 

 

※ web.xml

- 배포서술자 (DD, Deployment Descriptor)라고 한다.

- 서버에서 해당 애플리케이션 구동시 제일 먼저 읽혀지는 문서.

제일 먼저 읽혀져야 하는 것들, 실행되야 하는 것들을 여기에 작성한다.

- 주로 해당 웹 애플리케이션의 기본적인 설정 관련 내용들을 작성한다.

- welcome-file, Servlet, Filter, Wrapper 등을 등록할 수 있다.

 

 

※ welcome-file

- 서버에 해당 애플리케이션의 contextPath로 URL 요청시 보여지는 메인페이지. (서버 + contextPath로 url)

- 해당 파일은 src/main/webapp/ 폴더에 바로 위치해있어야 한다. webapp은 웹 컨테이너다. 

 

 

 

 

 

 

ㅁ index.html 파일 생성

- 이클립스의 패키지익스플로러 - webapp폴더 우클릭 - new - html - 이름을 index.html로 해서 파일을 만든다.

- 이클립스에서도 화면구현을 할 수 있지만 자동완성이 안 된다. 

- vscode에서 화면을 작업하고 이클립스에서 백단 작업해도 된다. 실제로 이렇게 많이 한다. 

대신 한 곳에서 작업을 끝냈으면 반드시 저장을 해야 한다.

 

- 이클립스를 다크모드로 바꾼다.

- 이클립스를 껐다 키면 서버도 종료된다.

 

 

- vscode에서도 확인할 수 있다. (워크스페이스를 어쩌구)

 

 

 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <!-- src/main/webapp/index.html : web.xml 파일에서 welcome-file로 등록된 파일(메인페이지)  -->
    <h1>Servlet</h1>
</body>
</html>
 

 

- 이렇게 작성하고 저장.

- 그런데 브라우저의 404 에러가 떴던 페이지를 새로고침해도 404 에러 그대로다.

이클립스에서 서버를 start하고 새로고침하면 제대로 뜬다.

 

 

 

 

ㅁ 서브페이지 생성

- 페이지를 더 만든다. 페이지들은 src 안의 webapp 안에 둬야 한다.

(메인페이지는 webapp 폴더 바로 아래에 있어야 하고, 나머지 페이지들은 webapp 폴더 안에만 있으면 되는 듯)

- 각각의 폴더에 각각의 페이지들을 생성할 예정이다.

webapp 폴더 안에 a_lifecycle 폴더, b_request 폴더, c_response 폴더, d_forward 폴더, e_redirect 폴더를 생성한다.

 

 

 

 

 

ㅁ Servlet 클래스의 LifeCycle

- C:\workspaces\05_jspServlet-workspace\01_servlet\src\main\webapp\a_lifecycle에 main.html을 만든다.

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
   
    <h2>Servlet이란?</h2>

</body>
</html>
 

 

- http://localhost:8888/servlet/a_lifecycle/main.html를 브라우저에 입력하면 방금 우리가 만든 main.html 문서가 보인다.

 

- contextPath가 webapp 폴더다. webapp 폴더 안에 a_lifecycle 폴더가 있다.

 

 

 

- index.html을 아래와 같이 작성한다.

 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <!-- web.xml 파일에서 welcome-file로 등록된 파일(메인페이지)  -->
    <h1>Servlet</h1>

    <a href="http://localhost:8888/servlet/a_lifecycle/main.html">1. Servlet 클래스의 LifeCycle</a> <br>
    <a href="">2. HttpServletRequest</a> <br>
    <a href="">3. HttpServletResponse</a> <br>
    <a href="">4. Forward</a> <br>
    <a href="">5. Redirect</a> <br>


</body>
</html>
 

 

- index.html에 href에 이미 만들어 놓은 정적인 페이지를 연결했다.

- http://localhost:8888/servlet/ 을 입력해서 메인페이지로 간 다음, 1번 하이퍼링크를 클릭하면 위에서 만든 페이지로 가진다. 

 

1을 누르면
위에서 만들고 링크건 페이지로 이동된다

 

 

 

- 그런데 <a href="http://localhost:8888/servlet/a_lifecycle/main.html">는 너무 길다.

- 사실 이미 index.html을 보고 있을 때 contextPath까지는 이미 기술이 되어 있는 거다.

그래서 그냥 <a href="a_lifecycle/main.html">만 써도 된다.

- 상대경로방식으로도 가능하다.

./가 현재 파일이 위치해있는 폴더를 가리킨다.

<a href="./a_lifecycle/main.html">로 해도 된다.

- index.html과 각 폴더들이 같은 level에 존재하고 있다.

 

 

 

※ 현재 웹 컨테이너(webapp 폴더) 내에 있는 정적 페이지 바로 요청시 상대경로로 작성하면 된다.

- 상대경로는 항상 URL 기준으로 생각해야 한다. 

- 현재위치 : http://localhost:8888/servlet/

- 이동할위치 : ./a_lifecycle/main.html        ( ./ : 현재위치(현재 URL)을 가리킴 )

                      => http://localhost:8888/servlet/a_lifecycle/main.html

 

 

 

 

 

 

 

 

ㅁ 단순 페이지 요청이 아닌 Sevlet 요청해보기

- webapp\a_lifecycle에 main.html을 아래와 같이 작성한다.

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
   
    <h2>Servlet이란?</h2>

    <p>
        웹 서비스를 위한 Java 클래스를 의미 <br>
        Java를 활용해서 웹 개발을 할 때 필요한 기술 <br>
        사용자의 요청을 받아 처리하고 그에 해당하는 결과를 다시 사용자에게 응답하는 역할 <br>
        즉, MVC 패턴 중에 Controller 역할
    </p>

    <h3>Servlet의 LifeCycle 확인</h3>

 

  <h4>Get 방식으로 요청</h4>
    <!-- http://localhost:8888/servlet/life -->    <!-- 이렇게 해도 되는데 너무 길어서. -->
    <a href="../life">Servlet 요청</a> <br>     <!-- 상대경로방식. 현재 보여지는 URL 기준으로 작성 -->
    <a href="/servlet/life">Servlet 요청</a> <br>    <!-- 절대경로방식. 다 같은 경로다 -->
 


 <h4>Post 방식으로 요청</h4>            
    <form action="/servlet/life" method="post">                <!-- a태그는 get 방식 요청이다 -->
        <button type="submit">Servlet 요청</button>
    </form>



</body>
</html>
 

 

 

- 여기서 뭔가를 클릭해서 요청을 보내본다.

요청을 보낸다는 것은 a 태그를 클릭해서 요청을 보낼 수도 있고,

form 태그를 둬서 사용자에게 입력을 받아서 요청을 보낼 수도 있다.

- 요청을 보내는 방식은 크게 두 가지로 나뉜다. get 방식과 post 방식.

- 단순 페이지 요청이 아닌 Sevlet을 요청해본다.

- url에 서버를 작성하고, 어플리케이션을 작성하고, URLMapping을 쓸 수 있다.

URLMapping이 곧 서블릿을 가리킨다.

 

 

※ URLMapping
1) 웹 애플리케이션 내부 경로를 의미 (즉, 이 웹 어플리케이션이 가지고 있는 서블릿 같은 걸 지칭할 수 있다.)
2) 결정 방법
  (1) Servlet 클래스 생성시 @WebServlet 어노테이션으로 결정
  (2) Servlet 클래스 생성후 WEB-INF/web.xml에 등록해서 결정

 

 

- URLMapping으로 /life라는 Mapping값이 붙은 채로 요청한다.

아직 만들진 않았지만 /life라는 URL 매핑을 가지고 있는 서블릿이 자동으로 실행될 것이다.

- 경로 작성을 http://localhost:8888/servlet/life 이렇게 써도 되지만 기니까, 상대경로로 작성한다.

지금 main.html은 servlet/a_lifecycle에 있다.

./는 a_lifecycle 폴더를 가리킨다.

../를 해야 현재 contextPath인 webapp 폴더를 가리킨다.         ../life

 

- 폴더가 겹겹이 안에 있을 경우 굉장히 복잡해진다. 절대경로는 훨씬 수월하다. 이제부터 절대경로로 쓴다.

- 단순 페이지 요청은 상대경로로 하면 되는데, 서블릿 요청할 때는 절대경로 방식으로 contextPath를 항상 작성하고, URLMapping 값을 작성한다.

 

- URLMapping을 작성할 때 절대경로방식으로 작성한다면 슬래시로 시작한다.

슬래시로 시작하는 구문을 절대경로방식이라고 한다.

- 상대경로 방식은 contextPath까지를 가리키지만,

절대경로 방식은 서버(ip주소:포트번호)까지만 가리킨다.

 

 

 

 

- 지금 404 에러 뜨는건 정상이다.

아직 /life라는 매핑을 가지는 서블릿을 만들지 않았기 때문이다.

- 3가지 방식 모두 주소창을 확인해보면 동일한 URL로 요청되는 것을 볼 수 있다.

 

 

 

====================================================================================

 

 

 

 

서블릿이란?

- Java를 활용해서 웹 개발을 할 때 필요한 기술

- 웹 서비스를 위한 Java 클래스를 의미

- 사용자의 요청을 받아 처리하고 그에 해당하는 결과를 다시 사용자에게 응답하는 역할

즉, MVC 패턴 중에 Controller 역할

 

 

 

ㅁ Servlet 파일 생성

- /life라는 URLMapping 값을 가지고 있는 서블릿을 만들어 본다. 

- 서블릿은 java 클래스이기 때문에 src/main/java에 만든다.

- src/main/java에 a_lifecycle이라는 패키지를 만든다.

이 패키지를 우클릭하고 new - Servlet을 클릭한다. 

- 클래스로 만들었다가 서블릿 역할을 수행하게끔 구조를 바꿔도 되지만 굉장히 복잡하다.

그래서 애초부터 서블릿으로 만든다.

 

 

- 서블릿도 클래스이기 때문에 클래스 이름을 준다. LifeCycle이라고 짓고 Next를 누른다.

 

 

- 여기가 서블릿 클래스의 URL 매핑을 지정하는 곳이다.

URL mapping의 /LifeCycle을 더블클릭해서 /life로 수정한다. NEXT.

 

 

 

- init, destroy, service를 체크한다.

매번 이렇게 만들 건 아니고, 처음이니까 내부적으로 어떤 흐름으로 실행되는지 보기 위해 체크했다.

- finish를 누르면 LifeCycle이라는 클래스가 만들어진다.

 

 

 

 

- 아래는 만들어진 LifeCycle.java 파일이다.

 

 
package a_lifecycle;

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


// http://localhost:8888/servlet/life URL 요청시 해당 Servlet 실행
@WebServlet("/life")
/*
 * * URL Mapping 등록방법
 *   1. Servlet 클래스 상단에 @WebServlet Annotation 활용
 *      @WebServlet("URLMapping")
 *      
 *   2. WEB-INF/web.xml 파일에 Servlet 클래스 등록시 매핑
 *      <servlet>
 *          <servlet-name>LifeCycle</servlet-name>
 *          <servlet-class>a_lifecycle.LifeCycle</servlet-class>
 *      </servlet>
 *      <servlet-mapping>
 *          <servlet-name>LifeCycle</servlet-name>
 *          <url-pattern>/life</url-pattern>
 *      </servlet-mapping>
 */


public class LifeCycle extends HttpServlet {
   
    /*
     * * Servlet
     *   1. 사용자의 요청을 받아 처리한 후 응답해주는 Java 클래스
     *   2. javax.servlet.http.HttpServlet 클래스를 상속 받아 구현
     *      (javax 패키지는 Tomcat이 제공하므로 Tomcat이 없으면 구현할 수 없음)
     *   3. 동일한 애플리케이션 내에 동일한 URL Mapping값의 Servlet이 존재해서는 안됨
              - url mapping은 서블릿을 지칭하는 식별자 같은 존재
     *   4. 사용자의 요청시 Servlet컨테이너가 작동되면서 해당 Servlet 클래스가 실행됨
     *      이때 미리 약속된 메소드가 호출되도록 되어있음 (LifeCycle)
     *
     * * Servlet LifeCycle
     *   1) 최초 요청일 경우 Servlet 객체 생성(생성자) => init() 메소드 호출
     *   2_1) service() 메소드 호출
     *   2_2) doGet() 또는 doPost() 호출 (service()메소드가 정의되어있지 않을 경우)
     *   3) 더이상 Servlet이 서비스되지 않을 경우 destroy() 호출
     *      (주로 서버종료 / 재컴파일시)
     */
   
    private static final long serialVersionUID = 1L;
       
    /**
     * * 생성자
     *   1. Servlet 생성시 호출됨
     *   2. 생성자 호출 이후에 자동으로 init() 메소드 호출됨
     */
    public LifeCycle() {
        super();
        System.out.println("LifeCycle Servlet 생성자 실행");
    }

    /**
     * * init()
     *   1. Servlet 환경설정을 담당하는 메소드
     *   2. init() 이후에 자동으로 service() 메소드 호출됨
     */
    public void init(ServletConfig config) throws ServletException {
        System.out.println("init() 메소드 실행");
    }

   

    /**
     * * service()
     *   1. 클라이언트로 부터 요청을 받을 수 있음 (HttpServletRequest 매개변수)
     *      클라이언트로 응답할 수 있음           (HttpServletResponse 매개변수)
     *   2. service() 메소드가 있을 경우 여기서 요청과 응답을 다 처리함 (doGet, doPost 메소드가 있어도)
     *      service() 메소드가 없을 경우 doGet() 또는 doPost() 메소드가 "요청방식에 따라 호출됨"
     */
    /*
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("service() 메소드 실행");
       
        // request.getMethod() : 요청된 요청방식 반환 ("GET" | "POST")
        switch(request.getMethod()) {
        case "GET" : System.out.println("Get 방식으로 요청됨"); break;
        case "POST": System.out.println("Post 방식으로 요청됨"); break;
        }
       
        System.out.println("--------------------------");
    }
    */

    /**
     * * doGet()
     *   1. service() 메소드가 없을 경우 GET방식 요청시 자동으로 호출됨
     *   2. GET 방식 요청 케이스
     *      ㄴ <a href='/servlet/life'>
     *      ㄴ <form action='/servlet/life' method='get'>
     *      ㄴ location.href = '/servlet/life';
     *      ㄴ window.open('/servlet/life');
     *      ㄴ $.ajax({
     *            url: '/servlet/life',
     *            type: 'get',
     *              ...
     *         });
     *  
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doGet() 메소드 실행 (Get방식으로 요청됨)");
    }

    /**
     * * doPost()
     *   1. service() 메소드가 없을 경우 POST 방식 요청시 자동으로 호출됨
     *   2. POST 방식 요청 케이스
     *      ㄴ <form action='/servlet/life' method='post'>
     *      ㄴ $.ajax({
     *            url: '/servlet/life',
     *            type: 'post',
     *              ...
     *         });
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doPost() 메소드 실행 (Post방식으로 요청됨)");
    }
   
    /**
     * * destroy()
     *   1. 더이상 해당 Servlet이 서비스되지 않을 경우 실행됨
     *      ex) 서버 종료 / 소스코드 재컴파일
     *  
     */
    public void destroy() {
        System.out.println("destroy() 메소드 실행");
       
    }

}
 

 

 

- 클라이어언트 측에서 다음과 같은 URL 요청시(http://localhost:8888/servlet/life)

'/life'라는 url mapping 값을 가지는 서블릿 클래스가 자동으로 실행된다.

- 서블릿 클래스는 내부적으로 자동으로 실행되는 메소드 흐름(lifecycle)이 있다. <- 면접때 이걸 묻기도 함.

서블릿도 클래스기 때문에 생성자가 먼저 실행되고, 미리 약속된 메소드가 순차적으로 호출된다. (자동으로)

단, 최초요청 시에만 !!! (생성자, init()은 최초 요청시에만. service()는 요청이 들어올 때 마다.) 

- 서블릿이 더 이상 쓰이지 않을 때(서버 종료/소스코드 재컴파일) 서블릿 객체가 소멸된다.

- 서블릿 클래스들 이름에 빨간줄이 그어져있을 때가 있다.

프로젝트 우클릭 - properties - project facets에서 오른쪽 탭에서 runtimes에서 톰캣 체크를 해줘야 한다.


- 사용자의 요청정보가 HttpServletRequest 타입의 매개변수에 담기게 된다.

- HttpServletResponse 타입의 매개변수를 이용해서 사용자에게 응답할 수 있다.

 

- destroy() 메소드는 중간에 박혀있어서 젤 마지막으로 이동시켰다.

- doGet(), doPost() 메소드에 자동으로 코드가 적혀 있는데, service()를 쓸 때 그 두 메소드 내용을 다 지웠다.

- 화면단만 수정한 경우에는 굳이 서버를 재시작하지 않아도 되지만,

자바 코드를 수정한 경우에는 서버를 재시작해야한다.

 

 

 

 

 

 

 

ㅁ URL Mapping 등록 방법

 

 

(1) Servlet 클래스 상단에 @webServlet Annotation 활용

 

@WebServlet("URLMapping")

 

 

(2) WEB-INF/web.xml 파일에 Servlet 클래스 등록시 매핑

- 이 방식은 알고만 있으면 된다. 복잡해서. 그냥 어노테이션 방식 쓰면 된다.

 

<servlet>

    <servlet-name>LifeCycle</servlet-name>                (서블릿을 지칭할 이름)

    <servlet-class>a_lifecycle.LifeCycle</servlet-class>     (서블릿 경로)

</servlet>

<servlet-mapping>

    <servlet-name>LifeCycle</servlet-name>

    <url-patterns>/life</url-pattern>               (url mapping값)

</servlet-mapping>

 

 

 

 

 

ㅁ Servlet 

- 사용자의 요청을 받아 처리한 후 응답해주는 Java 클래스

- HttpServlet 클래스를 상속받아 구현해야 한다. 이 클래스의 풀네임은 javax.servlet.http.HttpServlet이다.  

- javax 패키지는 Tomcat이 제공하기 때문에 Tomcat이 연동되어 있어야 구현할 수 있다. 

- 간혹 Servlet 관련한 클래스에 빨간줄이 그어질 때가 있다. 어쩌구

- 동일한 애플리케이션 내에 동일한 URL Mapping값의 Servlet이 존재해서는 안 된다.

- 사용자의 요청시 Servlet 컨테이너가 작동되면서 해당 Servlet 클래스가 실행된다.

이때 미리 약속된 메소드가 호출되도록 되어있다.

그게 바로 LifeCycle이다. Servlet이 ~때 어떤 메소드가 ~ 어쩌구.

 

 

ㅁ Servlet LifeCycle

- 내가 직접 호출하는게 아니고 자동으로 호출되게 되어있음.

 

(1) 최초 요청일 경우 Servlet 객체가 생성 후 (생성자 실행) -> init() 메소드 호출.

최초 요청이 아닌 경우 Servlet 객체가 생성되지도 않고 init() 메소드가 실행되지도 않음.

 

(2-1) service() 메소드 호출

(2-2) doGet() 또는 doPost() 호출 (service() 메소드가 정의되어있지 않을 경우)

 

(3) 더이상 Servlet이 서비스되지 않을 경우 destroy()가 호출된다. 이 객체가 소멸된다는 소리다.

주로 서버가 종료(stop)되거나 자바 코드가 수정돼서 내부적으로 재 컴파일이 진행될 때 destroy 메소드가 호출되면서 객체가 소멸한다.

 

 

 

 

ㅁ 생성자

- Servlet 생성시 호출됨.

- 생성자 호출 이후에 자동으로 init() 메소드 호출됨.

 

 

ㅁ init() 메소드

- Servlet 클래스의 환경설정을 담당하는 메소드

- init() 메소드 호출 이후에 자동으로 service() 메소드가 호출된다.

service()메소드가 ~있지 않다면 자동으로 doGet() 혹은 doPost() 메소드가 호출된다.

 

 

ㅁ service() 메소드

- 클라이언트로부터 요청을 받을 수 있다. 그 요청정보가 HttpServletRequest 매개변수 어쩌구

요청을 보낸 클라이언트에게 응답할 수 있다. HttpServletResponse 매개변수를 사용해서 어쩌구

- service() 메소드가 있을 경우 여기서 요청과 응답을 처리한다.

service() 메소드가 없을 경우 doGet() 또는 doPost() 메소드가 요청방식에 따라 호출된다.

 

 

ㅁ destroy() 메소드

- 더이상 해당 Servlet이 서비스되지 않을 경우 실행됨.

ex)  서버 종료 / 소스코드 재컴파일 

 

 

 

자바코드를 수정한 경우에는 서버를 반드시 restart 해야 반영될 때가 많다. 재생버튼 누르면 종료되었다가 다시 시작함.

 

ㅁ 서버가 시작되었다는 것을 확인 했으면 콘솔창의 로그들을 좀 지운다.

- clear console 아이콘 클릭.

 

 

 

 

 

- 3개의 요청을 차례로 보내본다.

 

 

- 최초 요청시에만 Servlet 객체가 생성되고 init() 메소드가 실행된다. 

- 생성자와 init() 메소드 등이 아예 안뜬다면 서버 리스타트!

 

 

 

- 여전히 destroy() 메소드는 사용되지 않고 있다.

소스코드를 수정해본다. 썼다가 지우니까 destroy()가 호출되었다.

 

 

 

- destroy() 후에 다시 요청을 보내면 객체가 새로 생성된다.

한글자 정도로는 destroy() 호출이 안됨. 막 치면 바로 호출된다. 저장도 하고.

- 서버를 종료해도 destroy() 메소드가 실행된다.

 

- 원래 개발을 할 때는 서버를 멈추고 자바 코드를 써야 한다.

그런데 매번 멈췄다가 자바 코드쓰고 실행하는게 번거롭기 때문에 보통 서버를 킨 상태에서 개발을 한다.

그러면 소스코드를 수정하고 저장할 때마다 재컴파일이 진행된다.

 

 

 

 

 

 

ㅁ doGet()와 doPost() 메소드

- service() 메소드를 전체 주석처리하고 없다고 생각한다. 

위의 코드가 사실 이 형태다.

- service() 메소드가 전체 주석처리되어있지 않을 때는 doGet과 doPost 메소드는 그냥 텅 비어있는 상태였다.

 

 

 

ㅁ doGet()

- service() 메소드가 없을 경우 GET 방식 요청시 자동으로 호출된다.

- GET 방식 요청 케이스

(1) <a href='/servlet/life'>

- a 태그 클릭시.

- a 태그는 기본적으로 get방식이다.  

(2) <form action='/servlet/life' method='get'>

(3) location.href = '/servlet/life';           (자바 스크립트방식으로 url 요청)

(4) window.open('/servlet/life');            (팝업창)

 

(5) $.ajax({

    url : '/servlet/life',

    type : 'get',

    ...

});

- AJAX

 

 

ㅁ doPost()

- service() 메소드가 없을 경우 POST 방식 요청시 자동으로 호출된다.

- POST 방식 요청 케이스

(1) <form action='/servlet/life' method='post'>

(2) $.ajax({

    url : '/servlet/life',

    type : 'post',

    ...

});

 

 

 

 

- 1, 2, 3 요청을 순서대로 보내면 이렇게 출력됨. 

다시 1번 요청을 보내도 "doGet() 메소드 실행 (Get방식으로 요청됨)" 1줄만 출력됨.

 

- 흰 화면이 뜨는 것은 정상이다. 

현재 서블릿 실행만 시켰고 응답페이지를 돌려주지 않았기 때문.

 

 

 

===========

 

 

 

ㅁ 지금처럼 서블릿 클래스의 모든 메소드들을 다 둘 필요는 없고 doGet(), doPost() 메소드만 두고 작업할 예정이다.

- 왜냐면 서블릿이 생성됐을 때, init() 메소드, destroy() 메소드가 실행됐을 때 실행할 내용이 딱히 없다.

- 우리는 요청이 들어왔을 때 요청을 받아서 처리하고 응답해주면 되는데 그때 이제 필요한 메소드가 저 둘이다.

 

 

 

자바코드는 수정 후에, 반드시 서버를 restart 해야 한다.

ㅁ 아무리 서버를 재구동해도 문제가 없어보이는데도 계속 문제가 발생한다면,

서버를 잠시 멈추고 상단 메뉴 Project - clean 누르면 강제로 소스코드들이 재컴파일된다.

그리고 서버 다시 start하고 요청 보내보기.

 

 

 

 

ㅁ 다시 index 페이지로 왔다.

- http://localhost:8888/servlet/ 치면 된다. 

 

- 지금은 2를 클릭해도 아무데도 이동하지 않는다. 

 

 

- 아래와 같이 index.html을 작성한다.

 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <!-- web.xml 파일에서 welcome-file로 등록된 파일(메인페이지)  -->
    <h1>Servlet</h1>

    <!-- http://localhost:8888/servlet/a_lifecycle/main.html -->
    <a href="./a_lifecycle/main.html">1. Servlet 클래스의 LifeCycle</a> <br>
    <a href="./b_request/main.html">2. HttpServletRequest</a> <br>
    <a href="">3. HttpServletResponse</a> <br>
    <a href="">4. Forward</a> <br>
    <a href="">5. Redirect</a> <br>


</body>
</html>
 

 

- 정적인 페이지로 이동.

- 이후 b_request 폴더에 main.html 파일을 만든다. 

 

 

 

- 아래처럼 b_request 폴더에 main.html을 만든다.

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <h2>HttpServletRequest 확인</h2>
   
</body>
</html>
 

 

 

 

- index.html, main.html을 "저장"하고, 브라우저창 가서 http://localhost:8888/servlet/을 "새로고침"하고,

2를 누르면 아래처럼 뜬다.

 

 

 

 

 

 

 

ㅁ Get 방식의 특징

- 요청시 전달되는 데이터가 URL의 Header 영역에 포함되어 전달된다.

URL에 데이터가 노출되기 때문에 보안 유지가 불가능하다.

- Header 영역은 전송하는 길이에 대해 제한이 있다.

방대한 데이터를 전송할 경우 초과된 데이터가 절단되어서 넘어감.

- 단, 해당 URL을 즐겨찾기(북마크)할 경우 동일한 데이터를 넘기면서 재요청이 가능하다.

기존에 봤던 페이지를 다시 볼 수 있다.

 

- Get 방식에 적합한 경우 : 검색요청

- Get 방식에 부적합한 경우 : 로그인 요청, 회원가입 요청, 게시판 작성 및 수정 요청(방대한 데이터)

 

- 게시글 내용같은거 get 방식으로 하면 안 된다. 내용은 엄청 길어서.

방대한 데이터를 넘길 때는 get방식으로 넘기면 안 된다.

 

 

- 아래처럼 b_request 폴더에 main.html을 작성한다.

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <h2>HttpServletRequest 확인</h2>
   

    <h4>Get 방식 요청</h4>

        <a href="/servlet/request?name=홍길동&age=20&hobby=sports&hobby=reading">요청1</a>
 

</body>
</html>
 

 

 

- 아까까지는 그냥 서블릿 요청만 했다면, 이번엔 요청시 강제로 전달값도 같이 전달 해본다.

- /request라는 url mapping 값을 가지는 서블릿 클래스는 아직 없지만, 그걸 실행한다. 값을 저렇게 넘기면서.

- 물음표 뒤는 키=밸류 세트로 넘어가는 데이터.

 

 

 

- 이클립스에서 src/main/java에 b_request라는 패키지를 만든다.

그리고 그 안에 servlet을 만든다. /request 매핑값을 가지는 Request라는 이름의 Servlet 클래스.

 

package b_request;

 

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;

 

 

 

@WebServlet("/request")

public class Request extends HttpServlet {

 

     private static final long serialVersionUID = 1L;

 

     public Request() {

         super();

     }

 

     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 

     }

 

     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 

     }

 

}

 

 

- 아무것도 체크 안해서 이것만 있다. 사실 doGet과 doPost만 있으면 된다.

- 기존에 doGet과 doPost에 적혀있는 코드는 다 지웠다!

 

 

 

 

ㅁ <  HttpServletRequest >

- 클라이언트의 요청관련 정보가 담겨있는 객체

- doGet() 또는 doPost() 메소드가 실행시 해당 객체가 생성돼서 매개변수(request)에 전달됨.

그래서 이 객체로부터 메소드 호출시 데이터(요청과 관련된 정보)를 꺼낼 수 있다.

request 객체에 요청 관련된 데이터들이 담겨있다.

 

 

- 요청 관련 주요 메소드

    

(1) getContextPath()          :   애플리케이션의 contextPath 반환

(2) getRequestURI()           요청 URL의 contextPath + URLMapping값 반환

(3) getRequestURL()         :   요청 URL의 전체 경로 반환

(4) getParameterMap()      :   요청에 포함된 parameter들을 Map<String, String[]> 로 반환

(5) getParameter(String)    :   요청에 포함된 parameter 특정 데이터를 "문자열"로 반환

(6) getPrameterValues(String)         :  요청에 포함된 parameter 다수의 데이터들을 문자열 배열로 반환

(7) setCharacterEncoding(String)    :  요청에 포함된 parameter들의 인코딩을 설정하는 메소드

 

- (1), (5), (6), (7)은 자주 쓴다. 

- (4)는 key는 String, value는 String[]로 되어 있다. 

뭐 가수의 파라미터들을 map 객체 통째로 받아보겠다 할 때는 getParameterMap() 메소드를 사용한다.

- (5), (6)은 어떤 데이터를 꺼낼건지 그 key를 제시해야한다.

 

 

 

- parameter(파라미터 = 매개변수)는 요청시 전달되는 값을 의미한다.

사용자가 입력한 값도 되고 직접 전달되는 값도 된다.

 

http://host:port/contextPath/URLMapping?param=value&param=value

 

 

- 모든 파라미터는 String 타입이다. 숫자여도 문자열의 형식으로 온다.

웹상에서 데이터를 주고받을 때는 문자열의 형식으로만 데이터를 주고받을 수 있다.

 

- 파라미터를 반환하는 메소드를 사용했는데 전달되는 파라미터 자체가 존재하지 않으면 null을 반환한다. 

- 파라미터를 반환하는 메소드를 사용했는데 파라미터 key는 있고 값이 존재하지 않을 경우 빈 문자열을 반환한다.

 

 

 

 

package b_request;

 

import java.io.IOException;

import java.util.Arrays;

 

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

 

@WebServlet("/request")

public class Request extends HttpServlet {

 

    private static final long serialVersionUID = 1L;

 

     public Request() {

          super();

     }

 

     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 

          System.out.println("doGet() 메소드 실행");

 

          System.out.println("contextPath: " + request.getContextPath());

          System.out.println("URI: " + request.getRequestURI());

          System.out.println("URL: " + request.getRequestURL());

 

          // name=홍길동&age=20&hobby=sports&hobby=reading

          // name=&age=

          String name = request.getParameter("name"); // "홍길동"  |  ""

          int age = Integer.parseInt(request.getParameter("age")); // "20" => 20  |  "" => NumberFormatException

          System.out.println("param(name) : " + name);

          System.out.println("pram(age) : " + age);

 

          String[] hobbyList = request.getParameterValues("hobby"); // ["sports", "reading"]  |  null

          System.out.println("param(hobby) : " + Arrays.toString(hobbyList));

 

          System.out.println("--------------------------------------");

 

     }

 

     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 

     }

 

}

 

- 빈문자열을 파싱하면 NumberFormatException 오류발생한다.

 

 

 

- 여기서 2 눌러서

 

- 요청1을 누른다.

 

 

- 이클립스 콘솔에 이렇게 뜸.

- http://localhost:8888/servlet/request?name=홍길동&age=20&hobby=sports&hobby=reading 에서

name, age, hobby 등을 브라우저 주소창에서 임의로 수정하고 다시 요청1을 누르면

 

 

 

- 이렇게 요청 관련 데이터를 뽑아서, 여기에서 서비스 호출하고, dao 호출해서 DB에 INSERT 과정을 진행한다. 

여기서부터는 나중에 jdbc가 쓰여질 예정이다. mvc 패턴으로.

지금 이건 컨트롤러 단이라고 보면 된다. 서블릿 클래스는. 

 

 

 

 

======================================

 

 

 

ㅁ 보통은 사용자에게서 입력값을 받음.

사용자에게 입력받은 데이터를 넘긴다.

 

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <h2>HttpServletRequest 확인</h2>
   

    <h4>Get 방식 요청</h4>

        <a href="/servlet/request?name=홍길동&age=20&hobby=sports&hobby=reading">요청1</a>
 

        <form action="/servlet/request" method="get">
            이름 : <input type="text" name="name"> <br>  <!-- key 값을 부여 해줘야 값이 넘어간다. -->
            나이 : <input type="number" name="age"> <br>
            취미 :
            <input type="checkbox" name="hobby" value="sports"> 운동
            <input type="checkbox" name="hobby" value="reading"> 독서
            <input type="checkbox" name="hobby" value="movie"> 영화
            <br><br>

            <input type="submit" vlaue="요청2">
        </form>



</body>
</html>
 

 

 

- 참고로 텍스트 상자는 기본적으로 문자열이 작성되어있다.

그래서 입력하지 않은 상태에서 요청시에는 빈 문자열이 들어온다. key는 있고 value는 비어있다.

- input type="submit" 버튼의 값을 변경시키려면 value속성을 쓴다.

 

2 고르고

 

 

- 작성하고 제출하면 브라우저 주소창에

http://localhost:8888/servlet/request?name=김김김&age=20&hobby=sports&hobby=reading 이 뜬다.

- 필수 요청사항을 뭐 required로 둔 것은 아니기에 이름을 비우고 제출하면 "name=" 이렇게 뜬다.

체크박스를 비우고 제출하면 아예 안 뜬다. 왜냐면 체크된 것의 key가 넘어가기 때문에. null이 반환된다.

 

 

- 나이를 비우고 제출하면 500 에러가 뜬다.

500 에러는 자바 코드 문제다. 오류 내용은 콘솔에서도 확인가능하다.

- 원래는 조건검사를 해야 한다. 저게 빈문자열인지 아닌지를 먼저.

- 해당하는 url mapping값을 가지는 서블릿이 없으면 404 에러가 뜬다.

 

 

ㅁ 깃허브에 프로젝트 폴더만 올려야 한다.

- Servers 폴더나 META-INF 폴더가 있으면 안 된다. 프로젝트 폴더만 있어야 한다.

- gitignore, readme, 텍스트 파일은 상관 없음.

 

 

====================================

 

 

ㅁ url 요청시에는 반드시 요청한 애플리케이션의 contextPath가 누락되어서는 안 된다.

- contextPath 뒤에 정적인 페이지의 경로를 줘도 되고, Servlet의URLMapping을 줘도 된다.

- http://localhost:8888/contextPath/정적인페이지의경로

- http://localhost:8888/contextPath/Servlet의URLMapping

 

 

ㅁ 상대경로와 절대경로 두 가지 방식으로 servlet 요청하기

 

 

ㅁ 상대경로와 절대경로 두 가지 방식으로 정적페이지 요청하기

 

 

ㅁ URL에 ?key=value 형식으로 추가된 부분을 **쿼리 스트링(Query String)**이라고 합니다.

- GET 요청에서 클라이언트가 서버에 데이터를 전달하기 위해 사용됩니다.

 

 

 

ㅁ < Post 방식 특징 >

- 요청시 전달되는 데이터가 URL의 Body 영역에서 포함돼서 전달

- URL에 데이터가 노출되지 않는다. 보안 유지 가능하다.

- Body 영역은 전송하는 길이에 대한 제한이 없다. 방대한 데이터를 전송할 수 있다.

- 단, 즐겨찾기 후 재요청시 기존의 데이터가 넘어가지 않는다.

기존에 보던 페이지를 다시 바로 볼 수 없다.

- Get 방식에 비해 상대적으로 처리 속도가 느리다.

페이지 요청시 기다리는 시간이 소요될 수 있다.

 

- Post 방식에 적합한 경우       : 로그인 요청, 회원가입 요청, 게시판 작성 및 수정 요청(방대한 데이터 전송 가능하니까)

- Post 방식에 부적합한 경우   : 검색 요청

 

 

 

- 아래처럼 b_request 폴더의 main.html을 작성한다.

 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <h2>HttpServletRequest 확인</h2>
   

    <h4>Get 방식 요청</h4>

        <a href="/servlet/request?name=홍길동&age=20&hobby=sports&hobby=reading">요청1</a>

        <form action="/servlet/request" method="get">
            이름 : <input type="text" name="name"> <br>  <!-- key 값을 부여 해줘야 값이 넘어간다. -->
            나이 : <input type="number" name="age"> <br>
            취미 :
            <input type="checkbox" name="hobby" value="sports"> 운동
            <input type="checkbox" name="hobby" value="reading"> 독서
            <input type="checkbox" name="hobby" value="movie"> 영화
            <br><br>

            <input type="submit" vlaue="요청2">
        </form>
    <hr>



   
    <h4>Post 방식 요청</h4>

    <form action="/servlet/request" method="post"> <!-- method만 get에서 post로 바꿨다. -->
        이름 : <input type="text" name="name"> <br>  <!-- key 값을 부여 해줘야 값이 넘어간다. -->
        나이 : <input type="number" name="age"> <br>
        취미 :
        <input type="checkbox" name="hobby" value="sports"> 운동
        <input type="checkbox" name="hobby" value="reading"> 독서
        <input type="checkbox" name="hobby" value="movie"> 영화
        <br><br>

        <input type="submit" vlaue="요청3">
    </form>



</body>
</html>
 

 

 

- 이후 이클립스로 넘어와서 비어있는 doPost메소드 작성. 

 

 

 

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

 

System.out.println("doPost() 메소드 실행"); // 이것만 doGet()에서 doPost()로 바꿈. 아래는 다 동일.

 

System.out.println("contextPath: " + request.getContextPath());

System.out.println("URI: " + request.getRequestURI());

System.out.println("URL: " + request.getRequestURL());

 

// name=홍길동&age=20&hobby=sports&hobby=reading

String name = request.getParameter("name"); // "홍길동"

int age = Integer.parseInt(request.getParameter("age")); // "20" => 20

System.out.println("param(name) : " + name);

System.out.println("pram(age) : " + age);

 

String[] hobbyList = request.getParameterValues("hobby"); // ["sports", "reading"]

System.out.println("param(hobby) : " + Arrays.toString(hobbyList));

 

System.out.println("--------------------------------------");

 

}

 

 

 

- vscode에서 라이브서버로 열지 않고 localhost:8888/servlet/를 주소창에 입력하면 메인페이지가 뜬다.

 


- 메인페이지에서 2를 누르면 단순 정적 페이지를 요청한다.

 

 

- Post방식으로 이름, 나이, 취미를 입력후 제출.

응답페이지는 작성안해서 흰색 빈 화면 뜨는게 정상이다.

url에 localhost:8888/servlet/request 밖에 없다. 뒤에 쿼리 스트링이 없다.

- 이클립스에서는 그런데 한글이 문제다. 숫자나 영문은 괜찮다. 

post방식에서 요청보내면 데이터 뽑을때 한글이 문제다. 인코딩 문제. 

post방식에서 데이터를 뽑을 때는 인코딩 작업을 해야 한다.

 

 

 

ㅁ < Post 방식 요청일 경우 >

- 파라미터들이 URL의 Body 영역에 포함되어 넘어온다.

- 별도의 인코딩 처리를 해야 한다.

- 유의사항 : 파라미터(데이터)를 뽑기 전에 setCharacterEncoding() 메소드를 이용해서 인코딩 처리를 해야 한다.

- 영문과 숫자 데이터만 넘어올 때는 인코딩 작업을 안해도 되지만 안전하게 해주는 것이 좋다. 

 

- 이클립스 코드를 수정하고 똑같이 입력 후 제출 해보면 이렇게 나옴.

 

 

- 잘 돼다가 갑자기 안되는 경우.

404 servlet/request를 뭐 찾을 수 없다. 

이런 경우에는 오류 메시지를 봐야함.

/request라는 매핑값을 가지는 servlet 클래스를 찾을 수가 없다. 

- 근데 있다면 소스코드 재컴파일이 뭔가 안되는거.

상단 project - clean을 주기적으로 해주는게 좋다. 

서버 restart도!