ViewControllerRegistry/ViewControllerRegistration/RedirectViewControllerRegistration是Spring MVC关于URL pattern和视图控制器(view controller)之间映射的注册信息的概念模型类,它们配合使用。
ViewControllerRegistry表示一组URL pattern和视图控制器(view controller)映射关系的注册信息,这一组注册信息中的每一条信息通过一个ViewControllerRegistration或者一个RedirectViewControllerRegistration对象来保存。
一个ViewControllerRegistration表示某一个URL pattern和视图控制器(view controller)之间映射的注册信息,能处理如下两种情况 :
- 映射一个
URL pattern到某个HTTP状态字,也就是请求符合该URL pattern时,会返回给浏览器该HTTP状态字,而不写响应体; - 映射一个
URL pattern到指定名称的视图。
一个RedirectViewControllerRegistration表示一个重定向视图控制器。
ViewControllerRegistry的典型用法是被某个WebMvcConfigurer实现类用于快捷配置视图控制器映射,使用例子如下所示 :
/**
* 初始化配置 ViewControllerRegistry registry
*
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// 请求匹配地址 /absent* 时,响应 HTTP代码403给浏览器端
registry.addStatusController("/absent*", HttpStatus.FORBIDDEN);
// 请求匹配地址 /fixed* 时,统一使用视图 fixed_content 进行渲染,
// 适合不需要Web控制器业务逻辑,只需要基于数据模型直接渲染一个页面视图模板的情况
registry.addViewController("/fixed*").setViewName("fixed_content");
// 请求匹配地址 /home* 时,浏览器同意跳转到 /
registry.addRedirectViewController("/home*", "/");
}
在上面的例子中,registry.addStatusController("/absent*", HttpStatus.FORBIDDEN)其实就是使用了ViewControllerRegistration,其具体用法如下 :
// ViewControllerRegistry 源代码片段
/**
* Map a simple controller to the given URL path (or pattern) in order to
* set the response status to the given code without rendering a body.
* @since 4.1
*/
public void addStatusController(String urlPath, HttpStatus statusCode) {
ViewControllerRegistration registration = new ViewControllerRegistration(urlPath);
registration.setApplicationContext(this.applicationContext);
registration.setStatusCode(statusCode);
registration.getViewController().setStatusOnly(true);
this.registrations.add(registration);
}
在上面的例子中,registry.addViewController("/fixed*").setViewName("fixed_content")也使用了ViewControllerRegistration,其具体用法如下 :
// ViewControllerRegistry 源代码片段
/**
* Map a view controller to the given URL path (or pattern) in order to render
* a response with a pre-configured status code and view.
* Patterns like "/admin/**" or "/articles/{articlename:\\w+}"
* are allowed. See org.springframework.util.AntPathMatcher for more details on the
* syntax.
*/
public ViewControllerRegistration addViewController(String urlPath) {
ViewControllerRegistration registration = new ViewControllerRegistration(urlPath);
registration.setApplicationContext(this.applicationContext);
this.registrations.add(registration);
return registration;
}
而registry.addRedirectViewController("/home*", "/")则使用到了RedirectViewControllerRegistration,其具体用法如下 :
// ViewControllerRegistry 源代码片段
/**
* Map a view controller to the given URL path (or pattern) in order to redirect
* to another URL. By default the redirect URL is expected to be relative to
* the current ServletContext, i.e. as relative to the web application root.
* @since 4.1
*/
public RedirectViewControllerRegistration addRedirectViewController(String urlPath,
String redirectUrl) {
RedirectViewControllerRegistration registration =
new RedirectViewControllerRegistration(urlPath, redirectUrl);
registration.setApplicationContext(this.applicationContext);
this.redirectRegistrations.add(registration);
return registration;
}
从上面的代码可以看出,其实一个ViewControllerRegistry对象其实是一组ViewControllerRegistration对象,对应其属性registration,和一组RedirectViewControllerRegistration,对应其属性redirectRegistrations:
// ViewControllerRegistry 源代码片段
// 属性定义
private final List<ViewControllerRegistration> registrations = new ArrayList<>(4);
private final List<RedirectViewControllerRegistration> redirectRegistrations = new ArrayList<>(10);
另外,一个ViewControllerRegistration/RedirectViewControllerRegistration最终都是一个这样的映射 :
<URL pattern, 一个 ParameterizableViewController 对象>
当应用开发人员通过上面的registry.addViewController/registry.addStatusController/registry.addRedirectViewController这种方式配置完视图映射关系之后,这些关系会被ViewControllerRegistration registry对象记录下来。然后在应用启动过程中,Spring MVC配置执行阶段,具体来讲,是bean resourceHandlerMapping实例化过程中,这些信息会被使用,如下代码所示 :
// WebMvcConfigurationSupport 源代码片段
/**
* Return a handler mapping ordered at 1 to map URL paths directly to
* view names. To configure view controllers, override
* #addViewControllers.
*/
@Bean
@Nullable
public HandlerMapping viewControllerHandlerMapping() {
// 创建一个 ViewControllerRegistration registry 对象用于容纳 视图<=>控制器Handler映射 注册信息
ViewControllerRegistry registry = new ViewControllerRegistry(this.applicationContext);
// 调用开发人员对 视图<=>控制器Handler映射 注册信息的定制逻辑
addViewControllers(registry);
// 生成最终使用的 视图<=>控制器Handler映射 HandlerMapping 对象 : handlerMapping
AbstractHandlerMapping handlerMapping = registry.buildHandlerMapping();
if (handlerMapping == null) {
return null;
}
handlerMapping.setPathMatcher(mvcPathMatcher());
handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
handlerMapping.setInterceptors(getInterceptors());
handlerMapping.setCorsConfigurations(getCorsConfigurations());
return handlerMapping;
}
而ViewControllerRegistry的具体实现如下 :
// ViewControllerRegistry 代码片段
/**
* Return the HandlerMapping that contains the registered view
* controller mappings, or null for no registrations.
* @since 4.3.12
*/
@Nullable
protected SimpleUrlHandlerMapping buildHandlerMapping() {
if (this.registrations.isEmpty() && this.redirectRegistrations.isEmpty()) {
return null;
}
Map<String, Object> urlMap = new LinkedHashMap<>();
for (ViewControllerRegistration registration : this.registrations) {
// 形成一条 url pattern <=> ParameterizableViewController 映射关系
// 针对状态字响应或者指定被渲染的视图名称
urlMap.put(registration.getUrlPath(), registration.getViewController());
}
for (RedirectViewControllerRegistration registration : this.redirectRegistrations) {
// 形成一条 url pattern <=> ParameterizableViewController 映射关系
// 针对浏览器端 redirect
urlMap.put(registration.getUrlPath(), registration.getViewController());
}
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
handlerMapping.setUrlMap(urlMap);
handlerMapping.setOrder(this.order);
return handlerMapping;
}

本文详细解析了SpringMVC中ViewControllerRegistry、ViewControllerRegistration及RedirectViewControllerRegistration的概念与用法,阐述了如何通过这些类实现URL模式与视图控制器的映射,包括响应HTTP状态码、渲染特定视图及重定向。
876

被折叠的 条评论
为什么被折叠?



