1. 개요

이 기사에서는 Spring 프레임 워크에서 사용할 수있는 다양한 핸들러 어댑터 구현에 초점을 맞출 것입니다.

2. Handleradapter 란 무엇입니까?

HandlerAdapter는 기본적으로 스프링 MVC에서 매우 유연한 방식으로 HTTP 요청의 처리를 용이하게하는 인터페이스입니다.

메서드를 특정 URL에 매핑하는 HandlerMapping 과 함께 사용됩니다 .

DispatcherServlet은 다음 사용 HandlerAdapter를 이 메소드를 호출 할. 서블릿은 메소드를 직접 호출하지 않습니다. 기본적으로 자체와 핸들러 객체 사이의 다리 역할을하여 느슨하게 결합 된 설계로 이어집니다.

이 인터페이스에서 사용할 수있는 다양한 메서드를 살펴 보겠습니다.

public interface HandlerAdapter {
    boolean supports(Object handler);
    
    ModelAndView handle(
      HttpServletRequest request,
      HttpServletResponse response, 
      Object handler) throws Exception;
    
    long getLastModified(HttpServletRequest request, Object handler);
}

지원의 API는 특정 핸들러 인스턴스가 지원되지 않거나 여부를 확인하는 데 사용됩니다. 핸들러 인스턴스가 지원되는지 여부를 확인하려면이 인터페이스 handle () 메소드를 호출하기 전에 먼저이 메소드를 호출 해야합니다.

핸들 API는 특정 HTTP 요청을 처리하는 데 사용됩니다. 이 메서드는 HttpServletRequestHttpServletResponse 개체를 매개 변수로 전달하여 처리기를 호출합니다 . 그런 다음 핸들러는 애플리케이션 로직을 실행하고 ModelAndView 객체를 반환 한 다음 DispatcherServlet에서 처리합니다 .

3. Maven 의존성

pom.xml에 추가해야하는 Maven 의존성부터 시작하겠습니다 .

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.8.RELEASE</version>
</dependency>

spring-webmvc 아티팩트 의 최신 버전은 여기 에서 찾을 수 있습니다 .

4. HandlerAdapter 유형

4.1. SimpleControllerHandlerAdapter

Spring MVC에서 등록한 기본 핸들러 어댑터입니다. 컨트롤러 인터페이스를 구현하는 클래스를 다루며 컨트롤러 객체에 요청을 전달하는 데 사용됩니다.

웹 애플리케이션이 컨트롤러 만 사용하는 경우 프레임 워크가이 클래스를 요청 처리를위한 기본 어댑터로 사용하므로 HandlerAdapter 를 구성 할 필요가 없습니다 .

이전 스타일의 컨트롤러 ( Controller 인터페이스 구현)를 사용하여 간단한 컨트롤러 클래스를 정의 해 보겠습니다 .

public class SimpleController implements Controller {
    @Override
    public ModelAndView handleRequest(
      HttpServletRequest request, 
      HttpServletResponse response) throws Exception {
        
        ModelAndView model = new ModelAndView("Greeting");
        model.addObject("message", "Dinesh Madhwal");
        return model;
    }
}

유사한 XML 구성 :

<beans ...>
    <bean name="/greeting.html"
      class="com.baeldung.spring.controller.SimpleControllerHandlerAdapterExample"/>
    <bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

BeanNameUrlHandlerMapping의 클래스는이 핸들러 어댑터의 매핑 클래스입니다.

참고 : 사용자 정의 핸들러 어댑터가 BeanFactory에 정의 된 경우이 어댑터는 자동으로 등록되지 않습니다. 따라서 컨텍스트에서 명시 적으로 정의해야합니다. 정의되어 있지 않고 사용자 정의 핸들러 어댑터를 정의한 경우 핸들러에 대한 어댑터가 지정되지 않았다는 예외가 발생합니다.

4.2. SimpleServletHandlerAdapter

이 핸들러 어댑터는 요청을 처리하기 위해 DispatcherServlet 과 함께 작동하는 모든 Servlet 의 사용을 허용합니다 . service () 메서드를 호출하여 DispatcherServlet 의 요청을 적절한 Servlet 클래스로 전달합니다 .

