ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [3-ch10 스프링] 프레젠테이션(웹) 계층의 CRUD 구현
    Back-End/Spring Legacy 2022. 8. 23. 12:30

     

    앞 포시팅에서, 비즈니스 계층과(Service) 영속계층 (MyBatis, Mapper.xml) 계층 구현은 완료했다. 그럼 스프링 MVC 작업에서 남은 건 Cotroller 이기에 이번 포스팅에선 Controller 메서드를 작성해보도록 하겠다. 

     

     

     

     

    https://wonisdaily.tistory.com/53

     

    [3-ch8 스프링] 영속/비지니스 계층의 CRUD 구현, Mapper 인터페이스와 xml

    VO 클래스 작성 VO 클래스를 생성하는 작업은 테이블 설계를 준으로 작성하면 된다. tbl_board 테이블의 구성대로 작성한다. 프로젝트에 org.zerock.domain 패키지를 생성하고 BoardVO 클래스를 정의한다. p

    wonisdaily.tistory.com

     

    https://wonisdaily.tistory.com/54

     

    [3-ch9 비즈니스 계층] Service의 생성과 설정

    비즈니스 계층이란? 비즈니스 계층은 고객의 요구사항을 반영하는 계층으로 프레젠테이션 계층(컨트롤러, view) 과 영속 계층(db)의 중간 다리 역할을 하게 된다. 영속 계층은 데이터베이스를 기

    wonisdaily.tistory.com

     

     

     

     

     

    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);
    	}
    	
    	
    
    }
    반응형

    댓글

Designed by Tistory.