Spring - @ModelAttribute

SPRING 2014. 3. 25. 06:17
728x90
반응형


@ModelAttribute

@ModelAttribute의 속성은 아래와 같다.

이름 타입 설명
value String 바인드하려는 Model 속성 이름.




@ModelAttribute는 실제적으로 ModelMap.addAttribute와 같은 기능을 발휘하는데, Controller에서 2가지 방법으로 사용된다.

1.메소드 리턴 데이터와 Model 속성(attribute)의 바인딩. 
메소드에서 비지니스 로직(DB 처리같은)을 처리한 후 결과 데이터를 ModelMap 객체에 저장하는 로직은 일반적으로 자주 발생한다.

...
	@RequestMapping(value = "/updateDepartment.do", method = RequestMethod.GET)
	public String formBackingObject(@RequestParam("deptid") String deptid, ModelMap model) {
		Department department = departmentService.getDepartmentInfoById(deptid); //DB에서 부서정보 데이터를 가져온다.
		model.addAttribute("department", department); //데이터를 모델 객체에 저장한다.
		return "modifydepartment";
	}
...

@ModelAttribute를 메소드에 선언하면 해당 메소드의 리턴 데이터가 ModelMap 객체에 저장된다.
위 코드를 아래와 같이 변경할수 있는데, 사용자로 부터 GET방식의 /updateDepartment.do 호출이 들어오면,
formBackingObject 메소드가 실행 되기 전에 DefaultAnnotationHandlerMapping이 org.springframework.web.bind.annotation.support.HandlerMethodInvoker을 이용해서 
(@ModelAttribute가 선언된)getEmployeeInfo를 실행하고, 결과를 ModelMap객체에 저장한다.
결과적으로 getEmployeeInfo 메소드는 ModelMap.addAttribute(“department”, departmentService.getDepartmentInfoById(…)) 작업을 하게 되는것이다.

...
	@RequestMapping(value = "/updateDepartment.do", method = RequestMethod.GET)
	public String formBackingObject() {
		return "modifydepartment";
	}
 
	@ModelAttribute("department")
	public Department getEmployeeInfo(@RequestParam("deptid") String deptid){
		return departmentService.getDepartmentInfoById(deptid); //DB에서 부서정보 데이터를 가져온다.
	}
	또는
	public @ModelAttribute("department") Department getDepartmentInfoById(@RequestParam("deptid") String deptid){
		return departmentService.getDepartmentInfoById(deptid);
	}
...

2.메소드 파라미터와 Model 속성(attribute)의 바인딩. 
@ModelAttribute는 ModelMap 객체의 특정 속성(attribute) 메소드의 파라미터와 바인딩 할때도 사용될수 있다.
아래와 같이 메소드의 파라미터에 ”@ModelAttribute(“department”) Department department” 선언하면 department에는 (Department)ModelMap.get(“department”) 값이 바인딩된다.
따라서, 아래와 같은 코드라면 formBackingObject 메소드 파라미터 department에는 getDepartmentInfo 메소드가 ModelMap 객체에 저장한 Department 데이터가 들어 있다.

...
	@RequestMapping(value = "/updateDepartment.do", method = RequestMethod.GET)
	public String formBackingObject(@ModelAttribute("department") Department department) { //department에는 getDepartmentInfo에서 구해온 데이터들이 들어가 있다.
		System.out.println(employee.getEmployeeid());
		System.out.println(employee.getName());
		return "modifydepartment";
	}
 
	@ModelAttribute("department")
	public Department getDepartmentInfo(@RequestParam("deptid") String deptid){
		return departmentService.getDepartmentInfoById(deptid); //DB에서 부서정보 데이터를 가져온다.
	}
...

 


출처 - http://www.egovframe.org/wiki/doku.php?id=egovframework:rte:ptl:annotation-based_controller&s[]=requestmapping


employee.getEmployeeid()가 아닌 department.getEmployeeid()가 아닌가 싶다.


===================================================================================


  • @ModelAttribute

  • HTTP Request에 포함된 파라미터를 Model 객체로 바인딩함, @ModelAttribute의 'name'으로 정의한 Model객체를 다음 View에서 사용 가능

 


@ModelAttribute

@ModelAttribute는 컨트롤러에서 다음과 같이 두 가지 방법으로 사용할 수 있다.

  • 컨트롤러 메소드에 정의

  • 입력 폼 페이지에서 출력해 줄 reference data를 전달하고자 할 때. 
    SimpleFormController의 referenceData() 메소드와 같은 역할

  • 컨트롤러 메소드의 입력 argument에 정의

  • 메소드의 argument로 입력된 Command 객체에 이름을 부여하고자 할 때.

다음은 위에서 설명한 두가지 방법으로 @ModelAttribute를 사용한 EditUserController 의 예이다.

@Controller
@RequestMapping("/user.do")
public class EditUserController {
    // 컨트롤러 메소드에 정의
    @ModelAttribute("deptList")
    public List populateDeptList() throws Exception {
        return deptService.getDeptList();
    }
    
    @RequestMapping(params = "param=add")
    public String addUser(@ModelAttribute("user")
        User user, BindingResult result, SessionStatus status) throws Exception {
        ...중략...
    }
}

 


출처 - http://dev.anyframejava.org/anyframe/doc/web/3.2.0/webfw/springmvc/basic/annotation_controller.html#aModelAttribute


