22.06.08
VO -> serviceInteface -> service -> daoInterface -> dao -> controller -> jsp
서로 의존 관계에 있다.
Interface로 변수를 선언하고 service,dao에 어노테이션을 등록.
메서드 마다 객체를 생성할 필요가 없어진다.
<script>
package com.spring.basic.model;
public class ScoreVO {
private String stuName;
private int kor;
private int eng;
private int math;
private int total;
private double average;
//총점,평균 구하는 메서드
public void calcData() {
this.total = this.kor + this.eng + this.math;
this.average = Math.round((this.total / 3.0) * 100) / 100.0;
}
//getter, setter
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
...
@Override
public String toString() {
return "ScoreVO [stuName=" + stuName + ",
kor=" + kor + ", eng=" + eng + ", math=" + math + ",
total=" + total + ", average=" + average + "]";
}
}
</script>
<script>
package com.spring.basic.service;
import java.util.List;
import com.spring.basic.model.ScoreVO;
public interface IScoreService {
//점수 등록
void insertScore(ScoreVO score);
//점수 전체 조회
List<ScoreVO> selectAllScores();
//점수 삭제
void deleteScore(int num);
//점수 개별 조회
ScoreVO selectOne(int num);
}
</script>
<script>
package com.spring.basic.service;
//자동 빈 등록
@Service
public class ScoreService implements IScoreService {
//service와 DAO사이의 의존성 자동 주입을 위한 변수 선언.
//메서드마다 객체를 생성할 필요가 없음.
@Autowired
private IScoreDAO dao;
@Override
public void insertScore(ScoreVO score) {
score.calcData();//총점,평균 계산
System.out.println("service: " + score);
dao.insertScore(score);
}
@Override
public List<ScoreVO> selectAllScores() {
return dao.selectAllScores();
}
@Override //화면에서 index+1값을 번호로 사용하기 때문에 index는 번호의 -1
public void deleteScore(int num) {
dao.deleteScore(num - 1);
}
@Override
public ScoreVO selectOne(int num) {
return dao.selectOne(num-1);
}
}
</script>
<script>
package com.spring.basic.repository;
public interface IScoreDAO {
//점수 등록
void insertScore(ScoreVO score);
//점수 전체 조회
List<ScoreVO> selectAllScores();
//점수 삭제
void deleteScore(int num);
//점수 개별 조회
ScoreVO selectOne(int num);
}
</script>
<script>
package com.spring.basic.repository;
@Repository //자동 빈 등록
public class ScoreDAO implements IScoreDAO {
//싱글톤패턴 작성 할 필요없음.
//학생들의 점수 정보를 저장할 리스트를 생성(DB 대용으로 사용)
private List<ScoreVO> scoreList = new ArrayList<ScoreVO>();
@Override
public void insertScore(ScoreVO score) {
scoreList.add(score);
}
@Override
public List<ScoreVO> selectAllScores() {
return scoreList;
}
@Override
public void deleteScore(int num) {
scoreList.remove(num);
}
@Override
public ScoreVO selectOne(int num) {
return scoreList.get(num);
}
}
</script>
<script>
package com.spring.basic.controller;
@Controller
@RequestMapping("/score")
public class ScoreController {
//컨트롤러와 서비스 계층 사이의 의존성 자동 주입을 위해 변수를 선언.
@Autowired
private IScoreService service;
//점수 등록 화면을 열어주는 처리를 하는 메서드
@GetMapping("/register")
public String register() {
System.out.println("/score/register: GET");
return "score/write-form";
}
//점수 등록 요청을 처리할 메서드
@PostMapping("/register")
public String register(ScoreVO vo) {
System.out.println("/score/register: POST");
System.out.println("param: " + vo);
service.insertScore(vo);//service에 받아온 객체 넣기
return "score/write-result";
}
//점수 전체 조회를 처리하는 요청 메서드
@GetMapping("/list")
public void list(Model model) {
System.out.println("/score/list: GET");
// List<ScoreVO> list = service.selectAllScores(); 변수 필요 없으면 바로 model에 저장
model.addAttribute("sList", service.selectAllScores());
}
//점수 삭제 요청 처리 메서드
@GetMapping("/delete")
public String delete(@RequestParam("stuNum") int stuNum, RedirectAttributes ra) {
//삭제 처리를 완료하신 후 list 요청이 다시 컨트롤러로 들어갈 수 있도록 처리해 보세요.
//list요청이 다시 들어가서 list.jsp로 갔을 때, 삭제 이후에 간 것이 판단된다면
//브라우저에 '삭제가 완료되었습니다.' 문구를 빨간색으로 띄워보세요.
//(RedirectAttributes 사용, 경고창으로 띄워도 좋아요.)
System.out.println("삭제할 할번: " + stuNum);
service.deleteScore(stuNum);
// ra.addFlashAttribute("msg", stuNum + "번의 삭제가 완료 되었습니다.");
ra.addFlashAttribute("msg","delSuccess");//경고창
return "redirect:/score/list";
}
//점수 개별 조회 화면 처리 메서드
@GetMapping("/search")
public void search() {
System.out.println("/score/search: GET");
}
//점수 개별 조회 요청 처리 메서드
@GetMapping("/selectOne")
public String selectOne(@RequestParam("stuNum") int stuNum,
Model model, RedirectAttributes ra) {
//전체 목록 끌어와서 길이보다 크거나 0과 같거나 작으면 학번이 없는 것이다.
List<ScoreVO> list = service.selectAllScores();
if(stuNum > list.size() || stuNum <= 0) {
ra.addFlashAttribute("msg", "학번 정보가 없습니다.");
return "redirect:/score/search";
} else {
model.addAttribute("stu", service.selectOne(stuNum));
return "score/search-result";
}
}
}
</script>
<body>
<h2>시험점수등록</h2>
<form method="post">
<p>
#이름: <input type="text" name="stuName"> <br>
#국어: <input type="text" name="kor"><br>
#영어: <input type="text" name="eng"><br>
#수학: <input type="text" name="math"><br>
<input type="submit" value="확인">
</p>
</form>
</body>
/basic 컨텍스트루트의 경우 변경,삭제 가능성이 높다.
해결방법.
JSTL : core 설정 추가 후
<a href="/basic/score/register">
아래코드로 컨텍스트루트 빼고 나머지 경로 value에 적어주기.
<a href="<c:url value='/score/register'/>">
<c:url value='uri 경로' />
- value속성 안에 컨텍스트 루트 경로를 제외한 절대 경로를 작성.
- 컨텍스츠 루트를 제외하고 연결이 가능. (컨텍스트 루트 변경 가능성을 대비)
<body>
<h2>점수 등록 성공</h2>
<p>
<a href="<c:url value='/score/register' />">다른 점수 등록하기</a>
<a href="<c:url value='/score/list' />">점수 전체 조회하기</a>
<a href="<c:url value='/score/search' />">점수 개별 조회하기</a>
</p>
</body>
forEach태그에서 varStatus를 사용하면 반복문의 목록수나 목록의 현재 index,
count 등의 위치값을 사용할 수 있습니다.
<body>
<h2>학생들의 전체 성적 조회</h2>
<%-- forEach태그에서 varStatus를 사용하면 반복문의 목록수나 목록의 현재 index,
count 등의 위치값을 사용할 수 있습니다. --%>
<c:forEach var="stu" items="${sList}" varStatus="stuNum">
<p>
학번: ${stuNum.index+1}, 이름: ${stu.stuName}, 국어: ${stu.kor}, 영어: ${stu.eng},
수학: ${stu.math}, 총점: ${stu.total}, 평균: ${stu.average}
<a href="<c:url value='/score/delete?stuNum=${stuNum.index+1}'/>">[삭제]</a>
</p>
</c:forEach>
<a href="<c:url value='/score/register' />"> 다른 점수 등록하기</a>
<%-- <p style="color:red">
${msg}
</p>--%>
<script type="text/javascript">
const msg = "${msg}"
if(msg === "delSuccess") {
alert('삭제가 완료 되었습니다.')
}
</script>
</body>
<body>
<%-- /selectOne 요청을 통해 해당 학번을 가진 학생의 성적 정보를 조회하여
search-result.jsp에 학생의 모든 정보를 적절하게 출력하세요. --%>
<form action="<c:url value='/score/selectOne' />">
<p>
#조회할 학번: <input type="text" name="stuNum" size="5">
<input type="submit" value="확인">
</p>
</form>
<%-- 사용자가 입력한 학번의 학생이 없다면 "학번 정보가 없습니다." 메세지를 띄워보세요. --%>
</body>
<body>
<h2>${stuNum}번 학생 정보</h2>
<p>
#이름: ${stu.stuName} <br>
#국어: ${stu.kor} <br>
#영어: ${stu.eng} <br>
#수학: ${stu.math} <br>
#총점: ${stu.total} <br>
#평균: ${stu.average} <br>
</p>
<a href="<c:url value='/score/search' />">점수 개별 조회</a>
<p style="color:green;">
${msg}
</p>
</body>
<script>
package com.spring.basic.model;
public class BoardVO {
private String writer;
private String title;
private String content;
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
...
}
</script>
<script>
package com.spring.basic.service;
public interface IBoardService {
//게시글 등록
void insertArticle(BoardVO vo);
//전제 게시글 목록
List<BoardVO> getArticles();
//게시글 상세 보기
BoardVO getArticle(int bId);
//게시글 삭제
void deleteArticle(int bId);
//게시글 수정
void updateArticle(int bId, BoardVO vo);
}
</script>
<script>
package com.spring.basic.service;
@Service
public class BoardService implements IBoardService {
@Autowired
private IBoardDAO dao;
@Override
public void insertArticle(BoardVO vo) {
dao.insertArticle(vo);
}
@Override
public List<BoardVO> getArticles() {
return dao.getArticles();
}
@Override
public BoardVO getArticle(int bId) {
return dao.getArticle(bId);
}
@Override
public void deleteArticle(int bId) {
dao.deleteArticle(bId);
}
@Override
public void updateArticle(int bId, BoardVO vo) {
dao.updateArticle(bId, vo);
}
}
</script>
<script>
package com.spring.basic.repository;
public interface IBoardDAO {
//게시글 등록
void insertArticle(BoardVO vo);
//전제 게시글 목록
List<BoardVO> getArticles();
//게시글 상세 보기
BoardVO getArticle(int bId);
//게시글 삭제
void deleteArticle(int bId);
//게시글 수정
void updateArticle(int bId, BoardVO vo);
}
</script>
<script>
package com.spring.basic.repository;
@Repository
public class BoardDAO implements IBoardDAO {
//게시글을 저장할 리스트(DB 대용)
private List<BoardVO> articles = new ArrayList<BoardVO>();
@Override
public void insertArticle(BoardVO vo) {
articles.add(vo);
}
@Override
public List<BoardVO> getArticles() {
return articles;
}
@Override
public BoardVO getArticle(int bId) {
return articles.get(bId - 1);
}
@Override
public void deleteArticle(int bId) {
articles.remove(bId - 1);
}
@Override
public void updateArticle(int bId, BoardVO vo) {
articles.set(bId - 1, vo);
}
}
</script>
<script>
package com.spring.basic.controller;
@Controller
@RequestMapping("/board")
public class BoardController {
@Autowired
private IBoardService service;
// 글 작성 화면을 열어주는 메서드
@GetMapping("/write")
public void write() {
System.out.println("/board/write: GET");
}
// 작성된 글 등록 처리 요청 메서드
@PostMapping("/write")
public String write(BoardVO vo) {
System.out.println("/board/write: POST");
service.insertArticle(vo);
return "redirect:/board/list";
}
// 글 목록 화면 요청
@GetMapping("/list")
public void list(Model model) {
System.out.println("/board/list: GET");
model.addAttribute("articles", service.getArticles());
}
// 글 내용 상세보기 요청 처리 메서드
@GetMapping("/content")
public void content(@ModelAttribute("boardNo") int boardNo, Model model) {
model.addAttribute("article", service.getArticle(boardNo));
}
// 글 수정하기 화면으로 이동 요청
@GetMapping("/modify")
public void modify(@ModelAttribute("boardNo") int boardNo, Model model) {
System.out.println("/board/modify: GET");
model.addAttribute("article", service.getArticle(boardNo));
}
// 글 수정 요청 메서드
@PostMapping("/modify")
public String modify(@RequestParam("boardNo") int boardNo, BoardVO vo) {
System.out.println("/board/modify: POST");
service.updateArticle(boardNo, vo);
return "redirect:/board/content?boardNo=" + boardNo;
}
// 글 삭제하기
@GetMapping("/delete")
public String delete(@RequestParam("boardNo") int boardNo) {
service.deleteArticle(boardNo);
return "redirect:/board/list";
}
}
</script>
<body>
<h2>게시글 등록</h2>
<form method="post">
<p>
# 작성자: <input type="text" name="writer"> <br>
# 제목: <input type="text" name="title"> <br>
# 내용: <textarea rows="3" name="content"></textarea> <br>
<input type="submit" value="등록">
</p>
</form>
</body>
<body>
<h2>게시글 목록</h2>
<table border="1">
<tr>
<th>글번호</th>
<th>제목</th>
<th>작성자</th>
<th>비고</th>
</tr>
<c:forEach var="article" items="${articles}" varStatus="num">
<tr>
<td>${num.index+1}</td>
<td>
<a href="<c:url value='/board/content?boardNo=${num.index+1}'/>">${article.title}</a>
</td>
<td>${article.writer}</td>
<td>
<a href="<c:url value='/board/delete?boardNo=${num.index+1}'/>">[삭제]</a>
</td>
</tr>
</c:forEach>
</table>
<a href="<c:url value='/board/write' />">게시물 작성하기</a>
</body>
<body>
<h2> ${boardNo}번 게시물 내용</h2>
<p>
# 작성자: ${article.writer}<br>
# 제목: ${article.title} <br>
# 내용: <textarea rows="5" readonly=>${article.content}</textarea>
</p>
<a href="<c:url value='/board/list'/>">글 목록 보기</a>
<a href="<c:url value='/board/modify?boardNo=${boardNo}'/>">글 수정 하기</a>
</body>
<body>
<h2>${boardNo}번 게시물 내용 수정</h2>
<form method="post">
<input type="hidden" name="boardNo" value="${boardNo}">
<p>
# 작성자: <input type="text" name="writer" value="${article.writer}"> <br>
# 제목: <input type="text" name="title" value="${article.title}"> <br>
# 내용: <textarea rows="3" name="content">${article.content}</textarea>
<input type="submit" value="수정">
</p>
</form>
</body>