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

JSP/SERVLET 정리

by moca7 2024. 9. 21.

 

[1.SERVLET]

[2.JSP]

[3.Servlet과 JSP 결합]

 

 

 

 

[1.SERVLET]


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

 


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

- 개발이 끝나고 서버에 배포가 되는 실 서버는 사용자들이 24시간 이용할 수 있게 24시간 열려 있다. 

- 지금 우리는 개발서버를 뒀다. 개발 서버는 스타트를 해줘야 접속할 수 있다.

 


ㅁ 화면구현 파일 열어보기

- http://localhost:8888/servlet/a_lifecycle/main.html를 브라우저에 입력하면 방금 우리가 만든 main.html 문서가 보인다.
- .html뿐 아니라 .jsp 파일도 이렇게 열어볼 수 있다.

- 그런데 <a href="http://localhost:8888/servlet/a_lifecycle/main.html">는 너무 길다.
사실 이미 index.html을 보고 있을 때 contextPath까지는 이미 기술이 되어 있는 거다.
그래서 그냥 <a href="a_lifecycle/main.html">만 써도 된다. (절대경로 방식)

 

 


ㅁ Servlet

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

 

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

 

 

 

 

ㅁ 요청
- 요청을 보낸다는 것은 a 태그를 클릭해서 요청을 보낼 수도 있고,
form 태그를 둬서 사용자에게 입력을 받아서 요청을 보낼 수도 있다.


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

 

 

 

 

< Get 방식의 특징 >


- 요청시 전달되는 데이터가 URL의 Header 영역에 포함되어 전달된다.
URL에 데이터가 노출되기 때문에 보안 유지가 불가능하다.
- Header 영역은 전송하는 길이에 대해 제한이 있다.
방대한 데이터를 전송할 경우 초과된 데이터가 절단되어서 넘어감.
- 단, 해당 URL을 즐겨찾기(북마크)할 경우 동일한 데이터를 넘기면서 재요청이 가능하다.
기존에 봤던 페이지를 다시 볼 수 있다.
 
- Get 방식에 적합한 경우 : 검색요청
- Get 방식에 부적합한 경우 : 로그인 요청, 회원가입 요청, 게시판 작성 및 수정 요청(방대한 데이터)

- 게시글 내용같은거 get 방식으로 하면 안 된다. 내용은 엄청 길어서.
방대한 데이터를 넘길 때는 get방식으로 넘기면 안 된다.

 

 

 

 

ㅁ < Post 방식 특징 >

- 요청시 전달되는 데이터가 URL의 Body 영역에서 포함돼서 전달
- URL에 데이터가 노출되지 않는다. 보안 유지 가능하다.
- Body 영역은 전송하는 길이에 대한 제한이 없다. 방대한 데이터를 전송할 수 있다.
- 단, 즐겨찾기 후 재요청시 기존의 데이터가 넘어가지 않는다.
기존에 보던 페이지를 다시 바로 볼 수 없다.
- Get 방식에 비해 상대적으로 처리 속도가 느리다.
페이지 요청시 기다리는 시간이 소요될 수 있다.

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

 




 

 

ㅁ 단순 페이지 요청이 아닌 Sevlet을 요청해본다.
- url에 서버를 작성하고, 어플리케이션을 작성하고, URLMapping을 쓸 수 있다.
URLMapping이 곧 서블릿을 가리킨다.

 

 


ㅁ URLMapping
- 웹 애플리케이션 내부 경로를 의미 (즉, 이 웹 어플리케이션이 가지고 있는 서블릿 같은 걸 지칭할 수 있다.)

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

- URLMapping을 작성할 때 절대경로방식으로 작성한다면 슬래시로 시작한다.
슬래시로 시작하는 구문을 절대경로방식이라고 한다.
- 절대경로 방식은 서버(ip주소:포트번호)까지만 가리킨다. 그래서 슬래시(/) 뒤에 context path를 작성한다.

 

 

※ 이 둘은 같다.
- http://localhost:8888/servlet/life
- /servlet/life 

 

 

 

 

ㅁ 메인페이지

- <a href="/servlet">홈으로 가기</a>

이렇게 context path까지 작성하면 메인페이지가 보여진다.

(web.xml에 작성되어 있기 때문에)

 

 

 


