** HttpServlet
1. 작성방법
2. 서블릿에서의 내장 객체 사용
3. 서블릿과 URL 매핑
4. 서블릿 생성 및 호출 실습
5. URL Pattern
6. Controller Pattern
7. Controller 패턴을 만들기 위해서 알아야 할 내용
8. 디렉토리 패턴을 이용한 페이지 이동
9. 서블릿과 jsp의 수명주기
10. Model2 MVC Pattern
** Modlel MVC 구조의 프로젝트 생성
1. Dynamic Web Project를 web.xml 파일을 포함하도록 생성
2. servlet-api.jar 파일을 프로젝트의 WebContent/WEB-INF/lib 디렉토리에 복사
3. 시작화면으로 사용할 index.jsp(html도 상관없음) 파일을 WebContent 디렉토리에 생성
4. DTO로 사용할 클래스를 생성
5. Repository에 해당하는 클래스를 생성 - 싱글톤 패턴
6. Service 클래스를 생성
7. Controller 생성
8. 웹 서버에서의 요청 처리
** Filter
1. Listener
2. Filter
3. Authentication Filter 만들기
※ HttpServlet
- URL을 이용해서 호출할 수 있는 Java EE의 클래스이다.
- Java SE 버전을 설치하고 이 클래스를 사용하려면 Spring 같은 프레임워크를 사용하거나 WAS(Web Application Server - Tomcat)를 사용해야 한다.
- Servlet이나 jsp 파일을 추가하면 에러가 발생하는데 이 에러를 제거하고자 하면 servlet-api.jar 파일을 프로젝트의 WebContent/WEB-INF/lib 디렉토리에 복사를 해야 한다.
- Servlet은 매핑이 되는 첫 번째 요청이 왔을 때 인스턴스를 생성하고 요청을 처리한 후 WAS가 관리하고 두 번째 요청부터는 이전에 만든 인스턴스를 이용해서 요청을 처리한다.
- 이 클래스를 만들 때는 HttpServlet 이라는 클래스를 상속받아서 생성한다.
- jsp는 HTML 코드 안에 Java코드를 삽입하는 형태이고 Servlet은 Java 코드 안에 HTML을 삽입할 수 있다.
- jsp 파일에는 EL과 JSTL을 이용해서 출력하는 코드만 작성하고 처리 작업은 Servlet과 Java 클래스를 이용하는 형태로 코딩하는 것을 권장하는데 이 방식을 Model2라고 한다.
1. 작성 방법
- HttpServlet 클래스로부터 상속받는 클래스를 생성
- 생성할 때 매핑이 되는 URL을 설정할 수 있고 나중에 web.xml 파일에 매핑이 되는 URL을 설정할 수 있다.
- 요청을 처리하는 메소드를 재정의
- doGet, doPost 메소드를 이용한 방식이 있고 service 메소드를 이용하는 방식도 있다.
- doGet은 get 방식으로 요청했을 때 호출이 되고 doPost는 post 방식으로 요청했을 때 호출이 되는 메소드이다.
- service는 요청 방식에 상관없이 호출되는 메소드이다.
- Servlet을 생성하면 doGet과 doPost가 이미 재정의 되어 있는데 doPost 메소드에는 doGet을 호출하는 문장이 있어서 실제로는 doGet에만 코딩을 하면 된다.
2. 서블릿에서의 내장 객체 사용
- doGet 메소드와 doPost 메소드의 매개변수로 request 객체와 response 객체가 전달된다.
- session 객체는 request.getSession() 메소드를 호출해서 리턴된 객체를 사용한다.
- application 객체는 request.getServletContext() 메소드를 호출해서 리턴된 객체를 사용한다.
- 출력을 할 때는 response.getWriter()를 호출해서 리턴된 객체를 사용한다.
3. 서블릿과 URL 매핑
1) annotation을 이용한 방법
- Servlet 클래스 상단에 어노테이션을 추가
@WebServlet("URL")
2) web.xml을 이용한 방법 - 권장하지 않음
<servlet>
<servlet-name>서블릿 이름</servlet-name>
<servlet-class>서블릿 클래스 경로</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>서블릿 이름</servlet-name>
<url-pattern>URL패턴<url-pattern>
</servlet-mapping>
4. 서블릿 생성 및 호출 실습
1) 서블릿 생성
2) 서블릿 호출
- 웹 애플리케이션을 실행하고 브라우저의 주소 표시줄에 @WebServlet("/FirstServlet")에 설정된 URL을 추가로 입력한다.
5. URL Pattern
- 서블릿은 생성하면 하나의 URL과 매핑이 된다.
- 여러 개의 요청을 처리하는 경우 여러 개의 서블릿이 필요하다.
- 여러 개의 URL을 묶어서 하나의 서블릿으로 처리할 수 있다.
- 하나의 객체가 하나의 이벤트를 처리할 수 있는데 이렇게 하면 여러 개의 이벤트를 처리하기 위해서 여러 개의 객체가 필요하다.
- 여러 개의 이벤트를 하나의 객체를 이용해서 처리하도록 하는 것을 이벤트 라우팅이라고 한다.
- 모든 웹 프로그래밍에서는 전부 이런 식으로 하나의 객체를 가지고 여러 URL을 처리한다.
1) 모든 URL 요청을 처리하는 방법
- URL을 "/*"로 설정한다.
2) 확장자 패턴 - 우리나라에서 많이 사용
- URL을 "*.확장자"로 설정한다.
- 위와 같이 설정하면 확장자로 끝나는 모든 요청을 처리한다.
- 우리나라 공공기관은 do 확장자를 많이 사용한다.
- 네이버는 nhn 확장자를 사용한다.
3) 디렉토리 패턴 - 최근에 권장
- URL을 "/디렉토리/*"로 설정한다.
- 위와 같이 설정하면 디렉토리가 포함된 모든 요청을 처리한다.
- 디렉토리에 작업의 의미를 부여해서 알아보기 쉽게 URL을 만드는 것을 권장한다.
- 최근에는 파라미터가 1개인 경우 파라미터를 이용하지 않고 디렉토리 패턴의 마지막 부분에 파라미터를 설정하는 방식이 많이 사용된다.
4) 확장자 패턴과 디렉토리 패턴은 같이 사용이 불가
- "/디렉토리/*.확장자" 형태는 안된다.
6. Controller Pattern
- 요청이 발생하면 반드시 Controller를 거쳐서 나가도록 하는 패턴이다.
- 요청이 발생할 때 거치도록 하면 FrontController 패턴이라고 한다.
- 실제 업무에서는 요청이 발생하면 그에 따른 공통 관심 사항이라고 부르는 Common Concern이 있는 경우가 많다.
- 이러한 작업은 한 곳에서 수행할 수 있도록 만드는 것이 유지보수에 유리하다.
- 자바에서는 Controller를 서블릿으로 생성한다.
- 다른 애플리케이션 개발을 할 때도 시작하는 클래스를 찾아두는 것이 중요하다.
7. Controller 패턴을 만들기 위해서 알아야 할 내용
- request.getContextPath() : 루트 경로를 문자열로 리턴해주는 메소드
- request.getRequestURI() : 전체 요청 경로를 문자열로 리턴해주는 메소드
- request.getMethod() : 요청 방식을 문자열로 리턴해주는 메소드(GET, POST)
- 포워딩
- RequestDispatcher ? = request.getRemoteDispatcher("포워딩할 URL");
- ?.forward(request객체, response객체);
- URL을 변경하지 않고 이동
- 리다이렉트
- response객체.sendRedirect("리다이렉트할 URL");
8. 디렉토리 패턴을 이용한 페이지 이동
- jsp 파일은 ex 디렉토리에 생성
- /authentication 디렉토리 패턴을 이용
1) WebContent 디렉토리 안에 ex 디렉토리를 만들고 main.jsp를 생성하고 작성
2) ex 디렉토리에 login.jsp 파일을 생성하고 작성
3) ex 디렉토리에 write.jsp 파일을 생성하고 작성
4) /authentication 디렉토리가 포함된 요청을 처리할 수 있는 서블릿을 생성하고 doGet메소드를 수정
- 폼 입력 화면으로 이동하는 것과 폼 요청을 처리하는 URL을 동일하게 만드는 것을 권장한다.
- 전송방식을 이용해서 폼 입력화면으로 갈 때는 GET 방식으로 포워딩하고 폼 요청을 처리하는 곳으로 갈 때는 POST 방식으로 리다이렉트 하도록 하는 것을 권장한다.
5) Webcontent 디렉토리에 시작 페이지로 사용할 index.jsp 파일을 만들고 링크를 추가
9. 서블릿과 jsp의 수명주기
- 서블릿은 매핑이 되는 첫 번째 요청이 왔을 때 인스턴스를 만들고 요청을 처리하고 다음 요청들을 이전에 만든 인스턴스로 처리한다.
- jsp는 매핑이되는 요청이 올 때마다 서블릿 클래스로 변환하고 인스턴스를 만든 후 요청을 처리하고 삭제한다.
1) 서블릿 인스턴스를 요청이 오기 전에 서버가 구동되면 바로 만들 수 있다.
- 이 경우는 web.xml 파일에 등록을 하면 된다.
<servlet>
<servlet-name>이름</servlet-name>
<servlet-class>클래스경로</servlet-class>
<load-on-startup>정수</load-on-startup>
</servlet>
- 실제 서블릿은 전부 위처럼 옵션을 설정한다.
- 정수는 생성되는 순서로 작은 숫자로 설정한 것이 먼저 생성된다.
2) 서블릿 초기화와 소멸에 관련된 메소드
- init을 재정의해서 초기화한다.
- destroy를 재정의해서 소멸될 때 수행할 작업을 작성한다.
- jsp는 jspInit과 jspDestroy를 이용한다.
10. Model2 MVC Pattern
- Command Pattern : 하나의 요청은 하나의 객체가 처리해야한다.
- 하나의 요청은 하나의 메소드와 매핑되어야 한다.
- Modle2 : 출력은 jsp에서 처리는 Servlet이나 Java Class가 수행하는 것을 말한다.
- MVC : 처리와 출력을 분할하고 이 둘을 연결시켜주는 Controller를 생성하는 패턴이다.
- Model이 모든 요청을 처리하고 View가 출력을 하고 Controller는 연결만 담당하도록 작성한다.
- Model은 다시 2개 부분으로 나누는데 하나는 Service라고 부르는 것으로 알고리즘을 처리하는 부분이고 다른 하나는 Repository라고 부르는 것으로 데이터와 관련된 작업을 처리하는 부분이다.
- 웹 프로젝트의 기본 구조
- View(jsp 나 html) <-> Controller(HttpServlet으로 생성) <-> Service(Java Class) <-> Repository(Java Class) <-> 데이터 저장소
- 금융처럼 여러 유저가 접속해서 사용하는 시스템에서는 데이터 저장소와 Repository 사이에 Middle Ware를 두기도 한다.
- 사용자의 요청 1개는 Service에서는 1개의 메소드만 호출해야 한다.
- 그 이후 메소드를 여러 호출하는 것은 상관없다.
- Service 부분은 템플릿 메소드 패턴(인터페이스 -> 클래스)을 사용하는 것을 권장한다.
- 서버에서 구동되는 클래스들은 싱글톤 패턴(인스턴스를 1개만 생성할 수 있는 클래스)으로 디자인하는 것을 권장한다.
- 동일한 여러 개의 요청이 온 경우 여러 개의 인스턴스가 처리하지 않고 하나의 인스턴스가 스레드를 이용해서 처리한다.
- Controller를 만들 때는 학습을 할 때는 제외하고는 대부분의 경우 URL 패턴을 /* 또는 jsp를 제외한 모든 요청을 처리할 수 있도록 설정한다.
※ Model MVC 구조의 프로젝트 생성
- todo 작업이라고 가정
- 요청은 4개라고 가정(select, insert, update, delete)
1. Dynamic Web Project를 web.xml 파일을 포함하도록 생성
2. servlet-api.jar 파일을 프로젝트의 WebContent/WEB-INF/lib 디렉토리에 복사
3. 시작화면으로 사용할 index.jsp(html도 상관없음) 파일을 WebContent 디렉토리에 생성
4. DTO로 사용할 클래스를 생성
- 업무 별로 패키지를 별도로 생성해서 배치
- 모바일이나 spring web에서는 패키지 이름을 3 level 이상으로 설정
- 회사 도메인의 역순이나 자신의 이메일 역순을 적고 업무명으로 패키지를 생성
5. Repository에 해당하는 클래스를 생성 - 싱글톤 패턴
- 이름은 대부분 업무명 뒤에 Dao를 추가한 형태로 생성한다.
6. Service 클래스를 생성
- Service는 템플릿 메소드 패턴과 싱글톤 패턴을 적용한다.
- 인터페이스를 만들고 클래스를 구현한다.
- Dao를 가져다가 사용한다.
- 이름은 업무명Service, 업무명ServiceImpl
1) 인터페이스 생성
2) 클래스 구현
7. Controller 생성
- Controller는 서블릿으로 생성한다.
- 싱글톤으로 만들어야 하는데 개발자가 코드를 작성할 필요가 없다. 그 이유는 Servlet은 WAS가 인스턴스를 만들 때 1개만 생성해서 관리하기 때문이다.
- url 패턴을 do 확장자를 처리하도록 하고 index.html 처리하도록 작성한다.
- index.html을 처리하지 않으면 시작 페이지는 Controller에 오지 않게 된다.
- 모든 요청은 Controller를 거치도록 만들어야 한다.
- 이처럼 Controller가 Entry Point가 되도록 하는 것은 FrontController 패턴이라고 한다.
8. 웹 서버에서의 요청 처리
html이나 jsp 페이지에서 요청 -> Controller -> Service -> Dao -> Database -> Dao -> Service -> Controller -> View
- 어떤 경우에는 Controller에서 바로 View로 가기도 함 : 단순 페이지로 이동한다.
- Dao가 생략되는 경우도 있음 : 데이터베이스 작업이 없는 단순한 업무 처리의 경우
- Controller 에서 View로 가지않고 다시 Controller를 거쳐서 View로 가기도 한다.
- redirect의 경우는 바로 View로 가지 않고 Controller에게 다시 요청해서 결과 페이지로 포워딩한다.
- 웹 브라우저에 출력을 할 때는 View가 jsp나 html이 되는 것이고 다른 프로그램에서 서버에 요청을 하는 경우에는 View가 json이나 xml이 되는 것이다.
※ Filter
- AOP(Aspects Of Programming - 관점 지향 프로그래밍) : 애플리케이션을 구현하다 보면 Business Logic(업무 처리 내용)과 Common Concern(공통 관심 사항)이 같이 수행되어야 하는 경우가 많다.
- 하나의 메소드에 기능이 다른 코드를 같이 작성하는 것은 가독성을 떨어뜨린다.
- 메소드를 분리해서 작성하고 호출하는 방식을 사용할 수 있지만 Java Web Programming에서는 별도의 클래스에 메소드를 만든 후 설정에서 호출하도록 만들 수 있다.
- 빌드를 할 때 설정 내용을 가지고 클래스 코드를 수정한다.
- 실제 만들어진 클래스에는 순서대로 호출하는 코드가 보인다.
- Java Web에서는 AOP를 Filter와 Listener를 이용해서 구현하고 Spring에서는 Intercaptor와 AOP를 이용해서 구현한다.
- AOP를 사용하게 되면 Business Logic과 Common Concern이 같이 존재하지 않기 때문에 가독성이 높아지고 유지보수에 유리해진다.
1. Listener
- 이벤트가 발생했을 때 이벤트를 처리해주는 객체
- Java EE에서는 웹 애플리케이션이 시작할 때 종료할 때 동작하는 메소드를 소유한 리스너와 세션이 생성될 때와 소멸될 때 호출되는 메소드를 소유한 리스너가 존재한다.
- 애플리케이션이 시작될 때는 나중에 필요한 자원들을 전부 생성하고 애플리케이션이 종료될 때는 메모리 정리 작업을 수행한다.
- 세션이 만들어질 때와 소멸될 때는 주로 접속한 세션의 개수를 더하거나 빼는 작업을 해서 현재 접속 중인 세션의 개수를 확인한다.
- 세션이 소멸될 때 호출되는 메소드는 브라우저를 종료하거나 컴퓨터를 강제로 종료하면 호출되지 않는다.
- 웹 클라이언트를 만들 때 브라우저를 종료하기 직전(before unload)에 이벤트 처리 핸들러에서 ajax를 이용해서 서버에게 종료를 알려주어야 한다.
2. Filter
- 클라이언트의 요청이 Controller에게 전달되기 전이나 Controller가 처리한 후에 수행할 작업을 작성할 수 있는 인터페이스이다.
1) 메소드
- init : 초기화 메소드
- destroy : 소멸될 때 호출되는 메소드
- doFilter : Controller에게 전달되기 전이나 처리한 후에 호출되는 메소드
- 이 메소드들을 재정의해서 수행할 일들을 작성한다.
- chain.doFilter()를 호출하는 구문 앞에 적으면 Controller가 처리하기 전이고 뒤에 적으면 Controller가 처리한 다음이면 이 메소드를 호출하지 않으면 원래의 요청을 처리하지 않는다.
2) URL 패턴 적용
- 상단에 Annotation을 이용해서 적용할 수 있고 web.xml 파일에 설정할 수 있다.
3. Authentication Filter 만들기
- Authentication(인증) : 로그인 여부에 따라 자원의 여부를 결정하는 것
- Authorization(인가) : 권한 여부에 따라 자원의 여부를 결정하는 것 - User 테이블에 권한을 저장할 수 있는 컬럼이 있어야 한다.
- 쓰기 요청을 할 때 로그인 여부를 확인해서 로그인이 되어 있지 않으면 로그인 페이지로 이동하기
1) index.jsp 파일을 수정
2) WebContent 디렉토리에 user 디렉토리를 생성하고 login.jsp 파일을 추가
3) WebContent 디렉토리에 board 디렉토리를 만들고 write.jsp 파일을 생성 및 작성
4) jstl.jar 파일을 WebContent/WEB-INF/lib 디렉토리에 복사
5) Controller 클래스에 요청 처리하는 부분을 추가
6) 로그인 화면에서 입력을 하고 로그인 요청을 처리하는 코드를 작성
- 작업을 수행해야 할 때는 데이터베이스 사용 여부를 확인 - 데이터베이스를 사용한다면 Dao 메소드를 만들어서 구현
- Service 인터페이스에 처리해 줄 메소드를 선언한다.
- 리턴 타입은 void 매개변수는 HttpServletRequest, HttpServletResponse로 설정하는데 Request만 선언하기도 한다.
- Controller에서 login 요청을 처리하는 코드를 작성
7) 로그아웃 처리를 위한 코드를 Controller 클래스에 doGet 메소드에 작성
8) write.do 요청이 오면 동작하는 필터를 생성하고 로그인이 되어 있지 않으면 로그인 페이지로 이동하는 코드를 작성
- doFilter 메소드 작성