1. 소개
간단히 말해, Front Controller 디자인 패턴 에서 단일 컨트롤러는 들어오는 HttpRequest 를 모든 애플리케이션의 다른 컨트롤러 및 핸들러로 보내는 역할을 합니다.
Spring의 DispatcherServlet 은이 패턴을 구현하므로 HttpRequests 를 올바른 핸들러로 올바르게 조정해야합니다 .
이 기사에서는 Spring DispatcherServlet의 요청 처리 워크 플로 와이 워크 플로에 참여하는 여러 인터페이스를 구현하는 방법을 살펴 보겠습니다.
2. DispatcherServlet 요청 처리
기본적으로 DispatcherServlet 은 들어오는 HttpRequest를 처리 하고 요청을 위임 하며 Spring 애플리케이션 내에서 구현 된 구성된 HandlerAdapter 인터페이스 에 따라 해당 요청을 처리하고 핸들러, 컨트롤러 엔드 포인트 및 응답 객체를 지정하는 수반되는 어노테이션을 처리합니다.
DispatcherServlet 이 구성 요소를 처리하는 방법에 대해 더 자세히 살펴 보겠습니다 .
- WebApplicationContext를 (A)에 연결된 DispatcherServlet이 키는 아래 DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE이 프로세스의 모든 요소를 검색하고 이용할 수있다
- DispatcherServlet은 의 모든 구현 발견 HandlerAdapter를 사용하여 운영자에 대해 구성된 인터페이스 - 및 getHandler ()를 각각 발견하고 구성 구현 핸들을 통해 요청 핸들을 () 프로세스의 나머지 부분을 통해
- LocaleResolver의은 임의로 로케일을 해결하는 과정에있는 요소를 사용하는 요청에 바인딩
- ThemeResolver은 임의로 같은 뷰와 같은 요소를 사용할 수 있도록 테마를 결정하라는 요청에 바인딩
- 경우 MultipartResolver가 지정된 요청을 위해 검사된다 의 MultipartFile S - 발견 된 모든은 래핑된다 MultipartHttpServletRequest를 추가 처리
- WebApplicationContext 에서 선언 된 HandlerExceptionResolver 구현은 요청 처리 중에 throw되는 예외를 선택합니다.
여기 에서 DispatcherServlet 을 등록하고 설정하는 모든 방법에 대해 자세히 알아볼 수 있습니다 .
3. HandlerAdapter 인터페이스
HandlerAdapter의 인터페이스 컨트롤러, 서블릿의 사용을 용이하게 HttpRequests을 몇 가지 특정 인터페이스를 통해 경로 및 HTTP. 따라서 HandlerAdapter 인터페이스는 DispatcherServlet 요청 처리 워크 플로 의 여러 단계에서 필수적인 역할을합니다 .
먼저 각 HandlerAdapter 구현은 디스패처의 getHandler () 메서드 에서 HandlerExecutionChain에 배치됩니다 . 그런 다음 각 구현 은 실행 체인이 진행됨에 따라 HttpServletRequest 객체를 핸들 () 합니다 .
다음 섹션에서는 가장 중요하고 일반적으로 사용되는 몇 가지 HandlerAdapter 를 자세히 살펴 봅니다.
3.1. 매핑
매핑을 이해하려면 컨트롤러가 HandlerMapping 인터페이스에 매우 중요하기 때문에 컨트롤러에 어노테이션을 추가하는 방법을 먼저 살펴 봐야합니다 .
SimpleControllerHandlerAdapter는 없이 명시 적으로 컨트롤러의 구현을 가능하게 @Controller의 어노테이션.
RequestMappingHandlerAdapter의 지원 방법은 어노테이션 @RequestMapping의 어노테이션 .
여기서는 @Controller 어노테이션 에 초점을 맞출 것이지만 SimpleControllerHandlerAdapter를 사용하는 여러 예제가 있는 유용한 리소스 도 사용할 수 있습니다.
@RequestMapping 어노테이션은 핸들러가 사용할 수있는 특정 엔드 포인트 설정 내에서 의 WebApplicationContext 와 연관된를.
'/ user / example' 엔드 포인트 를 노출하고 처리 하는 컨트롤러 의 예를 살펴 보겠습니다 .
@Controller
@RequestMapping("/user")
@ResponseBody
public class UserController {
@GetMapping("/example")
public User fetchUserExample() {
// ...
}
}
@RequestMapping 어노테이션에 지정된 경로 는 HandlerMapping 인터페이스 를 통해 내부적으로 관리 됩니다.
URL 구조는 당연히 DispatcherServlet 자체에 상대적 이며 서블릿 매핑에 의해 결정됩니다.
따라서 DispatcherServlet 이 '/'에 매핑되면 모든 매핑이 해당 매핑에 포함됩니다.
그러나 서블릿 매핑이 대신 ' / dispatcher '인 경우 @ RequestMapping 어노테이션은 해당 루트 URL에 상대적이됩니다.
'/'는 서블릿 매핑의 '/ *'와 동일하지 않습니다 ! '/'는 기본 매핑이며 모든 URL을 디스패처의 책임 영역에 노출합니다.
'/ *'는 많은 새로운 Spring 개발자들에게 혼란 스럽습니다. 동일한 URL 컨텍스트를 가진 모든 경로가 디스패처의 책임 영역에 있음을 지정하지는 않습니다. 대신 다른 디스패처 매핑을 무시하고 무시합니다. 따라서 '/ example'은 404로 표시됩니다!
따라서 '/ *'는 매우 제한된 상황 (예 : 필터 구성)을 제외하고 사용해서는 안됩니다 .
3.2. HTTP 요청 처리
DispatcherServlet 의 핵심 책임은 들어오는 HttpRequest 를 @Controller 또는 @RestController 어노테이션으로 지정된 올바른 핸들러 로 디스패치하는 것 입니다.
참고로 @Controller 와 @RestController 의 주요 차이점 은 응답이 생성 되는 방식입니다. @RestController 는 기본적으로 @ResponseBody 도 정의합니다 .
Spring의 컨트롤러에 대해 훨씬 더 깊이 들어가는 글은 여기 에서 찾을 수 있습니다 .
3.3. 의 ViewResolver 인터페이스
의 ViewResolver는 (A)에 부착된다 DispatcherServlet을 온 구성 설정 등 의 ApplicationContext 개체.
의 ViewResolver는 결정의 종류 뷰의 디스패처에 의해 그들이 제공하는 곳에서 봉사하는 것을 모두 .
다음은 JSP 페이지를 렌더링하기 위해 AppConfig 에 배치 할 구성의 예입니다 .
@Configuration
@EnableWebMvc
@ComponentScan("com.baeldung.springdispatcherservlet")
public class AppConfig implements WebMvcConfigurer {
@Bean
public UrlBasedViewResolver viewResolver() {
UrlBasedViewResolver resolver
= new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/view/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
}
매우 간단합니다! 여기에는 세 가지 주요 부분이 있습니다.
- 프리픽스 설정, 내에서 설정된 뷰를 찾기위한 기본 URL 경로를 설정합니다.
- 접미사를 통해 설정되는 기본보기 유형
- JSTL 또는 Tiles와 같은 기술이 렌더링 된 뷰와 연관 될 수 있도록 리졸버에 뷰 클래스 설정
한 가지 일반적인 질문은 디스패처의 ViewResolver 와 전체 프로젝트 디렉토리 구조가 얼마나 정확하게 관련되어 있는지 와 관련이 있습니다 . 기본 사항을 살펴 보겠습니다.
다음은 Spring의 XML 구성을 사용 하는 InternalViewResolver에 대한 예제 경로 구성입니다 .
<property name="prefix" value="/jsp/"/>
예제를 위해 애플리케이션이 다음에서 호스팅되고 있다고 가정합니다.
http://localhost:8080/
이것은 로컬로 호스팅되는 Apache Tomcat 서버의 기본 주소 및 포트입니다.
애플리케이션이 dispatcherexample-1.0.0 이라고 가정하면 다음에서 JSP 뷰에 액세스 할 수 있습니다.
http://localhost:8080/dispatcherexample-1.0.0/jsp/
Maven을 사용하는 일반 Spring 프로젝트에서 이러한 뷰의 경로는 다음과 같습니다.
src -|
main -|
java
resources
webapp -|
jsp
WEB-INF
보기의 기본 위치는 WEB-INF 내에 있습니다. 위의 스 니펫에서 InternalViewResolver 에 대해 지정된 경로 는 뷰를 사용할 수있는 'src / main / webapp'의 하위 디렉토리를 결정합니다.
3.4. LocaleResolver의 인터페이스
디스패처에 대한 세션, 요청 또는 쿠키 정보를 사용자 정의하는 기본 방법은 LocaleResolver 인터페이스를 사용하는 것 입니다.
CookieLocaleResolver 는 쿠키를 사용하여 상태 비 저장 애플리케이션 속성의 구성을 허용하는 구현입니다. AppConfig에 추가해 보겠습니다 .
@Bean
public CookieLocaleResolver cookieLocaleResolverExample() {
CookieLocaleResolver localeResolver
= new CookieLocaleResolver();
localeResolver.setDefaultLocale(Locale.ENGLISH);
localeResolver.setCookieName("locale-cookie-resolver-example");
localeResolver.setCookieMaxAge(3600);
return localeResolver;
}
@Bean
public LocaleResolver sessionLocaleResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.US);
localResolver.setDefaultTimeZone(TimeZone.getTimeZone("UTC"));
return localeResolver;
}
SessionLocaleResolver 는 상태 저장 애플리케이션에서 세션 별 구성을 허용합니다.
setDefaultLocale 반면 () 메소드는, 지리적, 정치적, 또는 문화적 영역을 나타내는 setDefaultTimeZone은 ( ) 관련 결정 시간대의 응용 프로그램에 대한 객체 Bean 문제를.
위의 LocaleResolver 구현 각각에서 두 메서드를 모두 사용할 수 있습니다 .
3.5. ThemeResolver 인터페이스
Spring은 뷰에 대한 스타일 테마를 제공합니다.
테마를 처리하도록 디스패처를 구성하는 방법을 살펴 보겠습니다.
먼저 정적 테마 파일을 찾아 사용하는 데 필요한 모든 구성을 설정해 보겠습니다 . 실제 테마 자체 를 구성하려면 ThemeSource 에 대한 정적 리소스 위치를 설정해야 합니다 ( 테마 개체에는 해당 파일에 규정 된 모든 구성 정보가 포함됨 ). 이것을 AppConfig에 추가하십시오 .
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/", "/resources/")
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new PathResourceResolver());
}
@Bean
public ResourceBundleThemeSource themeSource() {
ResourceBundleThemeSource themeSource
= new ResourceBundleThemeSource();
themeSource.setDefaultEncoding("UTF-8");
themeSource.setBasenamePrefix("themes.");
return themeSource;
}
DispatcherServlet에서 관리하는 요청 은 ThemeChangeInterceptor 객체 에서 사용할 수있는 setParamName ()에 전달 된 지정된 매개 변수를 통해 테마를 수정할 수 있습니다 . AppConfig에 추가 :
@Bean
public CookieThemeResolver themeResolver() {
CookieThemeResolver resolver = new CookieThemeResolver();
resolver.setDefaultThemeName("example");
resolver.setCookieName("example-theme-cookie");
return resolver;
}
@Bean
public ThemeChangeInterceptor themeChangeInterceptor() {
ThemeChangeInterceptor interceptor
= new ThemeChangeInterceptor();
interceptor.setParamName("theme");
return interceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(themeChangeInterceptor());
}
다음 JSP 태그가 뷰에 추가되어 올바른 스타일이 표시됩니다.
<link rel="stylesheet" href="${ctx}/<spring:theme code='styleSheet'/>" type="text/css"/>
다음 URL 요청은 구성된 ThemeChangeIntercepter에 전달 된 'theme'매개 변수를 사용하여 예제 테마를 렌더링합니다 .
http://localhost:8080/dispatcherexample-1.0.0/?theme=example
3.6. MultipartResolver 인터페이스
MultipartResolver의 구현은 멀티 파트에 대한 요청을 검사하고, 그들을 감싸는 MultipartHttpServletRequest를 상기 적어도 하나 개의 멀티 찾으면 과정에서 다른 요소들에 의해 추가적으로 처리. AppConfig에 추가 :
@Bean
public CommonsMultipartResolver multipartResolver()
throws IOException {
CommonsMultipartResolver resolver
= new CommonsMultipartResolver();
resolver.setMaxUploadSize(10000000);
return resolver;
}
이제 MultipartResolver 빈을 구성 했으므로 MultipartFile 요청 을 처리 할 컨트롤러를 설정하겠습니다 .
@Controller
public class MultipartController {
@Autowired
ServletContext context;
@PostMapping("/upload")
public ModelAndView FileuploadController(
@RequestParam("file") MultipartFile file)
throws IOException {
ModelAndView modelAndView = new ModelAndView("index");
InputStream in = file.getInputStream();
String path = new File(".").getAbsolutePath();
FileOutputStream f = new FileOutputStream(
path.substring(0, path.length()-1)
+ "/uploads/" + file.getOriginalFilename());
int ch;
while ((ch = in.read()) != -1) {
f.write(ch);
}
f.flush();
f.close();
in.close();
modelAndView.getModel()
.put("message", "File uploaded successfully!");
return modelAndView;
}
}
일반 형식을 사용하여 지정된 엔드 포인트에 파일을 제출할 수 있습니다. 업로드 된 파일은 'CATALINA_HOME / bin / uploads'에서 사용할 수 있습니다.
3.7. HandlerExceptionResolver 인터페이스
Spring의 HandlerExceptionResolver 는 전체 웹 애플리케이션, 단일 컨트롤러 또는 컨트롤러 세트에 대해 균일 한 오류 처리를 제공합니다.
응용 프로그램 전체의 사용자 지정 예외 처리를 제공하려면 @ControllerAdvice 어노테이션이 달린 클래스를 만듭니다 .
@ControllerAdvice
public class ExampleGlobalExceptionHandler {
@ExceptionHandler
@ResponseBody
public String handleExampleException(Exception e) {
// ...
}
}
@ExceptionHandler로 어노테이션이 달린 해당 클래스 내의 모든 메서드 는 디스패처의 책임 영역 내의 모든 컨트롤러에서 사용할 수 있습니다.
DispatcherServlet의 ApplicationContext 에있는 HandlerExceptionResolver 인터페이스의 구현은 @ExceptionHandler 가 어노테이션으로 사용되고 올바른 클래스가 매개 변수로 전달 될 때마다 해당 디스패처의 책임 영역에서 특정 컨트롤러 를 가로 챌 수 있습니다 .
@Controller
public class FooController{
@ExceptionHandler({ CustomException1.class, CustomException2.class })
public void handleException() {
// ...
}
// ...
}
이제 handleException () 메서드는 예외 CustomException1 또는 CustomException2 가 발생하는 경우 위의 예제에서 FooController 에 대한 예외 처리기 역할을 합니다.
다음 은 Spring 웹 애플리케이션에서 예외 처리에 대해 자세히 설명하는 기사입니다.
4. 결론
이 예제에서는 Spring의 DispatcherServlet 과이를 구성하는 몇 가지 방법을 검토 했습니다.
- https://docs.spring.io/spring-framework/docs/current/reference/html
- https://www.baeldung.com/spring-dispatcherservlet
'Java' 카테고리의 다른 글
Spring에서 속성 파일 다시로드 (0) | 2021.04.20 |
---|---|
Spring Boot : Jackson ObjectMapper 사용자 지정 (0) | 2021.04.20 |
Spring MVC의 ViewResolver 사용방법(예제) (0) | 2021.04.20 |
Spring Handler 매핑 사용방법(예제) (0) | 2021.04.20 |
Spring MVC 콘텐츠 협상 (0) | 2021.04.19 |