ㅁ Servlet 파일 생성
서블릿은 java 클래스이기 때문에 src/main/java에 만든다.
- 패키지를 우클릭하고 new - Servlet을 클릭한다. 
- 서블릿도 클래스이기 때문에 클래스 이름을 준다. LifeCycle이라고 짓고 Next를 누른다.

 

 


Servlet LifeCycle
- 1) 최초 요청일 경우 Servlet 객체 생성(생성자) => init() 메소드 호출
- 2_1) service() 메소드 호출
- 2_2) doGet() 또는 doPost() 호출 (service()메소드가 정의되어있지 않을 경우)
- 3) 더이상 Servlet이 서비스되지 않을 경우 destroy() 호출
(주로 서버종료 / 재컴파일시)

 

 



ㅁ service() 메소드


- 클라이언트로 부터 요청을 받을 수 있음 (HttpServletRequest 매개변수)
클라이언트로 응답할 수 있음           (HttpServletResponse 매개변수)


- service() 메소드가 있을 경우 여기서 요청과 응답을 다 처리함 (doGet, doPost 메소드가 있어도)
- service() 메소드가 없을 경우 doGet() 또는 doPost() 메소드가 "요청방식에 따라 호출됨"


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

 

 



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

 


※ GET 방식 요청 케이스


(1) a 태그 

 <a href='/servlet/life'>
- a 태그는 기본적으로 get방식이다.


(2) form 태그 (method='get')

<form action='/servlet/life' method='get'>


(3) 자바 스크립트방식으로 url 요청

location.href = '/servlet/life';


(4) 팝업창

window.open('/servlet/life');            


(5) ajax

$.ajax({
    url : '/servlet/life',
    type : 'get',
    ...
});


 


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

 


※ POST 방식 요청 케이스


(1) form 태그

<form action='/servlet/life' method='post'>

(2) ajax

$.ajax({
    url : '/servlet/life',
    type : 'post',
    ...
});



 

ㅁ 지금처럼 서블릿 클래스의 모든 메소드들을 다 둘 필요는 없고 doGet(), doPost() 메소드만 두고 작업할 예정이다.
- 왜냐면 서블릿이 생성됐을 때, init() 메소드, destroy() 메소드가 실행됐을 때 실행할 내용이 딱히 없다.
우리는 요청이 들어왔을 때 요청을 받아서 처리하고 응답해주면 되는데 그때 이제 필요한 메소드가 저 둘이다.


 


수시로 서버 재시작, project-clean, 브라우저 새로고침

- 아무리 서버를 재구동해도 문제가 없어보이는데도 계속 문제가 발생한다면,
서버를 잠시 멈추고 상단 메뉴 Project - clean 누르면 강제로 소스코드들이 재컴파일된다.
그리고 서버 다시 start하고 요청 보내보기.
- 화면단만 수정한 경우에는 굳이 서버를 재시작하지 않아도 되지만,
자바 코드를 수정한 경우에는 서버를 재시작해야한다.

 

 

 



ㅁ <a href="/servlet/request?name=홍길동&age=20&hobby=sports&hobby=reading">
- 아까까지는 그냥 서블릿 요청만 했다면, 이번엔 요청시 강제로 전달값도 같이 전달 해본다.
- 물음표 뒤는 키=밸류 세트로 넘어가는 데이터로 쿼리 스트링(query string)이라고 한다.
(get 방식의 경우다. url이 보이는 경우니까)




ㅁ < HttpServletRequest >
클라이언트의 요청관련 정보가 담겨있는 객체
doGet() 또는 doPost() 메소드가 실행시 해당 객체가 생성돼서 매개변수(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)은 자주 쓴다. 
(5), (6)은 어떤 데이터를 꺼낼건지 그 key를 제시해야한다.

 



parameter(파라미터 = 매개변수)는 요청시 전달되는 값을 의미한다.
- 사용자가 입력한 값도 되고 직접 전달되는 값도 된다.

모든 파라미터는 String 타입이다. 숫자여도 문자열의 형식으로 온다.
웹상에서 데이터를 주고받을 때는 문자열의 형식으로만 데이터를 주고받을 수 있다.

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



- 빈문자열을 파싱하면 NumberFormatException 오류발생한다. (String을 int형으로 parsing시 주의)

 


name 속성으로 key 값을 부여 해줘야 값이 넘어간다.


