Web Application Structure
Web Application의 일반적 구조
Service 계층과 DAO 계층 구조
@Service와 @Repository Annotation 활용
순서
요청과 함께 들어오는 데이터의 흐름을 처리할 수 있는 Controller 생성
Container에 bean 등록
Controller는 Service가 없으면 동작을 할 수 없으므로 @Autowired를 활용해 의존성 주입하고 자동 객체 등록
package com.spring.basic.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.spring.basic.model.ScoreVO;
import com.spring.basic.service.IScoreService;
@Controller
// Controller로 bean 등록
@RequestMapping("/score")
// 공통 url 지정
public class ScoreController {
// Controller는 Service가 무조건 필요하므로 (종속관계)
// 컨트롤러와 서비스 계층 사이의 의존성 자동 주입을 위해 변수 선언
@Autowired
// autowired를 통해 bean등록한 것을 자동으로 객체 주입
private IScoreService service;
// 점수 등록 화면을 열어주는 처리를 하는 메서드
@GetMapping("/register")
// /score/register 요청이 들어오면 해당 메서드 실행
public String register() {
System.out.println("/score/register : GET");
return "score/write-form";
// register 요청이 들어오면 GET방식으로 score/write-form으로 보내줌
}
// write-form에서 post방식으로 온 데이터를 처리하는 메서드
@PostMapping("/register")
public String register(ScoreVO scores) {
// write-form에서의 값의 파라미터 명은 scoreVO의 변수명과 같으므로 커맨드 객체 활용
System.out.println("/score/register : POST");
System.out.println(scores.toString());
// Service에 scores를 전달해야함
// 위에서 생성한 service를 통해 연결
service.insertScore(scores);
return "score/write-result";
}
// 점수 전체 처리하는 메서드
@GetMapping("/list")
public String list(Model model) {
// 데이터를 보내야 하기 때문에 Model 객체가 필요
System.out.println("/score/list : GET");
// List<ScoreVO> sList = service.listScore();
// service에 전체 리스트 값을 가져와라
model.addAttribute("sList", service.listScore());
// 모델 객체에 값을 담아줌
// 보낼 경로를 작성하게 되면 Model 객체는 자동으로 이동
return "score/list";
}
// 점수를 삭제하는 요청을 처리하는 메서드
@GetMapping("/delete")
public String delete(@RequestParam("stuNum") int stuNum,
RedirectAttributes ra) {
// delete요청이 들어올 때 stuNum라는 이름의 파라미터 값이 들어오기 때문에 requestParam을 사용
// RedirectAttributes 객체를 활용해서 redirect(다시 요청) 진행
System.out.println("/score/delete : GET");
service.deleteScore(stuNum);
ra.addFlashAttribute("message", "학번이 " + stuNum +" 님의 정보가 삭제가 완료되었습니다.");
// redirect할 때 표시할 메세지도 객체에 포함시킴
return "redirect:/score/list";
// 삭제를 진행한 후 다시 redirect를 통해 list에 다시 요청을 보내도록 함
}
// 특정 사람의 점수를 조회하는 메서드
@GetMapping("/search")
public String search() {
System.out.println("/score/search : GET");
return "score/search";
}
// 점수 개별 조회 처리 요청 메서드
@GetMapping("/selectOne")
public String select(@RequestParam("stuNum") int stuNum,
Model model,
RedirectAttributes ra) {
// 파라미터를 받고 조회가 된다면 조회 결과를 보낼 Model객체, 조회가 되지 않는다면 redirect 객체
System.out.println("/score/selectOne : GET");
ScoreVO score = service.selectScore(stuNum);
// 조회가 된다면 score는 null이 아님
// System.out.println(score);
if (score == null) {
// 객체가 없다면
ra.addFlashAttribute("message", "입력하신 " + stuNum + "의 정보가 없습니다.");
return "redirect:/score/search";
// 다시 요청
}
else {
// 객체가 존재한다면
model.addAttribute("score", score);
return "score/search-result";
}
}
}
요청과 함께 들어온 데이터를 바탕으로 연산 및 정제 작업을 진행하며 Controller와 DAO사이에서 데이터가 왔다 갔다 함
Service는 Repository가 없으면 동작을 할 수 없으므로 @Autowired를 활용해 의존성 주입하고 자동 객체 등록
Controller에서 전달 받은 값을 추가적인 연산 진행하고 Repository에 전달
package com.spring.basic.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.spring.basic.model.ScoreVO;
import com.spring.basic.repository.IScoreDAO;
@Service
// anotation Service를 추가하게 되면 container에 bean을 등록함
public class ScoreService implements IScoreService {
// service와 dao는 의존성이 있으므로 객체 생성
// Autowired는 container에서 타입에 맞는 객체를 찾아서 자동 주입
@Autowired
private IScoreDAO dao;
@Override
public void insertScore(ScoreVO score) {
// controller에서 전달된 값을 연산 진행 후 dao에 전달
score.calcData();
// 총점과 평균을 계산
System.out.println(score);
// score객체를 dao에게 전달해야함으로 service와 dao는 연관관계가 있음
dao.insertScore(score);
// dao에 score 객체를 넣어줌
}
@Override
public List<ScoreVO> listScore() {
return dao.listScore();
// controller에 return
// Controller에 값을 보내야하고 딱히 데이터를 처리할 필요가 없음
}
@Override
public void deleteScore(int num) {
dao.deleteScore(num);
}
@Override
public ScoreVO selectScore(int num) {
return dao.selectScore(num);
}
}
DB와 연결하는 계층이며 Service에서 데이터를 전달받아 DataBase의 CRUD 수행
Annotation을 사용하게 되면 Container에 bean 등록 진행
Service에서 전달 받은 값을 DB와 연결하여 연산 진행
package com.spring.basic.repository;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.spring.basic.model.ScoreVO;
@Repository
// 자동 bean 등록 annotation (@Repository)
public class ScoreDAO implements IScoreDAO {
// 학생들의 점수 정보를 저장할 리스트를 생성 (DB 대용)
private List<ScoreVO> scoreList = new ArrayList<>();
@Override
public void insertScore(ScoreVO score) {
scoreList.add(score);
// db에 넣어주는 작업을 현재에는 list로 작성하고 있으므로 간단하게 끄읏
// service에서 가져온 score를 받아서 값을 넣음
}
@Override
public List<ScoreVO> listScore() {
return scoreList;
// service에게 return
// 지금은 DB 연결하지 않아서 간단
}
@Override
public void deleteScore(int num) {
scoreList.remove(num-1);
// 인덱스 값으로 삭제하기 때문에 -1해줌
}
@Override
public ScoreVO selectScore(int num) {
// 저장되어 있지 않은 정보를 조회할 수 있으므로 조건문 삽입
if (num <= scoreList.size()) {
return scoreList.get(num-1);
} else {
// 현재 데이터의 사이즈보다 크다는 것은 잘못된 번호를 입력한 것
return null;
}
}
}
만약 context root가 바뀌게 된다면 해당 root를 모두 변경해야 하기 때문에 많이 귀찮을 수 있음
jstl을 활용하면 context root를 제외하고 절대 경로로 작성하게 되면 자동으로 context root 작성을 해줌
나중에 context root가 변경되어도 변경하지 않아도 됨
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2> 점수 등록 성공 </h2>
<p>
<!-- <a href="/basic/score/register">다른 점수 등록하기</a>
-->
<a href="<c:url value='/score/register' />">다른 점수 등록하기</a>
<!-- jstl을 통해 context root를 제외한 경로를 작성해 놓으면 context root를 붙여줌 -->
<a href="<c:url value='/score/list' />">점수 전체 조회하기</a>
<a href="">점수 개별 조회하기</a>
</p>
</body>
</html>