능글맞은 구렁이
Spring- 흐름이해하기 본문
*Spring MVC흐름*
*내장클래스 (이름 변경 불가!)*
DispatcherServlet : ~~.servlet // 웹브라우저에서 어떤 요청사항이 들어오게 되면 모든 것은 DispatcherServlet이
요청을 받는다. DispatcherServlet 요청 사항을 처리할 수 있는 컨트롤러를 반환받는데 그부분을 HandlerMapping 리턴시켜준다.
HandlerMapping : ActionFactory
Controller : ~~~.action들
View : ~~.jsp들
ViewResolver : url 변수
*실행순서*
project를 실행할때 제일 먼저 구동되는 파일은 web.xml문서가 먼저 로딩된다.
1. application → web.xml → 구동시작 (application은 계속 구동되어 있어야 한다.)
2. 웹브라우저 요청 → web.xml의 DispatcherServlet → board-servlet.xml내의 HandlerMapping에게 전달 →
HandlerMapping은 요청을 처리할 수 있는 컨트롤러 반환 →
반환받은 DispatcherServlet은 → ~~Controller → 요청사항 처리후, 결과 값과 출력 파일명을 ModelAndView객체로
반환 → 반환받은 DispatcherServlet은 → ViewResolver 에게 전달 → ViewResover는 해당 파일의 위치와 확장자를 반환 → 반환받은 DispatcherServlet은 해당 위치의 파일을 웹브라우저에게 응답처리
**web.xml문서에서 서블릿 등록방법**
1. 컨트롤러역할을 하는 서블릿의 이름 및 요청경로를 지정
<servlet>
<servlet-name>서블릿이름(클래스명은 아님)</servlet-name> <!--실행순서 3-->
<servlet-class>등록할 서블릿 클래스의 전체경로 및 클래스명</servlet-class> <!--실행순서 4-->
</servlet>
2. 어떻게 요청이 들어왔을 때, 처리할 것인가 (서블릿 자동호출)
<servlet-mapping>
<servlet-name>서블릿 이름</servlet-name> <!--실행순서 2-->
<url-pattern>웹주소줄을 통하여 요청</url-pattern> <!--실행순서 1-->
</servlet-mapping>
web.xml이 제일먼저 구동되므로 1번과 2번에 오타가 발생할경우 에러 404가 발생한다.
또한 프로젝트를 구성하기전 (1) web.xml의 welcome-file이 있는지 확인한다.
파일이있어도 에러시 (2) mapping과 servlet서블릿 이름이 같은지 확인한다.
예)<servlet>
<servlet-name>서블릿이름</servlet-name> <!--실행순서 3-->
<servlet-class>등록할 서블릿 클래스의 전체경로 및 클래스명</servlet-class> <!--실행순서 4-->
</servlet>
<servlet-mapping>
<servlet-name>서블릿 이름1</servlet-name> <!--실행순서 2-->
<url-pattern>웹주소줄을 통하여 요청</url-pattern> <!--실행순서 1-->
</servlet-mapping>
에러!!!
그래도 에러시 (3) servlet-class파일이 로드가 안되었거나 경로가 잘못되어 import가 안되는 경우이다.
**HandlerMapping 역할을 담당하는 XML문서**
1. 전체를 감싸는 태그는 반드시 <beans~~></beans>로
2. 작업에 필요한 객체 생성 및 클래스 등록은
<beans~~>
<bean> </bean>
</beans>
3. 첫번째 등록은 반드시 HandlerMapping
4. ViewResolver도 반드시 등록
5. 그외의 컨트롤러는 반드시 해당 클래스는 만든 후, 등록 즉,XML문서에 미리 설정금지
**클래스 등록방법**
1. 해당 xml문서에서 사용할 클래스(즉, 객체)
<bean id="객체명" class="패키지.클래스"> </bean>
예) 만약 board.dao.BoardDAO가 있을 경우(id값은 자유)
<bean id="boardDAO" class=" board.dao.BoardDAO"></bean>
2. 컨트롤러 클래스 등록방법 - [1] 전달받은 데이터가 없을 경우 :
예) 글목록..)
<baen name="요청사항(url)" class="요청사항처리클래스">
<property name="해당 클래스의 멤버변수명>
<ref bean="변수에 전달할 값"/>
</property>
</bean>
[2] 만약 board.controller.ListActionController가 존재할 경우, 내부에 BoardDAO dao
변수가 있을 경우, 요청사항이 list.do일 경우
<baen name="/list.do" class="board.controller.ListActionController">
<property name="dao">
<ref bean="BoardDAO"/>
</property>
</bean>
[3] ViewResolver클래스 등록방법
<baen id="객체명" class="스프링이 제공하는 InternalResourceViewResolver">
<property name="viewClass" value="스프링이 제공하는 InternalResourceView"> </property>
<property name="prefix" value="경로"></property>
<property name="suffix" value="구체적인 내용(즉확장자)"></property>
</bean>
[4] 화면 출력용 jsp 파일들이 WebContent폴더에 존재할경우:"list"
<baen id="viewResolver" class="~~~~.~~~~~>InternalResourceViewResolver">
<property name="viewClass" value="~~~.~~~.InternalResourceView"> </property>
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
**DB연결**
JNDI 방법으로 DB 연결하는 방법
META-INF -> Context.xml (DB 정보 를 태그 형태로 저장)
Java Naming Directory Interface (JNDI) -> DB 연결의 정보 --> Context.xml 에 저장 --> DB 정보를 이름으로 검색해서 가져옴 연결객체 가져옴
결과적으로, DAO 에 DB 에 대한 url, driver, 계정 , 암호를 입력하지 않아도 된다
1. 일반 XML문서 생성
Context.xml
2. Context.xml에 연결 정보 설정
name 속성 :
name속성을 찾아서 DB 를 찾아가 는데 사용자 가 임의로 줄 수 있다. 일반적으로는 jdbc/orcl 로 사용
외부에서는 name 만 알면 , 모든 속성 을 가져올 수 있다. 이 name 을 JNDI 이름이라고 한다.
nave="jdbc/orcl" ← JNDI 방식 : "java:comp/env/name속성값"
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/orcl"
auth="container"
type="javax.sql.DataSource"
username="board_mvc"
password="1234"
driverClassName="oracle.jdbc.driver.oracleDriver"
factor="org.apache.commons.dbcp.BasicDataSourceFactory"
url="jdbc:oracle:thin:@127.0.0.1:1521:XE"
maxActive="20"
maxIdle="10">
</Resource>
</Context>
속성명="값" | 역할 |
name="jdbc/orcl" | JNDI방식. 이 이름으로 외부클래스 (BoardDAO) 에서 접근 |
auth="container" | 리소스(DB) 를 누가 관리할 것인가?(스프링 컨테이너)관리자 |
type="javax.sql.DataSource" | 커넥션풀에 대한 DataSource 의 fullName |
username="freeflux | 접속할 계정명 |
password="free" | 접속할 암호 |
driverClassName="oracle.jdbc.driver.OracleDriver" | 접속할 데이터베이스 Driver 명 |
factory="org.apache.commons.dbcp.BasicDataSourceFactory" | 커넥션풀을 생성해주는 클래스 fullName |
url="jdbc:oracle:thin:@localhost:1521:XE" | 접속url |
maxActive="20" | 최대로 빌려줄 수있는 커넥션풀 갯수 지정(활성) |
maxIdle="10" | 최대로 여분이 있는 커넥션풀 갯수 지정(여유) |
*정리*
*프로젝트 실행시 실행순서 : WEB-INF → web.xml → board-servlet.xml*
1. WEB-INF (웹 애플리케이션 정보 폴더:톰캣이 자동 인식)
2. WEB-INF → web.xml읽기
3. web.xml → <servlet>, <servlet-mapping>, <welcome-file-list> 설정확인
(<servlet> 내의 <servlet-class>에서 가장 오류가 많이 발생!!
이유 : org.springframework.web.servlet.DispatcherServlet
만약 : WEB-INF → lib → spring.jar, spring-webmvc.jar 미존재시 DispatcherServlet 생성 불가 따라서 404오류
만약 : WEB-INF → lib → spring.jar, spring-webmvc.jar 존재시 패키지 구조 오타 : DispatcherServlet 생성불가
만약 : WEB-INF → board-servlet.xml 의 파일명이 다를 경우 HandlerMapping불가
예) <servlet-name>board</servlet-name>
b-servlet.xml (에러) / board.xml (정상) → HandlerMapping불가
*board.xml*
오류 : HandlerMapping 불가
WEB-INF → web.xml → board-servlet.xml
board.command → BoardCommand.java (글쓰기/수정 사용자입력값 → 컨트롤러에게 전달 전용 VO)
board.dao → BoardDAO.java
board.dto → BoardDTO.jave (데이터베이스와 컨트롤러 전달 전용 VO)
board.controller → ListActionController.java
WriteActionController.java
*VO역할 구분 이유*
1. 사용자 입력값은 5개, 테이블의 필드 10개중 사용자 입력 값은 5개, 기본값 설정이 되어 있는 필드 5개일 경우
기존 VO는 테이블의 전체 필드에 대한 멤버변수를 선언 그에 대한 getter, setter 필요
2. 동시접속자가 100,000일 경우 불필요한 5개 변수에 대한 메모리가 낭비
3. 따라서 사용자 입력값을 저장할 VO객체와 데이터베이스의 결과 값을 저장 할 VO객체를 분리하여 사용
*board.dao → BoardDAO.java*
META-INF → Context.xml:JNDI방식으로 데이터베이스에 접근하기 위해 만든 xml문서
1. JDBC 드라이버를 이용 : 접속할 때마다 Connection 객체를 생성 및 해제 따라서 동시접속자 수가 많을 경우, 퍼포먼서 저하
2. 스프링이 제공하는 DataSource 를 이용한 접근 방식: 미리 Connection 객체를 여러 개 생성 후, 풀에 담아 놓고 사용
예) 100명이 접속할 경우, JDBC 드라이버: 100번 요청이 있으면 Connecdtion객ㅊ를 100번 생성 이후 재활용 불가!
DataSource: 미리 100개를 생성. 1000명이 요청시, 미리 생성된 100개의 Connection객체 get!
사용자가 일을 마치면 해당 Connection 객체를 다시 pool에 반환
자동으로 관리해줌..(Connection객체 꺼내고/ 반환)
WEB_INF => web.xml 시작
=> board-servlet 시작 => <bean id="defaultHandlerMapping" ~~/>
=> <bean id="boardDAO" class="board.dao.BoardDAO"/>
=>BoardDAO의 생성자 => Context.xml
=> <bean name="/list.do"~~
=> <bean name="/writeui.do"~~
=> <bean name="/write.do"~~
=? <bean id="viewResolver"~~
=> board-servlet.xml 종료
=> web.xml 종료
=> 웹 애플리케이션 구동 완료
웹 애플리케이션 구동 완료 후
DispatcherServlet defaultHandlerMapping boardDAO
/list.do 처리 컨트롤러 객체 <=boardDAO 객체전달
/writeui.do 처리 컨트롤러 객체
/write.do 처리 컨트롤러 객체 <=boardDAO 객체전달
viewResolver
(prefix = 화면출력 파일에 대한 경로
suffix = 화면출력 파일에 대한 구체적인 내용 (즉, 확장자)
비지니스 로직을 처리하는 각 컨트롤러 : board.controller
1. 목록 처리 컨트롤러 : ListActionController
2. 쓰기화면 처리 컨트롤러 : 스프링이 제공하는 ParameterizableViewController (화면만 응답처리 할 경우)
@Override
public ModelAndView handleRequestInternal(~~~)~~~~{ }
handleRequestInternal() 메서드의 역할: viewName 속성값을 이용하여
ModelAndView mav = new ModelAndView();
mav.setViewName("viewName 속성값");
mav 객체를 반환
ParameterizableViewController 등록 시에는 반드시 viewName 속성에 출력화면 파일명만 설정
<bean name="/writeui.do" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
<property name="viewName" value="write"></property>
</bean> (변경불가) (write.jsp)
3. 저장 처리 컨트롤러 : WriteActionController extends AbstractCommandController
implements Controller : 브라우저로부터 데이터가 파라미터로 전달될 경우
@Override
public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
extends AbstractCommandController : 브라우저의 입력 파라미터 명과 해당 값을 VO 객체와 자동 매핑 시킨 후 컨트롤러에게 자동으로 전할 경우..
@Override
public ModelAndView handleRequest(HttpServletRequest,
HttpServletResponse,
Object command, <=자동 매핑된 VO 객체가 전달되는 매개변수
BindException error)
자동 매핑된 VO 객체를 Object command에 자동전달 하려면
해당 컨트롤러를 등록할 때 미리 설정해야 한다..
<property name="commandClass" value="자동매핑VO클래스" />
(변경불가)
웹 애플리케이션 구동 완료 후, 웹 브라우저가 요청시 (/list.do, /writeui.do, /write.do)
DispatcherServlet defaultHandlerMapping boardDAO객체
list.do : 처리 컨트롤러 객체 ←boardDAO 객체 전달
writeui.do : 처리컨트롤러 객체
write.do : 처리컨트롤러객체 ← boardDAO 객체전달
viewResolver prefix=화면 출력파일에 대한 경로
suffix = 화면 출력 파일에 대한 구체적인 내용(즉, 확장자)
'Framework > Spring' 카테고리의 다른 글
Spring-인텔리제이 프로젝트생성 (0) | 2021.06.13 |
---|---|
Spring-프로젝트 구조 분석 (0) | 2021.06.13 |
Spring-개발을 위한 준비/javaConfiguration(설정2) (0) | 2021.06.12 |
Spring-개발을 위한 준비 (설정1) (0) | 2021.06.12 |
Spring Framework 이란? (0) | 2021.06.10 |