2014-10-24 5 views
0

@ModelAttribute 사용에 문제가 있습니다. 주소 주소 -이 두 DTO들 완전히 동일 내부에 하나 개의 속성을 포함, PageDTO 및 SessionDTO :Spring - @ModelAttribute 동작

<mvc:annotation-driven /> 
<context:component-scan base-package="spring.test" /> 
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <property name="prefix" value="/WEB-INF/views/"></property> 
    <property name="suffix" value=".jsp"></property> 
</bean> 

2 DTO들을 갖는 등 상황에 맞는 간단한 봄을 갖는 (3.2.11) MVC 응용 프로그램

메소드를 가져 오거나 설정합니다. 컨트롤러를 갖는

<c:url var="actionURL" value="/processForm"/> 
<form:form method="POST" modelAttribute="pageDto" action="${actionURL}"> 
    <form:label path="address.street">Street: </form:label> 
    <form:input path="address.street"/> 
    <form:label path="address.houseNo">House No: </form:label> 
    <form:input path="address.houseNo"/> 
    <form:label path="address.city">City: </form:label> 
    <form:input path="address.city"/> 
    <form:label path="address.zip">ZIP: </form:label> 
    <form:input path="address.zip"/> 
    <input type="submit" name="searchAddress" value="Submit" /> 
</form:form> 

:

package spring.test.model; 

public class PageDTO implements java.io.Serializable { 
    private Address address; 
    // getters/setters omitted 
} 


package spring.test.model; 

public class SessionDTO implements java.io.Serializable { 
    private Address address; 
    // getters/setters omitted 
} 

package spring.test.model; 

public class Address implements java.io.Serializable { 
    private String street; 
    private String houseNo; 
    private String city; 
    private String zip;  
    // getters/setters omitted 
} 

하나 개의 형태를 가진 addressForm.jsp 갖는 여기

package spring.test.controller; 

// imports omitted 

@SessionAttributes("sessionDto") 
@Controller 
public class FormController { 

    @InitBinder 
    protected void initBinder(WebDataBinder binder) { 
     binder.registerCustomEditor(String.class, new StringTrimmerEditor(true)); 
    } 

    @ModelAttribute("pageDto") 
    public PageDTO initPageDTO() { 
     return new PageDTO(); 
    } 

    @ModelAttribute("sessionDto") 
    public SessionDTO initSessionDTO() { 
     return new SessionDTO(); 
    } 

    @RequestMapping(value = "/", method = RequestMethod.GET) 
    public ModelAndView renderHome(@ModelAttribute("pageDto") PageDTO pageDto, 
      @ModelAttribute("sessionDto") SessionDTO sessionDto) {  
     return new ModelAndView("addressForm", "pageDto", pageDto); 
    } 

    @RequestMapping(value = "/processForm", method = RequestMethod.POST) 
    public ModelAndView processForm(@ModelAttribute("pageDto") PageDTO pageDto, 
      @ModelAttribute("sessionDto") SessionDTO sessionDto) { 
     if(pageDto != null && pageDto.getAddress() != null 
       && sessionDto != null && sessionDto.getAddress() != null) { 
      System.out.println("pageDto.getAddress().getHouseNo(): " + pageDto.getAddress().getHouseNo()); 
      System.out.println("sessionDto.getAddress().getHouseNo(): " + sessionDto.getAddress().getHouseNo()); 
     } 
     return new ModelAndView("addressForm", "pageDto", pageDto); 
    } 

} 

을 그리고 문제를 온다. 주소 양식을 제출하면 두 DTO 모두 양식의 데이터로 채워집니다. 나는 JSP에서 양식 태그에 언급 된 "pageDto"이름 만 모델 속성이 채워 기대

로그 항목을 양식 제출 이벤트에서 :.

[10/24/14 11:23:09:382 CEST] 0000002b SystemOut  O pageDto.getAddress().getHouseNo(): 41 
[10/24/14 11:23:09:382 CEST] 0000002b SystemOut  O sessionDto.getAddress().getHouseNo(): 41 

내가 변경하면 이와 같은 제어부에서 processForm 방법 : 원하는

@RequestMapping(value = "/processForm", method = RequestMethod.POST) 
public ModelAndView processForm(@ModelAttribute("pageDto") PageDTO pageDto, 
     HttpSession httpSession) { 
    SessionDTO sessionDto = (SessionDTO) httpSession.getAttribute("sessionDto"); 
    if(pageDto != null && pageDto.getAddress() != null 
      && sessionDto != null && sessionDto.getAddress() != null) { 
     System.out.println("pageDto.getAddress().getHouseNo(): " + pageDto.getAddress().getHouseNo()); 
     System.out.println("sessionDto.getAddress().getHouseNo(): " + sessionDto.getAddress().getHouseNo()); 
    } 
    return new ModelAndView("addressForm", "pageDto", pageDto); 
} 

... 그것은 일 - sessionDto이 형태의 데이터로 채워 그래서 엔트리 (로그에 sessionDto.getAddress() == 널을 나타나지 NOT되고).

동기 부여 2 DTO들, 하나의 세션에 저장하도록 : 모델의

  • 모든 속성이 양식에 표시됩니다, 그래서 입력 유형을 사용하는 것을 = 숨겨진 느슨한되지 않은 데이터
  • 양식을 제출할 때 사용자가 변경 한 속성을 알아야합니다.

감사합니다.

+0

스토어 스스로 다음과 검색 요청 매개 변수를 기대하고있다. '@ ModelAttribute'로 사용하지 마십시오. 실제로는 그렇게하지 않기 때문입니다. 문제는 데이터 바인딩이 요청 매개 변수를 이름에 따라 객체에 바인딩한다는 것입니다. 따라서 매개 변수'houseNo'가 있고 어떤 모델 객체에도'setHouseNo'가 있다면 그것은 바인딩 될 것입니다. –

+0

그래서 모델 객체를 구별하지 않으면 @ModelAttribute ("name")에있는 이름의 의미는 무엇입니까? –

+0

모델에서 올바른 개체를 검색하지만 모든 모델 개체는 바인딩으로 간주됩니다. –

답변

1

제출시, ModelAttribute의 이름은 주로 미용 효과가 있습니다. 요청 매개 변수는 해시으로 구성됩니다. 여기서 keys는 이전 응답 (*)으로 전송 된 <form:input> 요소의 경로이며 값은 사용자가 양식에서 입력 한 값에서옵니다. 그러나 modelAttribute의 이름은 이 아니며 요청시이 아니며 Spring은이를 추측 할 방법이 없습니다.

그것은 방법의 모든 @ModelAttribute 매개 변수를 사용하고 키 요청 매개 변수의에 해당 속성을 설정하려고 시도하고, 당신이 일을 끝낼 때, 당신은 공급 이름으로 Model에서 그들을 넣습니다.

따라서 이름은 응답을 준비하고 요청을 구문 분석하지 않는 데에만 사용됩니다.

(*) 요청이 양식을 제출에서 유래하지만, 어떤 다른 방법에 의해 생산 될 수있는 경우는 - 단순히 스프링 MVC는 세션에서 그 규칙

+0

감사합니다. –

관련 문제