텍스트 상자는 기본적으로 문자열이 작성되어있다.
그래서 입력하지 않은 상태에서 요청시에는 빈 문자열이 들어온다.
checkbox로 같은 key 값으로 여러개의 값이 넘어오면 String[]로 넘어온다.

 

 



ㅁ 에러
- 500 에러는 자바 코드 문제다.

- 404 오류가 뜨는 이유는 서블릿을 못 찾을 거나 이동할 경로(html 페이지)를 못찾는 경우다.

대부분 오타다. 특히 대소문자.

서블릿 annotation과 포워드 메소드 getRequestDispatcher(이동할경로)에 오타가 없는지 체크한다. 

 



 

ㅁ 서블릿 or 정적 페이지

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

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

 

 

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

- 상대경로 : <a href="../../../test1">상대경로방식</a>

- 절대경로 : <a href="/servlet/test1">절대경로방식</a>

 

 

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

- 상대경로 : <a href="../../abc/main.html">상대경로방식</a>

- 절대경로 : <a href="/servlet/abc/main.html">절대경로방식</a>

 

 

 

 

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

request.setCharacterEncoding("UTF-8");

 

 

 

ㅁ 서블릿 활용 과정

- request 객체에서 데이터를 뽑고, 뽑은 데이터를 가지고 DB에 쿼리문을 실행한다.

- data를 service를 호출하면서 넘기고, service에서는 dao로 넘기고, dao에서 insert문 때려서 그 결과를 돌려받는다.

(jdbc과정. 서블릿이 controller단이다.)

- 성공적으로 다 되었다면 응답페이지를 제작해서 돌려줘야 한다.

요청에 대한 결과 페이지를 사용자에게 보여줘야한다.

 

 

 

 

 

 

 

 

ㅁ < HttpServletResponse >

- 요청을 보낸 클라이언트에게 응답할 수 있는 객체

- doGet() 또는 doPost() 메소드 실행시 해당 객체가 생성되어 매개변수(response)에 전달

 

 

- 응답 관련 주요 메소드

 

1) getWriter()                               :    클라이언트에게 응답문자를 전송할 수 있는 출력 스트림(PrintWriter 타입) 반환

2) setContentType(String)              응답문자의 데이터 형식(MIME-TYPE)을 설정

3) sendRedirect(String)               :    리다이렉트할 URL 전송 

 

- getWriter()는 통로다. 응답 데이터를 전달하려면 클라이언트와 연결된 통로가 필요하다. 

출력 스트림을 통해 클라이언트에게 응답 데이터를 전달한다. 

- ContentType이라고도 하고 MIME-TYPE이라고도 한다. 문자의 유형. 데이터 형식.

- 3)은 Redirect.

 

 

 

ㅁ 지금 화면 구현을 서블릿에서 out.println("")으로 하고 있는데, JSP 배우면 응답페이지 제작 과정을 JSP에 위임함.

- response 객체를 이용해서 한땀한땀 사용자에게 응답페이지를 보여줄 수도 있지만,

너무 번거롭기 때문에 JSP 배우면 응답 페이지 제작 과정은 JSP에게 위임한다.

 

 

 

ㅁ 포워드 하는 구문

- request.getRequestDispatcher("이동할경로").forward(request, response);

- context path는 빼고 url mapping만 이동할경로에 작성하면 된다

 

 

ㅁ 첫번째 목적지에서 포워딩시 request, response를 두번째 도착지로 전달했다.

- 그래서 doGet 메소드에 각각 대입되어있다.

- 첫번째 목적지에서 넘어온 파라미터를 두번째 서블릿의 doGet 메소드에서 고스란히 꺼낼 수 있다.

 

- forward는 요청의 방식을 유지하므로, GET이든 POST든 원래 요청된 방식을 그대로 사용합니다.

처음 get방식으로 서블릿을 요청했으면 forward로 이동한 서블릿에서도 doGet 메소드만 호출됨.

 

- forward로 이동한 경로(second)는 보이지 않는다.

 

 

 

 

ㅁ 서블릿이 실행되는 경우 3가지

(1) 클라이언트 요청에 의해서 (a, form submit 등)

(2) 서블릿에서 또다른 서블릿으로 "이동"할 경우 (forward)

(3) 서블릿에서 또다른 서블릿을 "재호출"할 경우 (redirect)    <-    url을 다시 강제로 호출

 

 

 

ㅁ < forward >