Servlet 인터페이스 를 구현하는 Bean 은이 어댑터에 의해 자동으로 처리됩니다. 기본적으로 등록되어 있지 않으며 DispatcherServlet 의 구성 파일에 다른 일반 빈처럼 등록해야합니다 .

<bean name="simpleServletHandlerAdapter" 
  class="org.springframework.web.servlet.handler.SimpleServletHandlerAdapter" />

4.3. AnnotationMethodHandlerAdapter

이 어댑터 클래스는 @RequestMapping 어노테이션으로 어노테이션 이있는 메소드를 실행하는 데 사용됩니다 . HTTP 메서드 및 HTTP 경로를 기반으로 메서드를 매핑하는 데 사용됩니다.

이 어댑터의 매핑 클래스는 DefaultAnnotationHandlerMapping으로, 유형 수준에서 @RequestMapping 어노테이션 을 처리하는 데 사용 되며 AnnotationMethodHandlerAdaptor 는 메서드 수준에서 처리하는 데 사용됩니다.

이 두 클래스는 DispatcherServlet 이 초기화 될 때 프레임 워크에 의해 이미 등록되어 있습니다. 그러나 다른 핸들러 어댑터가 이미 정의되어있는 경우 구성 파일에서도 정의해야합니다.

컨트롤러 클래스를 정의 해 보겠습니다.

@Controller
public class AnnotationHandler {
    @RequestMapping("/annotedName")
    public ModelAndView getEmployeeName() {
        ModelAndView model = new ModelAndView("Greeting");        
        model.addObject("message", "Dinesh");       
        return model;  
    }  
}

@Controller의 어노테이션은이 클래스의 역할 역할을 나타냅니다 컨트롤러.

@RequestMapping의 어노테이션은 매핑 getEmployeeName () URL에 대한 방법 / 이름입니다.

애플리케이션이 Java 기반 구성을 사용하는지 XML 기반 구성을 사용하는지에 따라이 어댑터를 구성하는 두 가지 방법이 있습니다. Java 구성을 사용하는 첫 번째 방법을 살펴 보겠습니다.

@ComponentScan("com.baeldung.spring.controller")
@Configuration
@EnableWebMvc
public class ApplicationConfiguration implements WebMvcConfigurer {
    @Bean
    public InternalResourceViewResolver jspViewResolver() {
        InternalResourceViewResolver bean = new InternalResourceViewResolver();
        bean.setPrefix("/WEB-INF/");
        bean.setSuffix(".jsp");
        return bean;
    }
}

애플리케이션이 XML 구성을 사용하는 경우 웹 애플리케이션 컨텍스트 XML에서이 핸들러 어댑터를 구성하는 두 가지 방법이 있습니다. spring-servlet_AnnotationMethodHandlerAdapter.xml 파일에 정의 된 첫 번째 접근 방식을 살펴 보겠습니다 .

<beans ...>
    <context:component-scan base-package="com.baeldung.spring.controller" />
    <bean 
      class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
    <bean 
      class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
    <bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

<컨텍스트 : 성분 스캔 /> 태그를 검색하기 위해 패키지를 지정하는 데 사용되는 컨트롤러 클래스.

두 번째 접근 방식을 살펴 보겠습니다.

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

<MVC : 어노테이션 중심이> 태그가 자동으로 스프링 MVC와 함께이 두 클래스를 등록합니다. 이 어댑터는 Spring 3.2에서 사용되지 않으며 RequestMappingHandlerAdapter 라는 새 핸들러 어댑터 가 Spring 3.1에 도입되었습니다.

4.4. RequestMappingHandlerAdapter

이 어댑터 클래스는 Spring 3.1에서 도입 되었으며 Spring 3.2에서 AnnotationMethodHandlerAdaptor 핸들러 어댑터를 사용하지 않습니다 .

@RequestMapping 어노테이션이 달린 메서드실행하는 RequestMappingHandlerMapping 클래스 와 함께 사용됩니다 .

