前言
viewControllerHandlerMapping可以提供访问url和实际url的映射。
一、viewControllerHandlerMapping
WebMvcConfigurationSupport.java
@Bean
public HandlerMapping viewControllerHandlerMapping(
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
ViewControllerRegistry registry = new ViewControllerRegistry(this.applicationContext);
//注册ViewController和viewName
addViewControllers(registry);
//创建SimpleUrlHandlerMapping
AbstractHandlerMapping handlerMapping = registry.buildHandlerMapping();
if (handlerMapping == null) {
return null;
}
PathMatchConfigurer pathConfig = getPathMatchConfigurer();
if (pathConfig.getPatternParser() != null) {
handlerMapping.setPatternParser(pathConfig.getPatternParser());
}
else {
handlerMapping.setUrlPathHelper(pathConfig.getUrlPathHelperOrDefault());
handlerMapping.setPathMatcher(pathConfig.getPathMatcherOrDefault());
}
//拦截器
handlerMapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
//跨域
handlerMapping.setCorsConfigurations(getCorsConfigurations());
return handlerMapping;
}
2、addViewControllers( )
从实现WebMvcConfigurer 接口的类中回调addViewControllers( )方法
protected void addViewControllers(ViewControllerRegistry registry) {
this.configurers.addViewControllers(registry);
}
public void addViewControllers(ViewControllerRegistry registry) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.addViewControllers(registry);
}
}
3、buildHandlerMapping( )
protected SimpleUrlHandlerMapping buildHandlerMapping() {
if (this.registrations.isEmpty() && this.redirectRegistrations.isEmpty()) {
return null;
}
//将urlPath和ViewController存入map,其中ViewController是ParameterizableViewController类型
Map<String, Object> urlMap = new LinkedHashMap<>();
for (ViewControllerRegistration registration : this.registrations) {
urlMap.put(registration.getUrlPath(), registration.getViewController());
}
for (RedirectViewControllerRegistration registration : this.redirectRegistrations) {
urlMap.put(registration.getUrlPath(), registration.getViewController());
}
//构建SimpleUrlHandlerMapping
return new SimpleUrlHandlerMapping(urlMap, this.order);
}
二、SimpleControllerHandlerAdapter
1、handle( )
SimpleControllerHandlerAdapter.java
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return ((Controller) handler).handleRequest(request, response);
}
2、handleRequest( )
AbstractController.java
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws Exception {
if (HttpMethod.OPTIONS.matches(request.getMethod())) {
response.setHeader("Allow", getAllowHeader());
return null;
}
// Delegate to WebContentGenerator for checking and preparing.
checkRequest(request);
prepareResponse(response);
// Execute handleRequestInternal in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
return handleRequestInternal(request, response);
}
}
}
//调用子类的handleRequestInternal,handler的实际类型是ParameterizableViewController
return handleRequestInternal(request, response);
}
3、handleRequestInternal( )
ParameterizableViewController.java
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
//获取viewName
String viewName = getViewName();
if (getStatusCode() != null) {
if (getStatusCode().is3xxRedirection()) {
request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, getStatusCode());
}
else {
response.setStatus(getStatusCode().value());
if (getStatusCode().equals(HttpStatus.NO_CONTENT) && viewName == null) {
return null;
}
}
}
if (isStatusOnly()) {
return null;
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addAllObjects(RequestContextUtils.getInputFlashMap(request));
if (viewName != null) {
modelAndView.setViewName(viewName);
}
else {
modelAndView.setView(getView());
}
return modelAndView;
}
三、示例
@Configuration
public class ViewControllerConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/swagger-ui/")
.setViewName("forward:/swagger-ui/index.html");
}
在访问/swagger-ui/路径时会跳转到/swagger-ui/index.html的路径。
总结
通过addViewControllers注册ViewControllers和ViewName。