- 특정 처리를 대신할 Servlet 및 JSP로 이동시 사용하는 기술

주로 응답페이지 제작하는 과정을 JSP에게 위임할 때 사용할 예정

 

- 이동 경로 작성시 contextPath를 제외하고 작성한다.

 

- ★★★ URL에는 forward된(이동된) 경로가 노출되지 않는다. ★★★

클라이언트에게 이동한 경로를 숨길 수 있다. 최초 요청한 서블릿의 url mapping값만 보여진다.

 

 

 

ㅁ 주로 forward 하는 경우

1) 단순히 페이지 이동할 때

- 경로작성해서 그냥 이동해도 되지만 url이 노출되니까 보안상 위험해서 이동한 경로를 숨기고자 할 때.

- 그냥 링크로 이동해도 되는데, 서블릿을 호출해서, 거기서 포워드 메소드로 페이지로 이동.

2) select 쿼리 이후 

- 조회 이후 forward를 굉장히 자주한다. db로부터 데이터를 조회 후 페이지로 이동할 때 forward 한다.

 

 

 

ㅁ 버튼에 클릭 이벤트 핸들러를 연결한다.

 

document.getElementById("writebtn").addEventListener("click", function() {

    location.href = '/servlet/e_redirect/boardWrite.html';

})

 

- location.href는 현재 페이지의 URL을 설정하는 속성입니다.

이 속성에 새로운 URL을 할당하면, 웹 브라우저는 해당 URL로 페이지를 이동합니다.

- location.href와 forward 모두 기존에 있던 페이지에서 다른 페이지로 이동하는 것을 의미합니다. 하지만 그 동작 방식결과가 다릅니다.

- location.href는 항상 GET 요청이다.

이동하는 페이지 주소가 그대로 노출된다.

새로운 페이지로 이동할 때 이동하는 URL이 그대로 브라우저의 주소창에 노출됩니다.

 

 

 

ㅁ db로부터 조회할 데이터 없는 단순 페이지 이동이라하더라도 서블릿을 호출해서 포워딩 방식으로 이동하는게 제일 좋다.

- URL에 해당 애플리케이션 내부 디렉토리가 노출되기 때문이다.

- location.href = '/servlet/e_redirect/boardWrite.html'; 대신 location.href = '/servlet/writeForm.bo';

 

 

 

ㅁ redirect

- forward 방식은 서버 내부에서만 요청을 전달하기 때문에, 클라이언트의 새 요청이 발생하지 않습니다.

- db에 insert하고 새로 추가된 데이터를 다시 조회해서 뿌릴 때는 forward 방식 대신 redirect를 사용한다.

- request.getRequestDispatcher("/e_redirect/boardList.html").forward(request, response); 대신

response.sendRedirect("/servlet/list.bo"); // => list.bo의 Servlet을 재실행 (재요청)

 

- DB로부터 데이터를 조회해서 해당 페이지로 이동하는 Servlet이 이미 존재함. 해당 서블릿을 재호출하면 된다.

 

 

 

 

 

 

ㅁ < redirect >

- 기존에 정의해둔 Servlet을 재실행 시키는 개념 (URL 요청과 동일)

- 등록 및 수정/삭제 후에 다시 조회 페이지를 요청할 때 주로 사용함

- redirect 시 현재 서블릿에 존재하는 request, response를 전달하지 않음.

서블릿이 새로 실행되는 것이기 때문에 저 객체들도 다시 생성된다.

 

- 요청할 URL 작성시 contextPath부터 작성

 

    response.sendRedirect("/servlet/list.bo");           <- 이 경로가 보여지게 된다.

 

- 클라이언트 측에서 redirect된 경로(최종 목적지)를 확인할 수 있음

URL에 현재 redirect한 URL이 보여진다.

 

- 주로 redirect 하는 경우

1) insert 쿼리 이후 => 게시글의 전체 조회 페이지 redirect

2) update 쿼리 이후 => 게시글의 상세 조회 페이지 redirect

3) delete 쿼리 이후 => 게시글의 전체 조회 페이지 redirect

 

 

 

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

 

 

 

[2.JSP]

 

 

 

ㅁ < Servlet > 

- 사용자의 요청을 받아 처리한 후 "자바코드를 이용해서 HTML을 작성"해서 응답해주는 Java 클래스

- 즉 Java 베이스에 HTML을 구현함

out.println 문으로 출력하면 화면에 출력된다.

 

 

