초기 환경설정 (웬만하면 순서대로)
1) pom.xml
2) web.xml
- DispatcherServlet, servlet-mapping (url-pattern)
- servlet-context.xml, root-context.xml
- CharacterEncodingFilter
3) servlet-context.xml
- base-package
.java 파일을 저장할 곳의 최상위 폴더
@Controller, @Autowired(@Inject), @Service, @Repository 어노테이션 문서를 찾는다.
- ViewResolver beans (prefix, suffix)
4) configuration.xml (mybatis-config.xml)
- typeAlias : DTO 클래스
5) mapper.xml
- namespace 지정
6) root-context.xml
- dataSource : DB 연동 드라이버, url, 계정
- sqlSessionFactory : dataSource, configuration.xml, mapper.xml
- SqlSessionTemplate
여태까지 만든 게시판과 다른 점
1) 게시판 페이징 처리
- service 패키지에 위치한다.
2) 글쓰기 폼과 답글 폼을 분리하지 않았으나 MVC 파일을 분리함
- replyForm.jsp, reply.jsp 는 없고, insert.jsp, insertForm.jsp에서 답글과 원문 글쓰기 모두를 처리한다.
- Controller, DAO, DTO, service, mapper가 분리되어 있다.
3) 분리된 DB 테이블
- 게시판 테이블 / 댓글 테이블이 분리되어 있다.
(게시판 테이블은 (board1 프로젝트에서 사용했던 테이블을 그대로 사용)
- replyboard 테이블의 bno 컬럼에 board 테이블의 num 컬럼을 연결하는 외래키 설정
- on delete cascade 제약조건을 설정하여
부모 테이블의 num 데이터가 삭제되면 자식 테이블의 bno 데이터를 함께 삭제한다.
이전 프로젝트의 테이블을 그대로 사용하고 있으므로
index.jsp를 실행하면 글 목록이 그대로 나타난다.
상세 페이지를 누르면 그제서야 달라진 점이 보인다.
index.jsp를 실행하면 어노테이션 값을 찾아 컨트롤러로 이동한다.
web.xml에서 어노테이션 설정을 *.do가 아닌 초기값 / 그대로 두었기 때문에
값을 받는 형태가 조금 달라져있다.
list.jsp에 가면
계속해서 ${path} 가 따라다니는데, 프로젝트 명인 sboard이다.
페이지 처리를 위한 컨트롤러 메소드.
처음보는 어노테이션이 등장했는데
@PathVariable (주소값 형태-path- 로 받아옴) 는 @RequestParam (여러 자료형으로 받아옴)과 비슷하게
jsp에서 전달한 값을 받는 어노테이션이다.
간단했던 이전 프로젝트의 view.jsp 파일과 달리
새로운 기능인 댓글이 등장했으므로 조금 더 복잡해졌다.
ajax를 활용해 비동기적으로 처리하고 있다.
댓글을 달면 페이지가 바뀌는 것이 아니라 페이지 하단에 즉각 출력된다.
빨간색 영역은 기존의 board1 테이블이 아닌 replyboard 테이블로 DB가 연결된다.
rno : 값을 넘기면 컨트롤러에서 값을 증가하는 SQL문을 호출한다.
bno : 참조키이므로 부모 테이블에서 값을 받아온다.
replytext : textarea에서 입력한 내용이 전달된다.
replyer : 현재는 부모글의 작성자 이름으로 댓글이 작성되도록 설정했다.
지금은 예제 파일이라 다소 엉성하지만 추후 제대로 된 게시판을 만들게 되면
회원 관리 프로그램과 연동하여 사용할 수 있을 것 같다.
댓글 입력 양식은 폼태그로 감싸져 있다.
동기적으로 처리할 때에는 (페이지를 변경해서 값을 넘길 때에는) action 값을 넣는데,
이건 비동기적 처리 방식이므로 action 값이 지정되어 있지 않다.
현재는 부모글의 작성자 이름으로 댓글이 작성되도록 설정됐기 때문에
hidden 객체로 board.wirter, board.num 값을 넘기도록 되어 있다. (부모글의 정보)
댓글창에 내용을 입력하고 확인을 누르는 순간 head 영역에 작성된 함수가 호출된다.
이 함수는 id가 repInsert인 버튼을 클릭하는 순간 클릭 이벤트가 발생하며,
그 이전에 load 함수가 먼저 동작한다.
요청값인 '${path}/slist/num/${board.num} 은, slist의 num 변수에 부모글의 정보 board.num 을 전달하는 내용이다.
정보를 전달하고 나면 가장 먼저 조건문으로 댓글창에 내용이 없을 경우 alert 메시지를 띄우고 있고,
만일 조건을 만족하지 않으면 (댓글창에 내용이 있다면)
상단의 $('#slist').load('${path}/slist/num/${board.num}') 코드를 내가 알고 있는 형태로 변경하면
load('slist?num=${board.num}') 이다.
load 함수의 요청값은 컨트롤러로 이동한다.
댓글 관련 내용은 본문과 따로 파일이 작성되어 있다.
(컨트롤러, DAO, DTO, 서비스, 매퍼, DB테이블)
"/slist/num/{num}" 에서 {num} 은 view페이지에서 board.num 으로 전송한 값이다.
즉, 부모글의 정보인 번호값 이다.
이 부모글 num 을 매개변수로 부모글의 정보를 구해와서 DTO 객체 board에 저장한다.
이 num 데이터는 게시판 테이블, 댓글 테이블의 공통 테이블이므로
댓글 목록을 구해오는 메소드 list를 호출하는 매개변수로 쓰인다.
구해온 값은 slist 라는 이름의 리스트 객체에 저장하여 model 객체로 공유 설정되어
뷰페이지 slist로 이동한다.
body 영역에는 forEach로 루프를 돌려서 리스트에 담긴 데이터를 하나씩 꺼내오는 내용이 작성되어 있다.
items로 설정된 ${slist}는 컨트롤러에서 구해와 뷰 페이지까지 전달된 리스트 객체의 이름이다.
수정, 삭제 버튼은 비동기 형식으로 역시 즉각 실행된다.
다시 view.jsp 로 돌아가서,
클릭 이벤트의 내용을 살펴본다.
만약 textarea가 비어있으면 확인 버튼을 눌렀을 때 alert 창이 뜨게 되어 있다.
댓글이 작성되어 있을 때에는 if 문 아래쪽의 내용이 실행된다.
댓글 작성 폼에서 넘어가는 값은 총 세 가지 이다.
board.wirter, board.num, 그리고 replytext
이 세 가지 값을 비동기적으로 처리하는 내용이 var frmData 부터 시작하는 단락이다.
주석으로 처리한 내용을 축약한 것이 serealize 함수이다.
form 태그 안에 있는 내용을 한꺼번에 구해오는 시리얼라이즈 함수로 한꺼번에 구해온다.
sInsert 값을 가진 어노테이션을 찾아간다.
ReplyBoard 객체 rb 값을 매개로 댓글 insert SQL문을 호출한다.
이전에 보지못한 형태의 selectKey 라는 것이 있다.
keyProperty : selectKey 괄호 안의 SQL문을 실행한 내용을 담을 변수
order : selectKey를 수행할 순서
(Before라고 적혀 있으니 insert SQL 실행 이전에 selectKey SQL문을 먼저 실행)
resultType : 돌려줄 자료형
selectKey SQL문은 replyBoard 테이블의 rno컬럼의 최대값에 +1을 한 결과를 출력하도록 되어 있다.
여기에서 구한 결과를 rno 변수에 저장하여
insert SQL문을 실행할 때, rno 자리에 #{rno} 를 적어주면 selectKey의 결과값인 rno가 들어가게 된다.
각각의 id를 부여한 SQL문으로 따로 처리할 수도 있지만,
selectKey를 사용하여 한꺼번에 처리할 수도 있다.
이렇게 insert문을 실행하고 나서 redirect:slist/num/ 값을 받아 댓글 목록 출력을 계속 유지하게 되는데,
부모글에 대한 정보를 다시 한번 불러온다.
그러면 부모글 컬럼에 같은 값을 가진 댓글 데이터들을 브라우저에 모두 출력하게 된다.
다시 view페이지로 돌아가면,
위 sInsert 어노테이션에서 처리한 내용을 slist라는 아이디값을 가진 div 영역에 출력하는 내용이 작성되어 있다.
그리고 replytext의 값은 초기화된다.
댓글 폼에 내용을 작성하고 확인을 누르면 위와 같은 과정을 거쳐
새로운 댓글이 화면에 출력되고, 댓글 창의 내용은 지워지게 되는 것이다.
이 모든 것들이 페이지를 바꾸지 않고 비동기적으로 처리된다.