ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스프링(Spring) 개발 - (11) HandlerMethodArgumentResolver 적용
    Spring 2015.05.13 21:08

    이번글에서는 지난글에서 이야기한 HandlerMethodArgumentResolver 라는것을 이야기하려고 합니다. 


    게시판 목록을 작성한 후, 게시판 글 등록 및 수정, 삭제에 대한 내용이 나와야하지 않나? 라고 생각하는 분들도 많이 있으실겁니다. 


    사실 HandlerMethodArgumentResolver 가 없어도 개발은 할 수 있지만, 개발을 더욱 편하게 할수 있는 역할을 하기때문에, 먼저 이야기를 합니다. 


    ------------------------------------------------------------------------------------


    1. HandlerMethodArgumentResolver 란?

    HandlerMethodArgumentResolver 는 스프링 3.1에서 추가된 인터페이스다. 스프링 3.1 이전에는 WebArgumentResolver 라는 인터페이스였는데, 

    스프링 3.1 이후부터 HandlerMethodArgumentResolver 라는 이름으로 바뀌었다. 


    이것이 하는 역할은 다음과 같다. 

    스프링 사용 시, 컨트롤러(Controller)에 들어오는 파라미터(Parameter)를 수정하거나 공통적으로 추가를 해주어야 하는 경우가 있다. 

    예를 들어, 로그인을 한 사용자의 사용자 아이디나 닉네임등을 추가하는것을 생각해보자. 

    보통 그런 정보는 세션(Session)에 담아놓고 사용하는데, DB에 그러한 정보를 입력할 때에는 

    결국 세션에서 값을 꺼내와서 파라미터로 추가를 해야한다.

    그런 경우가 뭐 하나나 두번 정도 있다면 몰라도, 여러번 사용되는 값을 그렇게 일일히 세션에서 가져오는건 상당히 번거로운 일이다.

    HandlerMethodArgumentResolver 는 사용자 요청이 Controller에 도달하기 전에 그 요청의 파라미터들을 수정할 수 있도록 해준다.

    자세한건 이제 소스를 보면서 하나씩 살펴보자.


    1. CommandMap 클래스 생성

    request에 담겨있는 파라미터를 Map에 담아주는 역할을 하는 클래스다. 지난 글에서 컨트롤러를 다시한번 살펴보자.

    public ModelAndView openSampleBoardList(Map<String,Object> commandMap) throws Exception{ 라고 선언을 했었다. 

    여기서 Map<String,Object> commandMap에 사용자가 넘겨준 파라미터가 저장되어 있다. (이는 앞으로 그렇게 하겠다는 의미이고, 현재는 저장되지 않는다.)

    그런데 여기서 문제는 HandlerMethodArgumentResolver는 컨트롤러의 파라미터가 Map 형식이면 동작하지 않는다. 

    엄밀히 말을하면, 스프링 3.1에서 HandlerMethodArgumentResolver를 이용하여 그러한 기능을 만들더라도, 컨트롤러의 파라미터가 Map 형식이면 우리가 설정한 클래스가 아닌, 스프링에서 기본적으로 설정된 ArgumentResolver를 거치게 된다. 

    항상 그렇게 동작하는것은 아니고, 스프링의 <mvc:annotation-driven/>을 선언하게 되면 위에서 이야기한것처럼 동작하게 된다. (본인은 처음에 이것을 몰라서 진짜 몇날 몇일을 삽질했다.)

    따라서 <mvc:annotation-driven/>을 선언하려면 Map을 그대로 사용할 수 없고, 선언하지 않으면 문제는 없다. 그렇지만 앞으로 포스팅할 내용중에는 <mvc:annotation-driven/>을 선언해야 하는 경우가 있기때문에, 여기서는 Map을 대신할 CommandMap을 작성한다.

    first 프로젝트의 common 패키지 밑에 common 패키지를 만들고, 다음을 작성하자.

    CommandMap.java

    package first.common.common;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Set;
    
    public class CommandMap {
    	Map<String,Object> map = new HashMap<String,Object>();
    	
    	public Object get(String key){
    		return map.get(key);
    	}
    	
    	public void put(String key, Object value){
    		map.put(key, value);
    	}
    	
    	public Object remove(String key){
    		return map.remove(key);
    	}
    	
    	public boolean containsKey(String key){
    		return map.containsKey(key);
    	}
    	
    	public boolean containsValue(Object value){
    		return map.containsValue(value);
    	}
    	
    	public void clear(){
    		map.clear();
    	}
    	
    	public Set<Entry<String, Object>> entrySet(){
    		return map.entrySet();
    	}
    	
    	public Set<String> keySet(){
    		return map.keySet();
    	}
    	
    	public boolean isEmpty(){
    		return map.isEmpty();
    	}
    	
    	public void putAll(Map<? extends String, ?extends Object> m){
    		map.putAll(m);
    	}
    	
    	public Map<String,Object> getMap(){
    		return map;
    	}
    }
    
    

    클래스는 별다른 부분은 없다. 내부적으로 Map을 하나 생성하고, 그 맵에 모든 데이터를 담는 역할을 한다. 

    여기서 중요한점은 절대로 Map을 상속받으면 안된다.

    Map을 상속받게 되면, 우리가 작성할 ArgumentResolver를 거치지 않게 되니 주의하자.

    여러가지 메서드들이 보이는데, 거의 대부분은 map의 기본기능을 다시 호출하는것에 지나지 않는다. 보통 가장 많이 사용하는 get, put 메서드만 있더도 큰 문제는 없겠지만, 여기서는 필자가 생각할때 필요한 맵의 기능들을 몇가지 골라서 추가했다. 

    그리고 다른곳에서는 이 CommandMap을 map과 똑같이 사용할 수 있도록 getMap 메서드를 추가했다.


    2. HandlerMethodArgumentResolver 작성

    first > common 패키지 밑에 resolver 패키지를 작성 후 다음을 작성하자.

    CustomMapArgumentResolver.java

    package first.common.resolver;
    
    import java.util.Enumeration;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.springframework.core.MethodParameter;
    import org.springframework.web.bind.support.WebDataBinderFactory;
    import org.springframework.web.context.request.NativeWebRequest;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.method.support.ModelAndViewContainer;
    
    import first.common.common.CommandMap;
    
    public class CustomMapArgumentResolver implements HandlerMethodArgumentResolver{
    	@Override
    	public boolean supportsParameter(MethodParameter parameter) {
    		return CommandMap.class.isAssignableFrom(parameter.getParameterType());
    	}
    
    	@Override
    	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    		CommandMap commandMap = new CommandMap();
    		
    		HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
    		Enumeration<?> enumeration = request.getParameterNames();
    		
    		String key = null;
    		String[] values = null;
    		while(enumeration.hasMoreElements()){
    			key = (String) enumeration.nextElement();
    			values = request.getParameterValues(key);
    			if(values != null){
    				commandMap.put(key, (values.length > 1) ? values:values[0] );
    			}
    		}
    		return commandMap;
    	}
    }
    
    

    이제 하나씩 살펴보자. 

    HandlerMethodArgumentResolver 인터페이스를 상속(인터페이스도 상속이라고 해야하는지 햇갈리긴 하지만...)하면 두가지 메서드를 반드시 구현해야 하는데, supportsParameter 메서드와 resolveArgument 메서드가 그것이다. 


    이름에서 알수 있듯이 supportsParameter 메서드는 Resolver가 적용 가능한지 검사하는 역할을 하고, resolverArgument 메서드는 파라미터와 기타 정보를 받아서 실제 객체를 반환한다.

    supportsparameter 메서드는 컨트롤러의 파라미터가 CommandMap 클래스인지 검사하도록 하였다. 

    이를 위해서 추후 Controller의 Map<String,Object> 형식을 CommandMap이라고 변경할 것이다. (잠시후에 다시 좀 더 자세하게 볼 것이다.)


    그 다음 중요한것이 resolverArgument 메서드다.

    중요한 부분만 살펴보자. 

    먼저, 아까 정의했던 CommandMap 객체를 생성하였다. (23번 줄)

    그 다음으로, request에 담겨있는 모든 키(key)와 값(value)을 commandMap에 저장하였다. (34번 줄) 

    30번 줄부터 32번 줄은 request에 있는 값을 iterator를 이용하여 하나씩 가져오는 로직이다. 

    마지막으로 모든 파라미터가 담겨있는 commandMap을 반환하였다. (37번 줄) 


    3. CustomMapArgumentResolver 등록

    이제 CustomMapArgumentResolver를 등록하자. 

    CustomMapArgumentResolver는 root context 영역에 등록이 되어야 한다. 따라서 action-servlet.xml에 등록해야 한다. (root context에 대한 내용은 추후 다시 하겠다.)

    action-servlet.xml에 다음과 같이 등록하자.

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:context="http://www.springframework.org/schema/context"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
    	<context:component-scan base-package="first"></context:component-scan>
    	
    	<mvc:annotation-driven>
    		<mvc:argument-resolvers>
    			<bean class="first.common.resolver.CustomMapArgumentResolver"></bean>		
    		</mvc:argument-resolvers>
    	</mvc:annotation-driven>
    	
    	<mvc:interceptors>
    		<mvc:interceptor>
    			<mvc:mapping path="/**"/>
    			<bean id="loggerInterceptor" class="first.common.logger.LoggerInterceptor"></bean>
    		</mvc:interceptor>
    	</mvc:interceptors>
    	
        <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
        
        <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="0" />
        <bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />    
        
        <bean
        	class="org.springframework.web.servlet.view.UrlBasedViewResolver" p:order="1" 
        	p:viewClass="org.springframework.web.servlet.view.JstlView" 
        	p:prefix="/WEB-INF/jsp/" p:suffix=".jsp">
       	</bean>
    </beans>
    

    위의 action-servlet.xml은 기존 글에서 작성된것에 CustomMapArgumentResolver를 등록한 내용이다. 실제로 등록을 한 부분은 13~17번째 줄이다. 

    <mvc:"argument-resolvers> 태그를 이용하여 우리가 만든 CustomMapArgumentResolver의 빈(bean)을 수동으로 등록했다. 


    4. Controller의 수정 및 테스트

    이제 위에서 작성한 것들이 정확히 동작하는지 확인해볼 시간이다.

    Controller에 다음을 추가하자. 

    @RequestMapping(value="/sample/testMapArgumentResolver.do")
    public ModelAndView testMapArgumentResolver(CommandMap commandMap) throws Exception{
    	ModelAndView mv = new ModelAndView("");
    	
    	if(commandMap.isEmpty() == false){
    		Iterator<Entry<String,Object>> iterator = commandMap.getMap().entrySet().iterator();
    		Entry<String,Object> entry = null;
    		while(iterator.hasNext()){
    			entry = iterator.next();
    			log.debug("key : "+entry.getKey()+", value : "+entry.getValue());
    		}
    	}
    	return mv;
    }
    

    좀 복잡해보일수도 있는데, 간단한 내용이다. 

    먼저 확인해야 할것은 public ModelAndView testMapArgumentResolver(CommandMap commandMap) throws Exception{ 부분이다. 

    지난 글에서 우리는 Controller를 public ModelAndView openSampleBoardList(Map<String,Object> commandMap) throws Exception{ 와 같이 작성했었다. (http://addio3305.tistory.com/72)

    여기서 Map<String,Object>가 방금 만든 CommandMap으로 바뀌었다. 

    그 후, commandMap에 있는 모든 파라미터를 iterator를 이용하여 출력하였다. 


    이제 서버를 실행시키고 테스트를 해보자. 

    주소창에 localhost:8080/first/sample/testMapArgumentResolver.do?aaa=temp 를 입력해보자. 방금 위에서 만든 컨트롤러에 get방식을 이용하여 aaa라는 키로 temp라는 값을 추가하였다. (주소 뒤에 ?를 붙이고 key=value 형식으로 파라미터를 추가할 수 있다.)


    이클립스의 콘솔창을 확인하면 다음과 같은 결과를 볼 수 있다.


    key : aaa, value : temp라는 로그를 보자. 

    아까 위에서 우리가 get으로 전송한 aaa라는 키와 temp라는 값이다. 

    위와 같은 결과가 나오면 정상적으로 CustomMapArgumentResolver가 등록된 것이다. 


    이번에는 두개의 키와 값을 전송해보자.

    localhost:8080/first/sample/testMapArgumentResolver.do?aaa=value1&bbb=value2 라고 입력해보자.


    정상적으로 aaa와 bbb에 해당하는 값 value1과 value2가 commandMap에 담겨져서 출력됨을 알 수 있다. 


    이것으로 HandlerMethodArgumentResolver에 대한 내용을 마무리한다.


    ------------------------------------------------------------------------------------


    이번글은 조금 짧았지만, 중요한 내용에 대해서 이야기를 했습니다. 


    다음글에서는 이제 게시글 작성 및 수정, 삭제에 대해서 이야기를 할 예정입니다. 


    사용자가 게시글을 작성하면, 그 데이터는 request에 담겨서 서버로 전송이 되고, 서버에서는 그 데이터를 DB에 입력 및 수정을 하게 됩니다.


    오늘 내용은 그 부분을 편하게 하기 위해서 먼저 설명을 했습니다. 


    만약 MapArguemtResolver를 등록하지 않았다면, 컨트롤러에서 request.getParameter 메서드 등을 이용하여 하나하나씩 


    값을 가져와야 하기 때문에 상당히 번거롭고 코드가 길어지게 됩니다. 


    (사실 Annotation을 이용하여 그러한 과정을 생략할 수 있지만, 위에서 이야기한것처럼 값을 수정하거나 추가하기 위해서


    MapArguementResolver를 등록했습니다.)


    그럼 다음글에서 뵙겠습니다.


    first.zip



    댓글 50

    • 이전 댓글 더보기
    • 글쎄 2015.10.22 14:08

      안녕하세요..oracle DB에 데이터를 넣지 않았을 때까지는 "조회된 결과가 없습니다." 까지 잘 나옵니다. 근데 레코드를 추가했는 데도 마찬가지네요..
      마치 캐시에 얹혀진게 그대로 보이는 거 같아요. Table 레코드의 변화를 반영해 주지 못하네요..

      테이블을 drop시키면 에라가 발생하는 거로 보아서 db에 연결은 된 거 같은데요.



      저는 오라클 11gR2를 깔았습니다.

      의견 부탁드리겠습니다. 감사합니다.

      • Favicon of https://addio3305.tistory.com BlogIcon 카루시에라 2015.10.22 19:40 신고

        토드 등의 툴을 이용해서 DB에 데이터를 입력하고 Commit을 안하신것 같습니다. 그 외에는 오라클이라고 특별히 안될 이유가 없어서요.

    • 글쎄 2015.10.22 14:10

      context_datasource.xml에서 mysql로 설정해서 해보면 mysql은 레코드의 변화를 그대로 잘 반영해 줍니다. oracle은 머가 문제일까요..

      감사합니다

    • 개발자3 2015.11.08 21:38

      음 현재 이전까지블로그 반나절만에 정주했습니다~ 넘 쉽게 되있어서 금방금방 따라왔습니다
      댓글보면서 거의 대부분 해결책도있고
      다름이 아니라 2가지가 궁금합니다.
      1. 현재 console에 찍히는데 쿼리문 날아가는것은 찍히게 할수는 없는지?
      2. 이번 게시물에서 하시는 부분이 매번 session에서 가져오는 것보다 좋다고하시는것같은데.
      둘의 차이가 큰가해서 여쭈어봅니다.
      아 그리고 좀 구체적인 사용 예시도 하나 알려주시면감사합니다

      • Favicon of https://addio3305.tistory.com BlogIcon 카루시에라 2015.11.09 17:51 신고

        1. http://addio3305.tistory.com/66 글을 참조하세요.
        2. 혼자서 한두개의 파일을 작성하는 경우라면 상관이 없지만, 실제 프로젝트에서는 한두개의 파일로 만들어지는게 아닙니다. 따라서 여러가지 값이 공통적으로 사용되는데, (예를 들어 로그인한 사용자의 아이디 같은것들) 이것들을 항상 세션에서 가져오는건 귀찮은 일이죠. 또 개발하다가 잊어먹어서 에러가 발생하는 요인이 되기도 하구요. 그런점에서 이런 방식을 사용합니다.

        그리고 구체적인 사용 예시라는건 이 HandlerMethodArgumentResolver를 말씀하시는게 맞나요? 그것은 앞으로의 글을 보시면 볼 수 있습니다.

    • 서현아빠 2015.12.17 10:51

      Spring을 공부해 보고 있습니다. 게시판도 성공했습니다.ㅎㅎ
      덕분에 실습해 볼수 있어서 감사합니다.

      다른분들은 콘솔에서 로그가 잘 보이나요?
      전 이렇게 실행되네요...
      HTTP Status 404 - /first/WEB-INF/jsp/.jsp

      type Status report

      message /first/WEB-INF/jsp/.jsp

      description The requested resource is not available.
      고민해 봐야겠습니다.

    • 개발자가되어라 2015.12.18 11:11

      정말 좋은강좌 감사합니다.

      한가지 궁금한점이 있는데요

      저는 지금까지 DTO를 활용하여 프로젝트를 진행해왔습니다.

      아직 모든 강좌를 보진 않았지만 이 글을 봣을때는

      DTO를 MAP으로 대신하는 것 같은데요

      어떤것이 더 좋은 방식인지 궁금합니다

      • Favicon of https://addio3305.tistory.com BlogIcon 카루시에라 2015.12.18 20:09 신고

        각각 장단점이 있습니다. 이야기를 하기에는 좀 길어질테구요. 각각 상황에 따라 다르게 쓰는게 좋다는 원론적인 이야기밖에 안될것같네요. 저는 개인적으로는 Map을 더 선호하지만 반대로 VO를 선호하는 사람들도 있습니다. 그에 대한 의견들은 구글에서 map vs dto로 검색하면 꽤 많이 나오니 한번 쭉 읽어보심이 좋을듯하네요.

    • Favicon of http://opera201.tistory.com BlogIcon opera 2016.01.18 17:53

      카루님 좋은 강의 감사드립니다. 다름이아니라 위에 언급하신 것 처럼 map대신 dto형식으로
      제가 작성을 해보았는대요 다름이아니라 list와 Content(내용부분)은 db값이 제대로 인식이되어 출력이 잘 됩니다. 그런대 예를들어 <![CDATA[
      INSERT INTO BOARD
      (
      IDX,
      TITLE,
      CONTENT,
      COUNT,
      REG_DATE,
      WRITER
      )
      VALUES
      (
      BOARD_SEQ.NEXTVAL,
      #{TITLE},
      #{CONTENT},
      0,
      SYSDATE,
      'Admin'
      )
      ]]> 이렇게 insert구문중에 value에 해당하는 #{ } 구문에 값들이 logger을 찍어봤을때 ERROR: jdbc.audit - 2. PreparedStatement.execute() INSERT INTO BOARD
      (
      IDX,
      TITLE,
      CONTENT,
      COUNT,
      REG_DATE,
      WRITER
      )
      VALUES
      (
      BOARD_SEQ.NEXTVAL,
      NULL,
      NULL,
      0,
      SYSDATE,
      'Admin'
      )
      java.sql.SQLException: ORA-01400: NULL을 ("SYSTEM"."BOARD"."TITLE";) 안에 삽입할 수 없습니다
      이렇게 나오면서 그냥 Null이라고 표현이됩니다.
      심각: Servlet.service() for servlet [appServlet] in context with path [/test] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException:
      ### Error updating database. Cause: java.sql.SQLException: ORA-01400: NULL을 ("SYSTEM"."BOARD"."TITLE";) 안에 삽입할 수 없습니다

      ### The error may involve defaultParameterMap
      ### The error occurred while setting parameters
      ### SQL: INSERT INTO BOARD ( IDX, TITLE, CONTENT, COUNT, REG_DATE, WRITER ) VALUES ( BOARD_SEQ.NEXTVAL, ?, ?, 0, SYSDATE, 'Admin' )
      ### Cause: java.sql.SQLException: ORA-01400: NULL을 ("SYSTEM"."BOARD"."TITLE";) 안에 삽입할 수 없습니다
      혹시 왜 그런지 알 수 있을까요? 구글 검색해 봐도 잘 모르겠습니다.

    • Kurt 2016.01.25 14:44

      아~ 그 동안 인터셉터 부분에서 부터 잘 안되던 문제가 있었는데 오늘 전체적으로 pom.xml에서의 각 라이브러리의 버젼들을 현재 올라와있는 최신 버젼으로 해주니 이상 없이 잘 되네요.
      하지만 springframework의 경우 최신 버젼인 4.x대로 해주면 jacksonjsonMapper 관련 에러(class not found 등)가 발생하네요. 그래서 3.x대의 가장 윗 단계인 3.2.9로 해주니 아무 이상이 없는데 혹시 해결 방법이 있는지 궁금합니다.

    • 하하하이니 2016.01.28 13:56

      감동하면서 읽고 따라하고 배우고 있습니다. 감사합니다!

    • 와니 2016.02.12 16:46

      annotation-driven 태그를 mvc:annotation-driven와 함께 사용하니 CommandMap에 아무 것도 담지를 못하더군요. 이걸로 1시간 삽질 ㅎㅎㅎ

    • 왕초보 2016.02.24 10:52

      와 정말 좋은글 감사합니다~~ 머가 하나 달려있었으면 강좌보면서 클릭해드렸을텐데 ㅎㅎ

      메일로 구독하고 싶지만 구독할 방법이 없네요..

    • 초보신입개발 2016.04.27 18:21

      정말쉽게설명잘하시네요 감사드립니다

    • 손님 2016.06.28 18:03

      정말 감사합니다.
      WebArgumentResolver 방식으로 줄곧 써오다가 스프링 4.x 로 올리면서 사용할려니 안되서,
      한참 찾을뻔 하다가 이렇게 좋은 정보 얻어서 금방 해결했습니다.
      정말 고맙습니다

    • blacklance 2016.06.30 21:58

      블로그글이 많은 도움이 됩니다. /sample/testMapArgumentResolver.do?aaa=test 로 테스트시 파라미터에 대한 내용이 진행되지 않습니다. 즉 콘솔에 표시가 안되는데 어떤 부분을 살펴봐야할까요? mvc:annotation-driven 태그설정과 CustomMapArgumentResolver 파일과 CommandMap 파일을 생성하였습니다.

    • WPJW 2016.09.04 17:48

      흠 로그가 안나와서 여러번 이번장에있는 소스를 다시가져와서 해봐도 콘솔에 로그가 안뜨네요..

      -제가 오타를 넣은건지 업로드 해주신 프로젝트로 import해서 하니까 잘 되네요-

    • List<map<String,Object>> 2017.01.18 10:56

      안녕하세여 파라미터 에 궁금한게 생겨서 어쭙니다.
      write 페이지에서 체크박스 만들어서 체크 하고 작성하기 누르면 체크된 값만
      java.lang.String;@41713092 이런 오류가 나서요

    • 새벽 두시 2017.03.16 13:27

      하나하나 따라하면서 하고 있는데 정말 감사합니다.

    • 1212 2017.05.18 00:22

      value의 한글처리 부분이 깨지는 점은 어디서 처리해야하나여? web.xml에도 jsp 파일에도 필요한 인코딩 부분은 다넣었습니다 ㅠ

    • 댓글 달아주시려나 2018.08.10 18:01

      너무 오래전글이라 답글 해주실진 모르겟지만 이거 하는과정이
      Controller 에서 Parameter 가는것 Map.put 이거 구지 안하고 보내는 그런 과정인가요?

      • Favicon of https://intro0517.tistory.com BlogIcon 전재훈 2018.08.24 16:22 신고

        제가 대신 답변드려도 되려나요 ~
        HandlerMethodArgumentResolver 인터페이스는 컨트롤러에서 파라미터를 바인딩해주는 역할을 하는게 맞습니다.
        HandlerMethodArgumentResolve 인터페이스 기반으로 구현된 @RequestParam, @RequestBody, @ModelAttribute 등의 어노테이션들이 많이 사용되니까 참고하시면 좋을 것 같습니다.

    • 개린이 2018.12.11 13:34

      처음하시는 분들 패키지 경로 잘 설정해주세요... 별 것도 아닌 거로 2시간 날렸습니다.
      Bean 객체를 찾지 못하는 에러는.. 무조건 경로였습니다 저 같은 경우에는.. ㅠㅠ

    • 조언이필요해 2019.01.17 20:02

      CommandMap 사용시 validator 를 적용할려면 어떻게 해야 하나요?

Designed by Tistory.