- 단점

(1) 복잡한 웹 화면을 구현하기 어려움

(2) 비즈니스 로직과 프리젠테이션 로직이 같이 기술되어 있어 유지보수가 불편하다.

그래서 나온게 JSP다.

 

 

 

 

ㅁ < JSP >

- Java Server Page

- HTML 베이스에 Java 코드를 작성할 수 있다. (즉 서블릿과 반대. <- 근데 얘도 서블릿임)

 

- 장점

(1) HTML 기반이기 때문에 웹 화면을 보다 쉽게 구현 가능하다.

(2) 비즈니스 로직(Java)과 프리젠테이션 로직(HTML)을 분리해서 관리할 수 있다.

- 개발자는 오직 비즈니스 로직에 집중하고, 퍼블리셔들은 프리젠테이션 로직에만 집중하게 분리 가능하다.

 

 

= 이제부터 페이지는 html이 아닌 JSP로 만든다.

 

 

 

 

- HTML comment <!-- -->는 Java 코드 및 JSP 관련 구문을 주석처리 할 수 없지만

JSP comment <%-- --%>는 Java 코드 및 JSP 관련 구문을 주석처리할 수 있다.

- jsp 주석은 jsp 파일에서만 쓸 수 있다. jsp 파일에선 웬만해선 jsp 주석을 쓰는게 좋다.

 

 

 

 

 

ㅁ JSP 스크립팅 원소 (Scripting Elements)

- jsp에서 java 코드를 기술할 수 있게 해주는 표현법.

 

 

(1)스크립틀릿 (Scriptlet)

- Java 코드 작성시 사용하는 기본 표현법

- 변수 선언, 제어문(조건문, 반복문) 등 작성

- <% Java 코드작성 %>

 

 

(2) 표현식 (Expression)

- Java에서의 값(변수에 담긴 값, 메소드호출을 통해 반환되는 값)을 출력할 때 사용

- 표현식 안에 메소드 호출구문 작성시 ; 찍어서는 안됨                            //     호출이 되어버림

- <%= Java값 %>

 

-  <%= sum %>하면 내부적으로  <% out.println(sum); %>이다.

 

 

 

 

<% String[] name = {"가가가", "나나나", "다다다", "라라라"}; %> 

- 배열에 담긴 값 : <%= String.join("-", name) %>   

- 배열에 담긴 값 : 가가가-나나나-다다다-라라라

 

 

 

 

 <%-- for문 활용 (반복적으로 요소 생성) --%>

 

    <ul>

        <% for(int i=0; i<name.length; i++) { %>

            <li><%= name[i] %></li>

        <% } %>

    </ul>

 

 

 

ㅁ  <%-- if문 활용 (선택적으로 요소 생성) --%>

 

    <% if(sum >= 10) { %>

      <b>덧셈결과가 10이상입니다.</b>

    <% }else { %>

        <i>덧셈결과가 10미만입니다.</i>

    <% } %>

 

- 문구만 출력하는 거면 out.println()으로도 되겠지만 b 태그와 i 태그를 출력하고 있다. 

- if문으로 선택적으로 요소를 생성시킨 것이다.

 

 

 

 

ㅁ JSP 지시어 (Directives)

- JSP_Page Directive
- JSP_Include Directive

- 나머지 JSP 지시어와 JSP 액션태그는 세미 이후에 배운다.

 

- <%@ 다음에 page가 붙으면 page 지시어고, include가 붙으면 include 지시어고, taglib이 붙으면 taglib 지시어다.

 

 

 

 

 

ㅁ 페이지 지시어

- jsp 파일은 항상 상단에 <%@   %>가 있다. 이게 페이지 지시어다. 이미 만들어져 있다.

- 현 jsp 페이지에 대한 정보(각종 속성)를 표현하고 있는 부분이다. 

- <%@ page 속성="값" 속성="값" ...%>

 

 

<%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding="UTF-8"%>

 

 

 

 

(1) import문

- <%@ page import="java.util.Date"%>

- import="java.util.List, java.util.ArrayList" 이렇게 컴마로 여러개 기술도 가능하지만 import는 한 줄씩 따로 쓰는게 좋다.

 

 

(2) 에러페이지

- <%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding="UTF-8" errorPage="/b_page_directive/error500.jsp" %>

 