RequestMappingHandlerMapping는 핸들러에 요청 URI의 매핑을 유지하는 데 사용됩니다. 핸들러가 확보되면 DispatcherServlet 은 요청을 적절한 핸들러 어댑터로 디스패치 한 다음 handlerMethod () 를 호출합니다 .

3.1 이전의 Spring 버전에서는 유형 수준 및 메서드 수준 매핑이 두 단계로 처리되었습니다.

첫 번째 단계는 DefaultAnnotationHandlerMapping으로 컨트롤러를 선택하는 것이고 두 번째 단계는 AnnotationMethodHandlerAdapter에 의해 실제 메서드를 호출하는 것 입니다.

Spring 버전 3.1부터는 컨트롤러 식별과 요청을 처리하기 위해 호출해야하는 메소드를 포함하는 단계가 하나뿐입니다.

간단한 컨트롤러 클래스를 정의 해 보겠습니다.

@Controller
public class RequestMappingHandler {
    
    @RequestMapping("/requestName")
    public ModelAndView getEmployeeName() {
        ModelAndView model = new ModelAndView("Greeting");        
        model.addObject("message", "Madhwal");        
        return model;  
    }  
}

애플리케이션이 Java 기반 구성을 사용하는지 XML 기반 구성을 사용하는지에 따라이 어댑터를 구성하는 두 가지 방법이 있습니다.

Java 구성을 사용하는 첫 번째 방법을 살펴 보겠습니다.

@ComponentScan("com.baeldung.spring.controller")
@Configuration
@EnableWebMvc
public class ServletConfig implements WebMvcConfigurer {
    @Bean
    public InternalResourceViewResolver jspViewResolver() {
        InternalResourceViewResolver bean = new InternalResourceViewResolver();
        bean.setPrefix("/WEB-INF/");
        bean.setSuffix(".jsp");
        return bean;
    }
}

애플리케이션이 XML 구성을 사용하는 경우 웹 애플리케이션 컨텍스트 XML에서이 핸들러 어댑터를 구성하는 두 가지 방법이 있습니다. spring-servlet_RequestMappingHandlerAdapter.xml 파일에 정의 된 첫 번째 접근 방식을 살펴 보겠습니다 .

<beans ...>
    <context:component-scan base-package="com.baeldung.spring.controller" />
    
    <bean 
      class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    
    <bean
      class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
    
    <bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

두 번째 방법은 다음과 같습니다.

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

이 태그는이 두 클래스를 Spring MVC에 자동으로 등록합니다.

RequestMappingHandlerMapping 을 사용자 정의해야하는 경우 애플리케이션 컨텍스트 XML에서이 태그를 제거하고 애플리케이션 컨텍스트 XML에서 수동으로 구성해야합니다.

4.5. HttpRequestHandlerAdapter

이 핸들러 어댑터는 HttpRequest 를 처리하는 핸들러에 사용됩니다 . 요청을 처리하고 응답을 생성하기위한 단일 handleRequest () 메서드를 포함하는 HttpRequestHandler 인터페이스를 구현합니다 .

이 메서드의 반환 유형은 void이며 다른 핸들러 어댑터에서 생성 한대로 ModelAndView 반환 유형을 생성하지 않습니다 . 기본적으로 바이너리 응답을 생성하는 데 사용되며 렌더링 할 뷰를 생성하지 않습니다.

5. 응용 프로그램 실행

애플리케이션이 포트 번호가 8082 인 localhost에 배포되고 context-root가 spring-mvc-handlers 인 경우 :

http://localhost:8082/spring-mvc-handlers/

6. 결론

이 기사에서는 Spring 프레임 워크에서 사용할 수있는 다양한 유형의 핸들러 어댑터에 대해 논의했습니다.

대부분의 개발자는 아마도 기본값을 고수 할 것이지만 기본을 넘어서야 할 때 프레임 워크가 얼마나 유연한 지 이해하는 것이 좋습니다.

이 예제의 소스 코드는 GitHub 프로젝트 에서 찾을 수 있습니다 .