===================================================================================


Q >  controller 단에서, 예를 들면 아래 인자값 3개의 차이점을 알고 싶습니다.
3개 모두가 같은 의미인것 같은데...
BbsVO selectBbs(
        BbsVO bbsVO,
        @ModelAttribute("bbsVO") BbsVO bbsVO,
        @RequestParam(value="bbsVO") BbsVO bbsVO,
)throws Exception{}

 

A >

우선 첫번째의 경우와 두번째의 경우 모두.. 앞 request parameter들이 VO에 담기는 역할은 똑같습니다..
다만, 두번째의 경우는 @ModelAttribute에 지정된 이름으로 모델 정보에 담아지기 때문에 
View부분(보통 JSP)에서 bbsVO라는 모델이름으로 해당 VO 값들을 참조할 수 있습니다...

세번째의 경우는 bbsVO라는 request parameter를 BbsVO에 넣으라는 의미로.. 위 두개의 의미와 차이가 있으며.. 
하나의 값을 일반적인 VO에 넣을 수 없기 때문에.. 잘못된 형식입니다..

정리하자면.. 두번째 형식을 사용하시면 됩니다.

 

 

Q > 아래 소스를 비교해 주셨으면 합니다. 
@RequestMapping("/sample/addSampleView.do")
public String addSampleView(@ModelAttribute("searchVO") SampleDefaultVO searchVO, Model model)throws Exception { 
 model.addAttribute("sampleVO", new SampleVO());
 return "sample/egovSampleRegister";
}

---->
@RequestMapping("/sample/addSampleView.do")
public String addSampleView(SampleDefaultVO searchVO, Model model)throws Exception { 
 model.addAttribute("sampleVO", new SampleVO());
 return "sample/egovSampleRegister";
}
이렇게 하는 것의 차이점을 알고 싶습니다. 의미상으로는 같은 건가요? 
A  >  
@ModelAttribute를 사용하는 이유는 Model 속성(VO)과 메소드 파라미터의 바인딩을 위해서입니다. 
즉, serchVO에 웹 request parameter값을 넣으려면 @ModelAttribute를 지정하셔야 합니다.
다만, 실제 @ModelAttribute 없이 테스트를 하셔도 parameter값들은 들어가도록 되어 있습니다. 
(Spec.상의 설명과 DispatcherServlet 구현상의 차이인 것 같습니다.) 
다시 말씀드리면 위 경우만으로 보면 차이점이 없습니다.
그러나 다음 JSP인 egovSampleRegister.jsp에서 serchVO 값을 참조하려면 반드시 @ModelAttribute를 지정하셔야 합니다.
@ModelAttribute에 지정된 name으로 JSP 페이지에서 참조할 할 수 있도록 Model정보로 담겨지기 때문입니다.
(별도로 두번째 방식에서 model.attribute("searchVO", searchVO); 코드를 추가하셔도 같은 기능을 수행합니다.)

 

 

Q> jsp 내의 <% %> 안에서 db에서 가져온 값을 사용하는 방법 

A>

Controller에서 담겨진 model 정보는 request 상의 attribute로 jsp에 전달됩니다.
즉 jsp 서버 사이드 스크립트(<% ... %>)에서는 다음과 같은 형식으로 사용하실 수 있습니다.
<%
DataVO data = (DataVO)request.getAttriubte("data");
%>

 

 

Q> db에 저장된 테그 표시

A> <c:out value="${....}" escapeXml="false" /> 

 

 

Q> 오라클 10g clob 등록방법

A>

조회는 resultmap에 clob로 선언을 해주어 표시를 했습니다.
저장은 #contents:CLOB# 이런 방법으로 저장함.

 

Q >  DB resource

egovframework/spring/context-datasource.xml

./WEB-INF/classes/egovframework/spring/context-datasource.xml


ex)

@Controller
@RequestMapping("/annot/registMember.do")
@SessionAttributes("memberInfo") //세션에 저장할 모델 객체
public class RegistMemberAnnotController {
 private Validator validator = new MemberInfoValidator();

 @ModelAttribute("memberInfo") // 스프링은 memberInfo를 뷰에 전달한다.
 public MemberInfo formBacking(HttpServletRequest reqeust) {
  MemberInfo memberInfo = new MemberInfo();
  memberInfo.setAddress(new Address());
  return memberInfo;
 }

 @RequestMapping(method = RequestMethod.GET)
 public String showForm() {
  return "registMemberFormUseAnnot";
 }

 @RequestMapping(method = RequestMethod.POST)
 public String processSubmitForm(@ModelAttribute("memberInfo") //ModelAttribute를 이용하여 커맨드 객체의 이름을 준다.
 MemberInfo command, BindingResult errors, SessionStatus sessionStatus) {
  validator.validate(command, errors);
  if (errors.hasErrors()) {
   return showForm();
  }
  // 로직 처리
  sessionStatus.setComplete(); //세션에 적용된 모델 객체를 삭제할 때 사용
  return "registMember";
 }
}


 

 

728x90
반응형
블로그 이미지

nineDeveloper

안녕하세요 현직 개발자 입니다 ~ 빠르게 변화하는 세상에 뒤쳐지지 않도록 우리모두 열심히 공부합시다 ~! 개발공부는 넘나 재미있는 것~!

,