Spring project 제작 과정 ( CRUD 기능구현 예제)

이기현·2020년 1월 21일
11

2020Camp

목록 보기
16/16

먼저 개발 환경을 설치하여야 한다.

  1. 툴 : Spring Tool Suite 3.9.5 (이클립스)

    -> 이클립스 상단매뉴 Help -> MarketPlace -> STS 설치..

  2. WAS(Web Application Server) = 아파치 톰캣
    was에 대한 설명 참조 : https://gmlwjd9405.github.io/2018/10/27/webserver-vs-was.html

  3. DB - MySQL

    순서 : 먼저 이클립스 EE 버젼과 Tomcat서버를 설치한다. 그 후 이클립스 안에서 STS(Spring Tool Suite)를 다운받는다.

    참조 : http://m.blog.daum.net/chan-0124/80?np_nil_b=-1&categoryId=8

    프로젝트 생성과정

먼저 이클립스에서 Spring project를 생성해야 한다

1.jpg

그 후 template을 Spring MVC Project를 선택한다.

2.jpg

패키지 이름은 3단으로 입력한다 (보통 com.프로젝트명.폴더)

3.jpg

그 후 작성한 프로젝트를 실행해 보기 위해선

  • 프로젝트우클릭 -> run as -> run on server

4.jpg

프로젝트가 빌드 되는 과정

전체 과정 :

flow.jpg

1. web.xml

설정을 위한 설정파일.
즉, 최초로 WAS가 최초로 구동될 때, 각종 설정을 정의해줍니다.
여러 xml파일을 인식하도록 각 파일을 가리켜 줍니다.

여기에서 root-context와 servlet-context파일을 지정해줌

Inkedweb_LI.jpg

참고

  • 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를 비롯한 다른 어노테이션 인식 !

ser.PNG

3. Controller

base-package에 선언된 package안에 있는 @Controller가 인식되게 된다.
그러면 그 Controller가 모델과 뷰를 관리하게 된다.
Url-mapping(@RequestMapping)을 통해서 입력받은 url에 맞는 모델을 실행하게 되고
이후 View를 호출한다.

여기서의 base-package는 com.crud.controller이므로 그 package안에 있는 controller를 인식하게 된다.

home.PNG

위 controller에서 /home url을 입력하에 되면 home이라는 모델이 실행되게 되는데 이 모델은 home이라는 view를 return 하게 된다.

home.PNG
위에서 localhost:8080은 Tomcat server을 의미하고, 뒤에있는 controller는 tomcat-server에서 이 프로젝트를 인식하는 Web project의 이름이다.

프로젝트 우클릭 -> properties -> Web Project Setting 에서 변경가능하다.
set.PNG

이 후 view가 리턴되면 view 폴더안에 있는 view라는 jsp파일이 호출되게 되는데 이 경로는 servlet-context안에서 설정가능하다.

view.PNG
ViewResolver에서 경로의 prefix와 suffix를 설정해 주고 있는데, 즉 return 값이 view라면 /WEB-INF/views/view.jsp 파일이 호출되는 것이다.

view.PNG

2.pom.xml 설정

  1. dependency 추가 !

CRUD 프로젝트 생성시 필요한 여러가지 기능들을 구현한 library들을 추가해주어야 한다
POM.xml 안에 dependency를 추가하여 library를 사용한다!( 다운받아오는건가?)

pon.jpg

dependency는 maven사이트 안에서 가져와서 추가할 수 있다

maven.PNG

3. DB연결을 위한 설정

  1. root-context에 db연결정보 설정하기
    DataSource등록

db.PNG
DB접속을 위해 나의 mysql url정보와 userid , passoword를 설정한다.

  1. Sqlsessionfactory등록

sf.PNG
(Mybatis 사용을 위한 sqlsessionfactory 커넥션 추가)

  1. namespace 설정

ns.jpg
(충돌방지 설정을 위한 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 생성한다.

vo.PNG

그 후 만들어 놓은 DB에 등록된 컬럼을 등록한다.
-> getter와 setter그리고 toString 메소드를 구현한다
-> 화면 우클릭 -> Source -> creat getter setter 클릭

스크린샷(16).png

5. Board-Mapper.xml 작성

1. DAO 와 연동하기 위한 SQL 작성하기

insert,select,update,delete,listAll 쿼리문 작성하기
vo3.PNG

문법 내용 :

vo4.jpg

6. DAO 작성

  • DAO (Data Access Object) : 데이터 접근 객체
  • 서비스 <-> DAO <-> Mapper
  • Service : 컨트롤러(서블릿)의 요청사항을 DAO에 전달
  1. 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변경 !
-> 새로만든 패키지에 있는 내용들의 어노테이션도 인식하기 위해 !

bb.PNG

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. 게시판 목록 페이지 만들기

  1. 선행작업

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>
  1. 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의 기본 주소값 변경 하는법

aa.jpg

aa2.jpg

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"; // 삭제가 완료된 후, 목록페이지로 리턴  
	  }

결과 화면 :

cr1.PNG

cr2.PNG

cr3.PNG

cr4.PNG

cr5.PNG

profile
실력을 쌓아가는 하루하루

2개의 댓글

comment-user-thumbnail
2021년 9월 6일

잘 읽고 갑니다!

답글 달기
comment-user-thumbnail
2022년 7월 9일

정말 딱 베이직 그 자체...!
잘 봤습니다 😊

답글 달기