https://velog.io/@emawlrdl/Spring-project-%EC%A0%9C%EC%9E%91-%EA%B3%BC%EC%A0%95-8yk5n8bogp
먼저 개발 환경을 설치하여야 한다.
- 툴 : 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참조 : http://m.blog.daum.net/chan-0124/80?np_nil_b=-1&categoryId=8
- 프로젝트 생성과정
- 순서 : 먼저 이클립스 EE 버젼과 Tomcat서버를 설치한다. 그 후 이클립스 안에서 STS(Spring Tool Suite)를 다운받는다.
먼저 이클립스에서 Spring project를 생성해야 한다
그 후 template을 Spring MVC Project를 선택한다.
패키지 이름은 3단으로 입력한다 (보통 com.프로젝트명.폴더)
그 후 작성한 프로젝트를 실행해 보기 위해선
- 프로젝트우클릭 -> run as -> run on server
프로젝트가 빌드 되는 과정
전체 과정 :
1. web.xml
설정을 위한 설정파일.
즉, 최초로 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.
2. context.xml
여기에서 context:component-scan을 설정하게 되는데
base-package에 component-scan을 할 패키지 경로를 명시해주면 해당 경로를 포함한 모든 하위 경로에 적용되고, 애노테이션을 명시한 자바 파일들이 Bean으로 동록 되어 사용 가능해진다.
즉 base-package안에 있는 어노테이션을 인식할 수 있게 되는 것이다. 따라서 그 package안에 있는 controller를 비롯한 다른 어노테이션 인식 !
3. 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 파일이 호출되는 것이다.
2.pom.xml 설정
- dependency 추가 !
CRUD 프로젝트 생성시 필요한 여러가지 기능들을 구현한 library들을 추가해주어야 한다
POM.xml 안에 dependency를 추가하여 library를 사용한다!( 다운받아오는건가?)
dependency는 maven사이트 안에서 가져와서 추가할 수 있다
3. DB연결을 위한 설정
- root-context에 db연결정보 설정하기
DataSource등록
DB접속을 위해 나의 mysql url정보와 userid , passoword를 설정한다.
- Sqlsessionfactory등록
(Mybatis 사용을 위한 sqlsessionfactory 커넥션 추가)
- namespace 설정
(충돌방지 설정을 위한 namespace 설정)
-- 나는 이게 왜 안될까 ? ㅠㅠ xml 파일 밑에 namespace라는 항목이 없다 ㅠㅠ
4. DB기초 공사
참조 : http://m.blog.daum.net/chan-0124/70?np_nil_b=1&categoryId=8
5. 5.VO(DTO) 생성
- VO (Value Object) : DB의 정보를 객체화 시키는 용도
- DTO (Data Transfer Object) : 외부 시스템과 데이터 통신을 하기 위함.
여기서는 VO를 생성 !
먼저 프로젝트 이름을 domain으로 해서 패키지를 하나 만들고 게시판 구성을 위한 BoardVO.java 생성한다.
그 후 만들어 놓은 DB에 등록된 컬럼을 등록한다.
-> getter와 setter그리고 toString 메소드를 구현한다
-> 화면 우클릭 -> Source -> creat getter setter 클릭
5. Board-Mapper.xml 작성
1. DAO 와 연동하기 위한 SQL 작성하기
insert,select,update,delete,listAll 쿼리문 작성하기
문법 내용 :
6. DAO 작성
- DAO (Data Access Object) : 데이터 접근 객체
- 서비스 <-> DAO <-> Mapper
- Service : 컨트롤러(서블릿)의 요청사항을 DAO에 전달
- BoardDAO 작성
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변경 !
-> 새로만든 패키지에 있는 내용들의 어노테이션도 인식하기 위해 !
7. Service 작성하기
- Service : 유지보수와 로직프로세스를 유연하게 처리하기 위한 중간 단계.
- 프레임워크 디자인패턴에 들어가며, 프로젝트 규모가 커질수록 관리하기 용이함
controller -> service(interface) -> ServiceImpl -> dao
- project안에 com.sample.service 패키지 만든 후
BoardService.java 와 BoardSeriveImple.java파일 만든다 !
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();
}
}
8. 게시판 목록 페이지 만들기
- 선행작업
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"%>
- BoardController 작성
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에 심부름할 내역(서비스 호출)
}
}
- 3-3. WAS의 기본 주소값 변경 하는법
9.글쓰기 구현
- 글쓰기는 GET & POST 2중으로 구성해야 한다
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"; // 작성이 완료된 후, 목록페이지로 리턴
}
10.글읽기 구현
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 서비스 호출
}
10.글수정/삭제 구현 (최종)
** 글수정과 글삭제는 글읽기(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"; // 삭제가 완료된 후, 목록페이지로 리턴
}
결과 화면 :
댓글