-
[3-ch10 스프링] 프레젠테이션(웹) 계층의 CRUD 구현Back-End/Spring Legacy 2022. 8. 23. 12:30
앞 포시팅에서, 비즈니스 계층과(Service) 영속계층 (MyBatis, Mapper.xml) 계층 구현은 완료했다. 그럼 스프링 MVC 작업에서 남은 건 Cotroller 이기에 이번 포스팅에선 Controller 메서드를 작성해보도록 하겠다.
https://wonisdaily.tistory.com/53
https://wonisdaily.tistory.com/54
Controller의 작성
스프링 MVC의 Controller는 하나의 클래스 내에서 여러 메서드를 작성하고, @RequestMapping 등을 이용해 URL을 분기하는 구조로 작성할 수 있기 때문에 하나의 클래스에서 필요한 만큼 메서드의 분기를 이용하는 구조로 작성한다.
Tomcat(WAS)을 실행하고 웹 화면을 만들어서 결과를 확인하는 대신 이번 포스팅에서 테스트코드를 작성해서 컨트롤러가 잘 작성됐는지 확인해보도록 하겠다.
일단) 작성하기 전에 반드시 현재 원하는 기능을 호출하는 방식에 대해 다음과 같이 테이블로 정리한 후 코드를 작성하는 것이 좋다.
url, method, parameter, from, url 이동에 대한 항목을 작성한 테이블이다.
BoardController 작성
src/main/java 폴더에 org.zerock.controller 패키지를 선언하고 BoardController 클래스를 설계한다.
BoardCotroller는 @Controller 어노테이션을 추가해서 스프링의 빈으로 인식할 수 있게 하고, @RequestMapping을 통해 '/board'로 시작하는 모든 처리를 BoardController가 하도록 지정한다. BoardController가 속한 org.zerock.contorller 패키지는 servlet-context.xml에 기본으로 설정되어 있으므로 별도의 설정이 필요하지 않다.
BoardController는 BoardService에 대해 의존적이므로 @AllArgsConsructor를 이용해 생성자를 만들고 자동으로 주입하도록 한다. (만약 생성자를 만들지 않을 경우 @Setter(onMethod_ = @Autowired)를 이용해서 처리한다.
< list >
list()는 나중에 게시물의 목록을 전달해야 하므로 Model을 파라미터로 지정하고, 이를 통해서 BoardServiceImpl 객체의 getList() 결과를 담아 전달한다.
<register, modify, remove>
String을 리턴 타입으로 지정하고, RedirectAttributes를 파라미터로 지정한다. 이는 등록 작업이 끝난 후 다시 목록화면으로 이동하기 위함인데, register()는 추가적으로 새롭게 등록된 게시물의 번호를 같이 전달하기 위해 RedirectAttribute를 이용한다.
package org.zerock.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; 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 org.zerock.domain.BoardVO; import org.zerock.service.BoardService; import lombok.AllArgsConstructor; import lombok.extern.log4j.Log4j2; @Controller @Log4j2 @RequestMapping("/board/*") @AllArgsConstructor public class BoardController { private BoardService service; @GetMapping("/list") public void list(Model model) { log.info("list"); model.addAttribute("list", service.getList()); } @PostMapping("/register") public String register(BoardVO board, RedirectAttributes rttr) { log.info("register........" + board); service.register(board); rttr.addFlashAttribute("result", board.getBno()); return "redirect:/board/list"; } @GetMapping("/get") public void get(@RequestParam("bno") Long bno, Model model) { log.info("get" ); model.addAttribute("list", service.get(bno)); } @PostMapping("/modify") public String modify(BoardVO board,RedirectAttributes rttr ) { log.info("modify....."); if(service.modify(board)) { rttr.addFlashAttribute("result", "success"); } return "redirect:/board/list"; } @PostMapping("/remove") public String remove(@RequestParam("bno") Long bno, RedirectAttributes rttr) { log.info("remove ... " +bno); if(service.remove(bno)) { rttr.addFlashAttribute("result", "success"); } return "redirect:/board/list"; } }
BoardContorllerTest
테스트 방식과, 처리 화면 결과는 이전 service나 영속MVC 화면과 똑같이 나오기 때문에 따로 과정을 첨부하진 않겠다.
package org.zerock.controller; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import lombok.Setter; import lombok.extern.log4j.Log4j2; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration({"file:src/main/webapp/WEB-INF/spring/root-context.xml", "file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"}) @Log4j2 public class BoardControllerTests { @Setter(onMethod_ = @Autowired) private WebApplicationContext ctx; private MockMvc mockMvc; @Before public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build(); } @Test public void testList() throws Exception { log.info( 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", "user00")) .andReturn().getModelAndView().getViewName(); log.info(resultPage); } @Test public void tetGet() throws Exception { log.info(mockMvc.perform(MockMvcRequestBuilders.get("/board/get").param("bno", "2")).andReturn() .getModelAndView().getModelMap()); } @Test public void testModify() throws Exception { String resultPage = mockMvc .perform(MockMvcRequestBuilders.post("/board/modify").param("bno", "1").param("title", "컨트롤러 수정된 테스트 새글 제목") .param("content", "컨트롤러 수정된 테스트 새글 내용").param("writer", "user00")) .andReturn().getModelAndView().getViewName(); log.info(resultPage); } @Test public void testRemove() throws Exception { // 삭제전 데이터베이스에 게시물 번호 확인할 것 String resultPage = mockMvc.perform(MockMvcRequestBuilders.post("/board/remove").param("bno", "6")).andReturn() .getModelAndView().getViewName(); log.info(resultPage); } }
반응형'Back-End > Spring Legacy' 카테고리의 다른 글
[3-ch11 Spring view] 게시글 조회, 수정/삭제, 뒤로가기 처리 (0) 2022.08.26 [3-ch11 Spring view] 게시판 목록, 등록 jsp 화면 처리하기, jQuery 통해 Modal 창 띄우기 (0) 2022.08.24 [Spring] GET/POST 두 방식의 특징과 차이점 알아보기 (0) 2022.08.23 [3-ch9 비즈니스 계층] Service의 생성과 설정 (0) 2022.08.19 [3-ch8 스프링] 영속/비지니스 계층의 CRUD 구현, Mapper 인터페이스와 xml (0) 2022.08.19