복붙노트

[SPRING] Spring MVC 3에서 양식 제출 - 설명

SPRING

Spring MVC 3에서 양식 제출 - 설명

Spring 3 MVC에서 폼을 어떻게 제출하는지 이해하는데 문제가 있습니다.

내가하고 싶은 일은 사용자 이름을 가져다가 컨트롤러에 표시하는 컨트롤러를 만드는 것입니다. 그리고 어떻게 든 나는 그것을 해냈지만 실제로 어떻게 작동하는지 이해하지 못합니다. 그래서..

나는 다음과 같은 형태를 가지고있다.

<form:form method="post" modelAttribute="person">
    <form:label path="firstName">First name</form:label>
    <form:input path="firstName" />
    <br />

    <form:label path="lastName">Last name</form:label>
    <form:input path="lastName" />
    <br />

    <input type="submit" value="Submit" />
</form:form>

나는 또한 다음과 같은 컨트롤러를 가지고있다 :

@Controller
public class HomeController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String showHelloPage(Model model) {
        model.addAttribute("person", new Person());
        return "home";
    }

    @RequestMapping(value = "/", method = RequestMethod.POST)
    public String sayHello(Person person, Model model) {
        model.addAttribute("person", person);
        return "home";
    }
}

사용자에게 환영 메시지를 표시하려면 JSP 페이지에서 다음 코드를 사용한다.

<c:if test="${not empty person.firstName and not empty person.lastName}">
    Hello ${person.firstName} ${person.lastName}!
</c:if>

그리고 그것은 작동합니다 (XML 구성 파일은 문제와 관련이 없으므로 생략합니다).

폼의 "modelAttribute"애트리뷰트가 입력 값으로 채워 져야하는 bean 변수를 가리킨다 고 생각했다. 그러나 외모는 매우 다른 방식으로 작용합니다. 내가 선을 제거하면

model.addAttribute("person", new Person());

"showHelloPage"메서드에서 (공통적 인) 예외 "BindingResult도 아니고 ..."이 나타납니다.

또한 처음에는 "sayHello"메소드가 다음과 같이 보입니다.