- 이러면 이 페이지에서 에러가 발생하면 화면에 저 경로에 제작해 놓은 에러페이지가 보여진다. 

- 그런데 이렇게 하지 않고 web.xml에 여러개의 에러페이지를 메인페이지처럼 한번에 등록해놓을 수 있다.

 

 

 

 

ㅁ web.xml에 에러페이지 추가하기

 

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">

  <display-name>02_jsp</display-name>

  <welcome-file-list>

    <welcome-file>index.html</welcome-file>

    <welcome-file>index.jsp</welcome-file>

    <welcome-file>index.htm</welcome-file>

    <welcome-file>default.html</welcome-file>

    <welcome-file>default.jsp</welcome-file>

    <welcome-file>default.htm</welcome-file>

  </welcome-file-list>

 

  <error-page>

    <error-code>500</error-code>

    <location>/b_page_directive/error500.jsp</location>

  </error-page>

 

  <error-page>

    <error-code>404</error-code>

    <location>/b_page_directive/error404.jsp</location>

  </error-page>

 

</web-app>

 

 

 


ㅁ include 지시어

- 애플리케이션의 어떤 페이지든 항상 header랑 footer는 존재해야 한다.

section에는 그 페이지에서 보여줘야할 내용이 출력된다.

- header랑 footer는 매 페이지마다 동일하게 보여진다.

그렇다고 매 페이지마다 header와 footer 페이지를 만들 필요는 없다. 별도로 jsp로 정의해두고 include로 표현할 수 있다.

 

 

<%@ include file="header.jsp" %>

- 현재 이 페이지와 같은 폴더에 header.jsp가 있다면 위와 같이 경로를 파일명만 작성하면 된다.

 

- header, footer, nav 등의 태그도 결국 div다. 의미를 부여한 시멘틱 태그다.

 

 

- header.jsp와 footer.jsp의 body 영역에 보여지는 요소가 들어온다

- 회사에선 head, body 태그 다 떼고 보여질 요소만 작성한다. 딱 body에 표현할 요소만을 작성한다.

다른 곳에 포함될 페이지는 전체 구조를 다 둘 필요 없이 포함될 요소만 작성해도 된다.

 

- 사이드 영역도 매 페이지마다 같다면 include로 포함시킨다.

 

- header.jsp에서 선언한 변수를 main.jsp에서도 쓸 수 있다.

말 그대로 저 페이지상에 존재하는 모든 구문들이 이 자리에 들어갔다.

 

 

 

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

 

 

 

[3.Servlet과 JSP 결합]

 

 

서블릿과 JSP를 결합시켜서 사용자가 요청할 수 있는 페이지를 제작한다.

- 요청은 서블릿이 처리하고, 처리된 결과를 JSP 페이지를 통해 사용자에게 응답하여 표현한다.

 

 

 

ㅁ select

- key값은 select 태그에 한번만 작성하면 된다

- option에 value 속성을 두지 않으면 텍스트값이 넘어간다.

 

 

<select name="pizza"> 

    <option>치즈피자</option>

    <option>페퍼로니피자</option>

    <option>하와이안피자</option>

    <option>씨푸드피자</option>

</select>

 

 

 

ㅁ checkbox와 라디오 버튼은 name 속성(key), value 속성을 다 써줘야 한다. 

 

<input type="checkbox" name="topping" value="고구마무스">

<input type="radio" name="payment" value="card" checked>

 

 

 

 

ㅁ 현재 <form action="/jsp/order.do" method="post">인 상태다.

 

ㅁ 서블릿은 MVC 패턴 중에 컨트롤러 역할이기 때문에 controller 패키지로 만든다. 

- controller 패키지에 서블릿으로 PizzaOrder.java를 만든다.

- 서블릿의 annotaion을 "/order.do"로 변경한다.

- doPost() 메소드는 doGet() 메소드를 호출한다.

 

 

 

 

ㅁ doGet() 메소드

- 1. 요청하면서 전달한 값(파라미터)을 뽑아서, 그 값을 가지고 요청을 처리한다. (주로 JDBC)

- 2. 돌려받은 결과를 가지고 응답페이지를 제작한다.

 

 

 

(1) 요청시 전달값 뽑기

 

request.setCharacterEncoding("utf-8"); // post방식 요청이기 때문에 데이터를 뽑기 이전에 인코딩 지정해야 한다.

 

