먼저 개발 환경을 설치하여야 한다.
툴 : Spring Tool Suite 3.9.5 (이클립스)
-> 이클립스 상단매뉴 Help -> MarketPlace -> STS 설치..
WAS(Web Application Server) = 아파치 톰캣
was에 대한 설명 참조 : https://gmlwjd9405.github.io/2018/10/27/webserver-vs-was.html
DB - MySQL
순서 : 먼저 이클립스 EE 버젼과 Tomcat서버를 설치한다. 그 후 이클립스 안에서 STS(Spring Tool Suite)를 다운받는다.
참조 : http://m.blog.daum.net/chan-0124/80?np_nil_b=-1&categoryId=8
전체 과정 :
설정을 위한 설정파일.
즉, 최초로 WAS가 최초로 구동될 때, 각종 설정을 정의해줍니다.
여러 xml파일을 인식하도록 각 파일을 가리켜 줍니다.
여기에서 root-context와 servlet-context파일을 지정해줌
참고
root-context의 역활 :
servlet-context.xml 과는 반대로 view와 관련되지 않은 객체를 정의합니다.
따라서 Service, Repository(DAO), DB등 비즈니스 로직과 관련된 설정을 해줍니다.
servlet-context의 역활 :
servlet에서 보듯이 요청과 관련된 객체를 정의합니다.
url과 관련된 controller나, @(어노테이션), ViewResolver, Interceptor, MultipartResolver 등의 설정을 해줍니다.
초기 파일을 보시면위와 같은 주석이 있는데,,
DispatcherServlet과 관련된 설정을 해야함을 알 수 있습니다.
DispatcherServlet은 사용자의 요청이 오면 제일 먼저 시작되는 servlet.
여기에서 context:component-scan을 설정하게 되는데
base-package에 component-scan을 할 패키지 경로를 명시해주면 해당 경로를 포함한 모든 하위 경로에 적용되고, 애노테이션을 명시한 자바 파일들이 Bean으로 동록 되어 사용 가능해진다.
즉 base-package안에 있는 어노테이션을 인식할 수 있게 되는 것이다. 따라서 그 package안에 있는 controller를 비롯한 다른 어노테이션 인식 !
base-package에 선언된 package안에 있는 @Controller가 인식되게 된다.
그러면 그 Controller가 모델과 뷰를 관리하게 된다.
Url-mapping(@RequestMapping)을 통해서 입력받은 url에 맞는 모델을 실행하게 되고
이후 View를 호출한다.
여기서의 base-package는 com.crud.controller이므로 그 package안에 있는 controller를 인식하게 된다.
위 controller에서 /home url을 입력하에 되면 home이라는 모델이 실행되게 되는데 이 모델은 home이라는 view를 return 하게 된다.
위에서 localhost:8080은 Tomcat server을 의미하고, 뒤에있는 controller는 tomcat-server에서 이 프로젝트를 인식하는 Web project의 이름이다.
프로젝트 우클릭 -> properties -> Web Project Setting 에서 변경가능하다.
이 후 view가 리턴되면 view 폴더안에 있는 view라는 jsp파일이 호출되게 되는데 이 경로는 servlet-context안에서 설정가능하다.
ViewResolver에서 경로의 prefix와 suffix를 설정해 주고 있는데, 즉 return 값이 view라면 /WEB-INF/views/view.jsp 파일이 호출되는 것이다.
CRUD 프로젝트 생성시 필요한 여러가지 기능들을 구현한 library들을 추가해주어야 한다
POM.xml 안에 dependency를 추가하여 library를 사용한다!( 다운받아오는건가?)
dependency는 maven사이트 안에서 가져와서 추가할 수 있다
DB접속을 위해 나의 mysql url정보와 userid , passoword를 설정한다.
(Mybatis 사용을 위한 sqlsessionfactory 커넥션 추가)
(충돌방지 설정을 위한 namespace 설정)
-- 나는 이게 왜 안될까 ? ㅠㅠ xml 파일 밑에 namespace라는 항목이 없다 ㅠㅠ
참조 : http://m.blog.daum.net/chan-0124/70?np_nil_b=1&categoryId=8
VO (Value Object) : DB의 정보를 객체화 시키는 용도
DTO (Data Transfer Object) : 외부 시스템과 데이터 통신을 하기 위함.
여기서는 VO를 생성 !
먼저 프로젝트 이름을 domain으로 해서 패키지를 하나 만들고 게시판 구성을 위한 BoardVO.java 생성한다.
그 후 만들어 놓은 DB에 등록된 컬럼을 등록한다.
-> getter와 setter그리고 toString 메소드를 구현한다
-> 화면 우클릭 -> Source -> creat getter setter 클릭
insert,select,update,delete,listAll 쿼리문 작성하기
문법 내용 :
public interface BoardDAO {
public void create(BoardVO vo) throws Exception;
public BoardVO read(Integer bno) throws Exception;
public void update(BoardVO vo) throws Exception;
public void delete(Integer bno) throws Exception;
public List<BoardVO> listAll() throws Exception;
}
2.BoardDAOImpl 작성
package com.sample.persistence;
@Repository
public class BoardDAOImpl implements BoardDAO {
@Inject
private SqlSession session;
private static String namespace = "com.myp.mapper.BoardMapper";
@Override
public void create(BoardVO vo) throws Exception {
session.insert(namespace+".create", vo);
}
@Override
public BoardVO read(Integer bno) throws Exception {
return session.selectOne(namespace + ".read", bno);
}
@Override
public void update(BoardVO vo) throws Exception {
session.update(namespace+".update", vo);
}
@Override
public void delete(Integer bno) throws Exception {
session.delete(namespace+".delete", bno);
}
@Override
public List<BoardVO> listAll() throws Exception {
return session.selectList(namespace + ".listAll");
}
}
그 후 servlet-context안에있는 base-package의 root변경 !
-> 새로만든 패키지에 있는 내용들의 어노테이션도 인식하기 위해 !
controller -> service(interface) -> ServiceImpl -> dao
BoardService
package com.sample.service;
import java.util.List;
import com.sample.domain.BoardVO;
public interface BoardService {
public void regist(BoardVO board) throws Exception;
public BoardVO read(Integer bno) throws Exception;
public void modify(BoardVO board) throws Exception;
public void remove(Integer bno) throws Exception;
public List<BoardVO> listAll() throws Exception;
}
BoardServiceImpl
package com.sample.service;
import java.util.List;
import javax.inject.Inject;
import com.sample.domain.BoardVO;
import com.sample.persistence.BoardDAO;
public class BoardServiceImple implements BoardService {
@Inject
private BoardDAO dao;
@Override
public void regist(BoardVO board) throws Exception {
dao.create(board);
}
@Override
public BoardVO read(Integer bno) throws Exception {
return dao.read(bno);
}
@Override
public void modify(BoardVO board) throws Exception {
dao.update(board);
}
@Override
public void remove(Integer bno) throws Exception {
dao.delete(bno);
}
@Override
public List<BoardVO> listAll() throws Exception {
return dao.listAll();
}
}
WAS 구동시 home.jsp 페이지에서 게시판 목록(listAll.jsp)으로 가는 기능 구현
home.jsp 수정
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page session="false" %>
<html>
<head>
<title>Home</title>
</head>
<form action = "listAll" method="get">
<body>
<button type ="submit">CRUD게시판 가기</button>
<h1>
Hello world!
</h1>
<P> The time on the server is ${serverTime}. </P>
</body>
</form>
</html>
2.listAll.jsp 만들기 (view폴더 아래)
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ page session="false"%>
<!DOCTYPE html>
<html>
<head>
<title>게시판 목록</title>
</head>
<form action = "regist" method = "get">
<body>
<table border="1" width="880">
<tr>
<td width="77">
<p align="center">글번호</p>
</td>
<td width="327">
<p align="center">제목</p>
</td>
<td width="197">
<p align="center">작성자</p>
</td>
<td width="155">
<p align="center">작성일</p>
</td>
<td width="90">
<p align="center">조회수</p>
</td>
</tr>
<c:forEach items="${list}" var="boardVO">
<tr>
<td>${boardVO.bno}</td>
<td><a href='/read?bno=${boardVO.bno}'>${boardVO.title}</a></td>
<td>${boardVO.writer}</td>
<td><fmt:formatDate pattern="yyyy-MM-dd HH:mm"
value="${boardVO.regdate}" /></td>
<td><span class="badge bg-red">${boardVO.viewcnt}</span></td>
</tr>
</c:forEach>
</table>
<button type ="submit">글쓰기</button>
</body>
</form>
</html>
package com.sample.controller;
import javax.inject.Inject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.sample.service.BoardService;
@Controller // 컨트롤러임을 명시
@RequestMapping(value = "/") // 주소 패턴
public class BoardController {
@Inject // 주입(심부름꾼) 명시
private BoardService service; // Service 호출을 위한 객체생성
@RequestMapping(value= "/listAll", method = RequestMethod.GET) // 주소 호출 명시 . 호출하려는 주소 와 REST 방식설정 (GET)
public void listAll(Model model)throws Exception { // 메소드 인자값은 model 인터페이스(jsp전달 심부름꾼)
model.addAttribute("list",service.listAll()); // jsp에 심부름할 내역(서비스 호출)
}
}
GET : 단순 글쓰기 페이지 VIEW
POST : 글쓰기 작업 완료 후 DB전송 및 listAll.jsp에 구현
regist.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
<title>글쓰기</title>
</head>
<form method = "post">
<body>
<p><label>제목</label><input type="text" name ="title"></p>
<p><label>작성자</label><input type="text" name="writer" size="15">
</p>
<label>내용</label><p>
<textarea rows="15" cols="65" name = "content"></textarea><p>
<button type = "submit">등록</button>
</form>
</body>
</html>
controller에 기능추가
@RequestMapping(value = "/regist", method = RequestMethod.POST) // POST방식으로 내용 전송
public String registPOST(BoardVO board, RedirectAttributes rttr) throws Exception { // 인자값으로 REDIRECT 사용
service.regist(board); // 글작성 서비스 호출
return "redirect:/listAll"; // 작성이 완료된 후, 목록페이지로 리턴
}
read.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page session="false"%>
<!DOCTYPE html>
<html>
<head>
<title>글읽기</title>
</head>
<form>
<body>
<p><label>글번호</label> <input type="text" name ="bno" value ="${boardVO.bno}" readonly="readonly"></p>
<p><label>제목</label> <input type="text" name ="title" style="background-color:#B0E0E6;" value ="${boardVO.title}" readonly="readonly"></p>
<p><label>작성자</label> <input type="text" name="writer" size="15" value = "${boardVO.writer}"readonly="readonly"><p>
<label>내용</label> <textarea name=content rows ="10" cols="70" style="background-color:#B0E0E6;" readonly="readonly">${boardVO.content}</textarea><br>
<button type="submit" formaction="modify" formmethod="get">수정</button>
<button type="submit" formaction="remove" formmethod="post">삭제</button>
<button type="submit" formaction="listAll" formmethod="get">목록</button>
</body>
</form>
</html>
controller에 기능추가
@RequestMapping(value = "/read", method = RequestMethod.GET) // GET 방식으로 페이지 호출
public void read(@RequestParam("bno")int bno, Model model) throws Exception{
// 인자값은 파라미터 값으로 기본키인 글번호를 기준으로 Model을 사용하여 불러옴
model.addAttribute(service.read(bno)); // read 서비스 호출
}
** 글수정과 글삭제는 글읽기(READ.JSP)페이지에서 작동
** 글수정은 GET/POST 2중으로 구성
modify.jsp 작성
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page session="false"%>
<!DOCTYPE>
<html>
<head>
<title>글수정</title>
</head>
<body>
글 수 정 페 이 지
<form action="modify" method = "post">
<body>
<p><label>글번호</label> <input type="text" name ="bno" value ="${boardVO.bno}" readonly="readonly"></p>
<p><label>제목</label ><input type="text" name ="title" value ="${boardVO.title}" ></p>
<p><label>작성자</label> <input type="text" name="writer" size="15" value = "${boardVO.writer}"></p>
<label>내용</label>
<textarea name=content rows ="10" cols="70" >${boardVO.content}</textarea><br>
<button type ="submit">완료</button>
</body>
</form>
</html>
controller에 기능 추가 - modify
@RequestMapping(value = "/modify", method = RequestMethod.GET) // GET 방식으로 페이지 호출
public void modifyGET(int bno, Model model) throws Exception {
model.addAttribute(service.read(bno)); // 수정을 위한 글읽기 서비스 호출
}
@RequestMapping(value = "/modify", method = RequestMethod.POST)// POST방식으로 데이터 전송
public String modifyPOST(BoardVO board, RedirectAttributes rttr) throws Exception {
service.modify(board); // 글수정 서비스 호출
return "redirect:/listAll"; // 수정이 완료된 후, 목록페이지로 리턴
}
controller에 기능추가 - delete
@RequestMapping(value = "/remove", method = RequestMethod.POST)// POST방식으로 데이터 전송
public String removePOST(@RequestParam("bno") int bno, RedirectAttributes rttr) throws Exception{
service.remove(bno); // 글삭제 서비스 호출
return "redirect:/listAll"; // 삭제가 완료된 후, 목록페이지로 리턴
}
결과 화면 :
잘 읽고 갑니다!