Gidhub BE Developer

Spring MVC - @ModelAttribute의 또 다른 사용법

2019-09-13
goodGid

이 글의 코드 및 정보들은 강의를 들으며 정리한 내용을 토대로 작성하였습니다.

Model Attribute

  • @Controller를 사용한 클래스에서

    Model 정보를 초기화 할 때 사용한다.


Example Code

  • 2가지 예시 상황을 통해

    ModelAttribute 속성에 대해 알아보자.

  1. Key 세팅 순서에 따른 결과

  2. Key 값의 대소문자 구분 유무


순서에 따른 결과

Controller

@Controller
@RequestMapping
public class SampleController {

    @ModelAttribute
    public void setCategories(Model model){
        System.out.println("Call setCategories()");
        model.addAttribute("categories", List.of("db","network","algorithm"));
        model.addAttribute("Language", List.of("java","c++"));
    }

    @ModelAttribute("Language")
    public List<String> setLanguage(Model model){
        System.out.println("Call setLanguage()");
        return List.of("java","c++","python");
    }

    @ModelAttribute("writer")
    public List<String> setWriter(Model model){
        System.out.println("Call setWriter");
        return List.of("goodgid","gid","kiyong");
    }

    @GetMapping("/events")
    public String hello(){
        return "hello";
    }
}

Result

Call setCategories() method
Call setLanguage() method
Call setWriter() method

...

ModelAndView:
View name = hello
        View = null
Attribute = categories
    value = db,network,algorithm
Attribute = Language
    value = java,c++
Attribute = writer
    value = goodgid,gid,kiyong
  • setLanguage()함수는

    기존에 Language 라는 Key 값이 설정되어 있기 때문에

    setLanguage()자체가 실행되지 않는다.


Controller

@Controller
@RequestMapping
public class SampleController {

    @ModelAttribute("Language")
    public List<String> setLanguage(Model model){
        System.out.println("Call setLanguage()");
        return List.of("java","c++","python");
    }

    @ModelAttribute
    public void setCategories(Model model){
        System.out.println("Call setCategories()");
        model.addAttribute("categories", List.of("db","network","algorithm"));
        model.addAttribute("Language", List.of("java","c++"));
    }

    @ModelAttribute("writer")
    public List<String> setWriter(Model model){
        System.out.println("Call setWriter");
        return List.of("goodgid","gid","kiyong");
    }

    @GetMapping("/events")
    public String hello(){
        return "hello";
    }
}

Result

Call setLanguage() method
Call setCategories() method
Call setWriter() method

...

ModelAndView:
View name = hello
        View = null
Attribute = Language
    value = java,c++
Attribute = categories
    value = db,network,algorithm
Attribute = writer
    value = goodgid,gid,kiyong
  • setLanguage(), setCategories(), setWriter() 순서로 method가 호출되었다.

    그리고 Language라는 같은 Key에 대해 중복하여 세팅을 할 경우엔

    (= setLanguage() -> setCategories() 순서로 호출 )

    나중에 세팅된 값으로 세팅이 되는 결과를 확인할 수 있다.

Attribute = Language
    value = java,c++

대소문자 구분 유무

Controller

@Controller
@RequestMapping
public class SampleController {

    @ModelAttribute
    public void setCategories(Model model){
        System.out.println("Call setCategories()");
        model.addAttribute("categories", List.of("db","network","algorithm"));
        model.addAttribute("Language", List.of("java","c++"));
    }

    @ModelAttribute("language") // 대소문자 구분한다.
    public List<String> setLanguage(Model model){
        System.out.println("Call setLanguage()");
        return List.of("java","c++","python");
    }

    @ModelAttribute("writer")
    public List<String> setWriter(Model model){
        System.out.println("Call setWriter");
        return List.of("goodgid","gid","kiyong");
    }

    @GetMapping("/events")
    public String hello(){
        return "hello";
    }
}

Result

Call setCategories() method
Call setLanguage() method
Call setWriter() method

...

ModelAndView:
View name = hello
        View = null
Attribute = categories
    value = db,network,algorithm
Attribute = Language
    value = java,c++
Attribute = language
    value = java,c++,python
Attribute = writer
    value = goodgid,gid,kiyong
  • setCategories(), setLanguage(), setWriter() 순서로 method가 호출되었다.

    그리고 Languagelanguage

    각각 Key 값으로 Value가 설정되어 있음을 확인할 수 있다.

  • 대소문자를 구분하여 model에 값을 관리한다.


Test Code

Test Code

@RunWith(SpringRunner.class)
@WebMvcTest
public class SampleControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Test
    public void helloTest() throws Exception {
        mockMvc.perform(get("/events"))
               .andDo(print())
               .andExpect(model().attributeExists("categories"))
               .andExpect(model().attributeExists("Language"))
               .andExpect(model().attributeExists("writer"))
               .andExpect(status().isOk());
    }
}
  • model안에

    특정 attribute 값이 존재하는지 확인하고 싶다면

    model().attributeExists(“ 찾고자 하는 Key 값 “) 메소드를 사용하면 된다.


주의 사항

  • 일반적으로 핸들러 생성 시

    View를 렌더링 할 목적의 핸들러가 아니라면

    핸들러에 @ResponseBody를 사용하여

    Return Value가 View Name이 아니라

    Response Body에 담겨질 값임을 명시해준다.


  • 그렇기 때문에

    우리가 테스트하고자 상황

    (= Model에 Attrubute가 제대로 담겨져 있는가)를

    갖추기 위해서는

    핸들러에 @ResponseBody 애노테이션을 제거해줘야한다.

@ResponseBody 
  • 그렇지 않으면 TC 자체가 실패한다.

Reference


Comments

Index