(...)
public String sayHello(@ModelAttribute("person") Person person, Model model) {
(...)

제 말은 "ModelAttribute"주석이 있다는 것입니다. 내가 읽은 튜토리얼에서는 항상 존재했기 때문에 덧붙였다. 하지만 제거한 후에 모든 것이 잘 돌아갔습니다.

그래서 내 질문은 - "ModelAttribute"anonnatation의 사용은 무엇입니까? 양식에서 "modelAttribute"특성을 생략하는 것이 어떤 방법입니까? 그리고 두 번째 부분은 양식을 만드는 방법 (어쩌면 몇 가지 주석)이 입력 값을 적절한 bean의 속성 (메소드 매개 변수로 선언 됨)에 자동으로 바인딩하는 방법은 무엇입니까? 폼을 보내기 전에 빈 빈을 추가 할 필요없이 (지금해야만하기 때문에).

답장을 보내 주셔서 감사합니다 (이미 읽었으므로 Spring의 설명서 링크는 아닙니다).

해결법

  1. ==============================

    1.이 경우 @ModelAttribute 주석은 Spring이 모델 속성으로 추가해야하는 객체를 식별하는 데 사용됩니다. 모델 속성은 HttpServletRequest 속성의 추상화입니다. 기본적으로 HttpServletRequest 속성으로 들어가는 열쇠로 식별되는 객체입니다. Model # addAttribute (String, Object)를 사용하여 속성을 수동으로 추가하거나 @ ModelAttribute 주석이있는 메소드가 있거나 @ModelAttribute로 메소드 매개 변수에 주석을 추가하여이 작업을 수행 할 수 있습니다.

    이 경우 @ModelAttribute 주석은 Spring이 모델 속성으로 추가해야하는 객체를 식별하는 데 사용됩니다. 모델 속성은 HttpServletRequest 속성의 추상화입니다. 기본적으로 HttpServletRequest 속성으로 들어가는 열쇠로 식별되는 객체입니다. Model # addAttribute (String, Object)를 사용하여 속성을 수동으로 추가하거나 @ ModelAttribute 주석이있는 메소드가 있거나 @ModelAttribute로 메소드 매개 변수에 주석을 추가하여이 작업을 수행 할 수 있습니다.

    이해해야 할 것은 Spring이 처리기 메소드 매개 변수를 해결하고 인수를 주입하는 방법입니다. HandlerMethodArgumentResolver 인터페이스를 사용하여 그렇게합니다. 다수의 구현 클래스 (javadoc 참조)가 있으며 각각은 Spring이 리플렉션을 통해 핸들러 메소드를 호출 (invoke)하는 데 사용할 인수를 반환하여 resolveArgument ()를 수행 할 책임이 있습니다. Spring은 HandlerMethodArgumentResolver supportsParameter () 메소드가 특정 매개 변수에 대해 true를 리턴하는 경우에만 resolveArgument () 메소드를 호출합니다.

    문제의 HandlerMethodArgumentResolver 구현체는 ModelAttributeMethodProcessor에서 확장 한 ServletModelAttributeMethodProcessor이다.

    Spring (3.2)은이 HandlerMethodArgumentResolver와 다른 것을 등록 할 것이다.

    private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
            List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
    
        // Annotation-based argument resolution
        resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
        resolvers.add(new RequestParamMapMethodArgumentResolver());
        resolvers.add(new PathVariableMethodArgumentResolver());
        resolvers.add(new ServletModelAttributeMethodProcessor(false));
        resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
        resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
        resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
        resolvers.add(new RequestHeaderMapMethodArgumentResolver());
        resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
        resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
    
        // Type-based argument resolution
        resolvers.add(new ServletRequestMethodArgumentResolver());
        resolvers.add(new ServletResponseMethodArgumentResolver());
        resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));
        resolvers.add(new RedirectAttributesMethodArgumentResolver());
        resolvers.add(new ModelMethodProcessor());
        resolvers.add(new MapMethodProcessor());
        resolvers.add(new ErrorsMethodArgumentResolver());
        resolvers.add(new SessionStatusMethodArgumentResolver());
        resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
    
        // Custom arguments
        if (getCustomArgumentResolvers() != null) {
            resolvers.addAll(getCustomArgumentResolvers());
        }
    
        // Catch-all
        resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
        resolvers.add(new ServletModelAttributeMethodProcessor(true));
    
        return resolvers;
    }
    

    Spring이 핸들러 메소드를 호출 할 필요가있을 때, 매개 변수 유형과 위의 목록을 반복하여 supportsParameter ()를 지원하는 첫 번째 메소드를 사용합니다.

    ServletModelAttributeMethodProcessor의 두 인스턴스가 추가됩니다 (// 모든 주석을 catch 한 후에 하나). ModelAttributeMethodProcessor에는 @ModelAttribute를 찾아야하는지 여부를 알려주는 annotationNotRequired 필드가 있습니다. 첫 번째 인스턴스는 @ModelAttribute를 찾아야하며 두 번째 인스턴스는 그렇지 않습니다. Spring은 독자적인 HandlerMethodArgumentResolver 인스턴스를 등록 할 수 있도록 이것을한다. // Custom arguments 주석을 보라.

    특히

    @RequestMapping(value = "/", method = RequestMethod.POST)
    public String sayHello(Person person, Model model) {
        model.addAttribute("person", person);
        return "home";
    }
    

    이 경우 Person 매개 변수에 주석을 달았는지 여부는 중요하지 않습니다. ModelAttributeMethodProcessor는이를 해결하고 양식 필드를 바인딩합니다. 요청 매개 변수를 인스턴스의 필드에 추가합니다. ModelAttributeMethodProcessor 클래스가이를 처리 할 때 모델에 추가 할 필요조차 없습니다.

    showHelloPage () 메소드에서

    model.addAttribute("person", new Person());
    

    taglib에 필요합니다. 이것이 입력 필드를 해결하는 방법입니다.

    지정된 매개 변수 (또는 메서드 반환 값)를 모델에 자동으로 추가합니다.

    아니요, 양식 바인딩은 모델에서 개체를 찾고 필드를 html 입력 요소에 바인딩합니다.

    Spring 태그는 모델 속성 객체에 래치되고 해당 필드를 사용하여 입력 및 레이블 요소를 만듭니다. 모델에서 오브젝트가 끝나는 한 오브젝트가 끝나는 방법은 중요하지 않습니다. 지정한 이름 (키)을 가진 모델 속성을 찾을 수없는 경우, 본 것처럼 예외가 발생합니다.

     <form:form method="post" modelAttribute="person">
    

    빈 빈을 제공하는 대신 html을 직접 생성하는 방법도 있습니다. 모든 Spring의 은 빈의 필드 이름을 사용하여 입력 요소를 생성합니다. 그래서 이건

    <form:form method="post" modelAttribute="person">
        <form:label path="firstName">First name</form:label>
        <form:input path="firstName" />
    

    다음과 같은 것을 생성합니다.

    <form method="post" action="[some action url]">
        <label for="firstName">First name<label>
        <input type="text" name="firstName" value="[whatever value firstName field had]" />
        ...
    

    Spring은 name 속성을 사용하여 요청 매개 변수를 인스턴스 필드에 바인딩합니다.

  2. from https://stackoverflow.com/questions/18944627/form-submit-in-spring-mvc-3-explanation by cc-by-sa and MIT license