지난 번에 Service 클래스를 구현했다.
Service 클래스를 이용해 뷰로 전달하기 위해
Controller 클래스를 작성해야 한다.
주석들을 참고하며 코드를 보자
@Controller //스프링의 빈으로 인식할 수 있게 어노테이션 추가
@Log4j
@RequestMapping("/board/*") // /board 로 시작하는 모든 처리를 이 클래스에서 하도록 함.
//ServletConfig 클래스에 이 패키지가 설정돼있음 (@ComponentScan)
@AllArgsConstructor //단일 생성자를 만들어 자동 주입
public class BoardController {
private BoardService service;
@GetMapping("/list")
//Model 객체는 컨트롤러에서 처리된 데이터를 뷰로 전달해줌
public void list(Model model) {
log.info("list.............");
//request.setAttribute 와 같은 역할
model.addAttribute("list", service.getList());
}
@PostMapping("/register")
//RedirectAttributes 는 redirect 할때 컨트롤러에서 처리된 데이터가 소멸되지 않게 세션에 보관해줌.
public String register(BoardVO board, RedirectAttributes rttr) {
log.info("register: " + board);
service.register(board);
//세션에 result 값을 보관했다가 redirect 되면 model에 반환
rttr.addFlashAttribute("result", board.getBno());
return "redirect:/board/list";
}
@GetMapping("/get")
//@RequestParam 을 이용해 view 에서 파라미터를 받음
public void read(@RequestParam("bno")Long bno, Model model) {
log.info("/get");
//파라미터를 받아 게시물을 얻고 model에 저장
model.addAttribute("board", service.get(bno));
}
@PostMapping("/update")
//수정, 삭제는 반드시 POST로 처리한다
public String update(BoardVO board, RedirectAttributes rttr) {
log.info("/update");
//modify 메서드는 boolean 값을 반환하기 때문에 if 문을 써서 성공 여부 확인
if(service.modify(board)) {
rttr.addFlashAttribute("result", "success");
}
// 게시물 목록 페이지로 redirect 된다.
return "redirect:/board/list";
}
@PostMapping("/remove")
//수정, 삭제는 반드시 POST로 처리한다
public String remove(@RequestParam("bno") Long bno, RedirectAttributes rttr) {
log.info("/remove");
//update 메서드와 같은 로직
if(service.remove(bno)) {
rttr.addFlashAttribute("result", "success");
}
return "redirect:/board/list";
}
}
컨트롤러를 테스트하는 작업이 필요하다.
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration //WebApplicationContext를 이용하기 위해
@ContextConfiguration(classes = {org.zerock.config.RootConfig.class,
org.zerock.config.ServletConfig.class})
@Log4j
public class BoardControllerTests {
@Setter(onMethod_=@Autowired)
private WebApplicationContext ctx;
//MockMvc 는 말그대로 MVC를 가상으로 흉내내어 테스트해준다.
//톰캣 구동 없이 테스트 가능
private MockMvc mockMvc;
@Before //어노테이션은 이 클래스의 모든 메서드가 시작되기 전에 아래의 메서드를 실행
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
}
@Test
public void testList() throws Exception {
log.info(
//MockMvc 객체 안의 메서드들을 이용해 게시물 목록을 불러오는 테스트
mockMvc.perform(MockMvcRequestBuilders.get("/board/list"))
.andReturn()
.getModelAndView()
.getModelMap()
);
}
@Test
public void testRegister() throws Exception {
String resultPage = mockMvc.perform(
MockMvcRequestBuilders.post("/board/register")
.param("title", "테스트 새글 제목")
.param("content", "테스트 새글 내용")
.param("writer", "user001")
).andReturn().getModelAndView().getViewName();
log.info(resultPage);
}
@Test
public void testGet() throws Exception {
log.info(
mockMvc.perform(MockMvcRequestBuilders.get("/board/get")
.param("bno", "2"))
.andReturn()
.getModelAndView().getModelMap());
}
@Test
public void testUpdate() throws Exception {
String resultPage =
mockMvc.perform(MockMvcRequestBuilders.post("/board/update")
.param("bno", "1")
.param("title", "수정된 테스트 새글 제목")
.param("content", "수정된 테스트 새글 내용")
.param("writer", "user001"))
.andReturn().getModelAndView().getViewName();
log.info(resultPage);
}
@Test
public void testRemove() throws Exception {
String resultPage =
mockMvc.perform(MockMvcRequestBuilders.post("/board/remove")
.param("bno", "9"))
.andReturn().getModelAndView().getViewName();
log.info(resultPage);
}
}