String userName = request.getParameter("userName"); 

 

// 요청과 같이 전달된 값을 뽑아서 곧바로 요청처리 하려하지말고, 항상 출력해서 잘 넘어왔는지 확인해봐라.

System.out.println("유저이름 : " + userName);

 

 

 

(2) 요청처리 (주로 JDBC)

 

// => service => dao => 쿼리 실행 => 결과 돌려받기

// 요청 처리 후 돌려받은 결과가 주문번호라고 가정.

String orderNo = "20240828-1234567"

 

 

 

(3) 돌려받은 결과를 가지고 응답페이지 제작하기

 

// resoponse 객체를 이용해서 한땀한땀 html 구문을 출력해도 되지만,

이제부턴 응답페이지 제작하는 과정을 jsp로 이동(forward)해서 진행한다.

 

 

//  HttpServletRequest 객체의 응답데이터 처리 메소드

- 응답페이지에서 필요한 데이터는 보통 request 객체에 담아서 forward로 넘긴다.

- setAttribute(String 속성, Object 값) : 이동(forward)되는 jsp에서 사용할 데이터를 담는 메소드

- getAttribute(String 속성) : 해당 데이터를 Object 타입으로 반환 (형변환이 필요할 수 있음)

- removeAttribute(String 속성) : 해당 데이터를 제거하는 메소드

 

 

request.setAttribute("userName", userName);

request.setAttribute("orderNo", orderNo);

 

request.getRequestDispatcher("/d_pizza/result.jsp").forward(request, response);

 

 

- 요청시 전달된 다수의 값을 service, dao로 넘길 때 vo객체가 있다면 거기에 담아서 한번에 넘긴다.

담는 과정도 여기서 진행한다. 

- setAttribute(String 속성, Object 값)에서 String 속성은 속성명이고 Object 객체가 내가 request 객체에 담고자 하는 값이다.

배열도 담을수 있고 리스트도 담을 수 있다. vo객체도 담을 수 있다.

 

 

 

 

 항상 이런 흐름으로 간다. 

- 요청을 보내면 요청시 전달값을 뽑아서 sql query를 실행해서 결과를 돌려받고,

그에 해당하는 응답페이지를 jsp로 만들어서 이동시킨다.

- 그때 응답페이지에서 필요한 데이터는 위와 같이 setAttribute라는 메소드로 request 객체에 담아서 전달시킨다.

 

 

 

 

ㅁ 아래와 같이 응답페이지인 result.jsp를 만든다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"

          pageEncoding="UTF-8"%>

<%

  String userName = (String)request.getAttribute("userName"); // 실제론 String 타입의 데이터지만 반환은 Object로 됨.

  String orderNo = (String)request.getAttribute("orderNo");

  String pizza = (String)request.getAttribute("pizza");

  String[] topping = (String[])request.getAttribute("topping");

  String[] side = (String[])request.getAttribute("side");

  String payment = (String)request.getAttribute("payment");

%>

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Insert title here</title>

</head>

<body>

 

  <h2>주문 완료</h2>

 

  <h3>주문번호 : <%= orderNo %></h3>

  <h3>주문자명 : <%= userName %></h3>

 

  <h3>주문내역</h3>

  <ul>

    <li>피자 : <%= pizza %></li>

    <%-- 토핑과 사이드는 체크한게 없으면 null일 수 있다. --%>

    <li>토핑 :

      <% if(topping == null) { %>

        <b>선택안함</b>

      <% }else { %>

        <%= String.join(", ", topping) %>

      <% } %>

    </li>

    <li>사이드 :

      <%

      if(side== null) {

        out.println("<b>선택안함</b>");

      }else {

        out.println(String.join(", ", side));

      }

      %>

    </li>

    <li>결제방식 : <%= payment.equals("card") ? "카드" : "현금" %></li>

</ul>

 

</body>

</html>

 

 

- 응답페이지(.jsp)에서 request 객체로부터 getAtrribute로 데이터를 꺼낸다.

- request 객체에서 데이터를 뽑는 구문은 페이지 로드되자마자 바로 실행되게끔 주로 상단에 쓴다. 

 

- jsp에서는 request객체를 import 없이 바로 쓸 수 있다. jsp 내장객체다. 

- <% %> 에는 자바코드만 있어야 하고 html 구문이 있어서는 안 된다.

out.println문에 html태그를 쓰면 된다.