springMVC实现首页的重定向(<mvc:view-controller>以及<mvc:annotation-driven/>标签使用)

来源:互联网 发布:淘宝上传宝贝图片大小 编辑:程序博客网 时间:2024/05/21 22:07

一、背景

由于web首页中的数据也需要从后台获取,因此需要走controller。环境myeclipse2014、gradle2.13、win7、tomcat7.0.30


二、实现方式

1. 采用controller方式

对路径“/”进行映射

@RequestMapping("/")public String indexPage() throws Exception {return "index";     或者为 return "redirect:/index"   重定向到index map中}

如果重定向到“/index”,则需要在程序中配置

@RequestMapping("/index")public String index() throws Exception {return "index";}

或者一步到位,对"/"和“/index”都进行配置

@RequestMapping({ "/", "/index" })public String index() throws Exception {return "index";}

2.使用mvc:view-controller标签

在springMVC servlet配置文件配置如下:

<mvc:view-controller path="/" view-name="redirect:/index" />

"/"是访问的path,"/index"是重定向后的path

该标签的解释:

This tag is a shorcut for defining a ParameterizableViewController that immediately forwards to a view when invoked. 
这个标签是为了简化ParameterizableViewController映射到视图的配置

Use it in static cases when there is no Java Controller logic to execute before the view generates the response. 
当响应视图是不需要执行控制器逻辑时使用

An example of view-controller that forwards to a home page is shown below: 
一个跳转到主页的配置例子

<mvc:view-controller path="/" view-name="home"/>

两种用法 
1)、重定向 
<mvc:view-controller path="/" view-name="redirect:/admin/index"/> 
即如果当前路径是/ 则重定向到/admin/index 
2)、view name 
<mvc:view-controller path="/" view-name=admin/index"/> 
如果当前路径是/ 则交给相应的视图解析器直接解析为视图 

三、遇到的问题

1.如果按照以上的配置失败了,请检查你的配置文件中最上方是否配置了相应的命名空间

 xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="       http://www.springframework.org/schema/mvc       http://www.springframework.org/schema/mvc/spring-mvc.xsd"

2.配置成功之后,你可能会发现你访问其他的页面会失败

原因:如果没有<mvc:annotation-driven/>,那么所有的@Controller注解可能就没有解析,所有当有请求时候都没有匹配的处理请求类,就都去<mvc:default-servlet-handler/>即default servlet处理了。

在springmvc配置文件中加上<mvc:annotation-driven/>即可(使用注解方式设置的springMVC需要加上此设置)

该标签的作用:

This tag registers the DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter beans that are required for Spring MVC to dispatch requests to Controllers. 
这个标签注册了Spring MVC分发请求到控制器所必须的DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter实例,已经被RequestMappingHandlerMapping替代。

3.发现重定向没有成功

删除webapp下的index.jsp(可以不用删除,只要做了相关映射及视图配置)


将web.xml中的如下信息删除(可以不用删除,只要做了相关映射及视图配置)

<welcome-file-list>    <welcome-file>index.html</welcome-file>    <welcome-file>index.htm</welcome-file>    <welcome-file>index.jsp</welcome-file>    <welcome-file>default.html</welcome-file>    <welcome-file>default.htm</welcome-file>    <welcome-file>default.jsp</welcome-file></welcome-file-list>
将index放到springmvc配置的目录下

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!-- <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> --><!-- 前缀 --><property name="prefix" value="/WEB-INF/views/jsp/" /><!-- 后缀 --><property name="suffix" value=".jsp" /></bean>


四、顺便附上解析<mvc:annotation-driven/>及<view-controller>自定义标签的源码

根据spring配置文件的解析原则,可参见Spring实战篇系列----Spring配置文件的解析由springMVC中的META-INF/spring.handlers可知该自定义标签是在MvcNamespaceHandler中注册的

spring.handlers

http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler

MvcNamespaceHandler.java

/* * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.web.servlet.config;import org.springframework.beans.factory.xml.NamespaceHandler;import org.springframework.beans.factory.xml.NamespaceHandlerSupport;/** * {@link NamespaceHandler} for Spring MVC configuration namespace. * * @author Keith Donald * @author Jeremy Grelle * @author Sebastien Deleuze * @since 3.0 */public class MvcNamespaceHandler extends NamespaceHandlerSupport {@Overridepublic void init() {registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());registerBeanDefinitionParser("velocity-configurer", new VelocityConfigurerBeanDefinitionParser());registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());}}

1)<mvc:annotation-driven/>自定义标签的解析器为AnnotationDrivenBeanDefinitionParser,其中的parse函数为

@Overridepublic BeanDefinition parse(Element element, ParserContext parserContext) {Object source = parserContext.extractSource(element);XmlReaderContext readerContext = parserContext.getReaderContext();CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);parserContext.pushContainingComponent(compDefinition);RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, parserContext);RootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);handlerMappingDef.setSource(source);handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);handlerMappingDef.getPropertyValues().add("order", 0);handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);if (element.hasAttribute("enable-matrix-variables")) {Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enable-matrix-variables"));handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);}else if (element.hasAttribute("enableMatrixVariables")) {Boolean enableMatrixVariables = Boolean.valueOf(element.getAttribute("enableMatrixVariables"));handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);}configurePathMatchingProperties(handlerMappingDef, element, parserContext);readerContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME , handlerMappingDef);RuntimeBeanReference corsConfigurationsRef = MvcNamespaceUtils.registerCorsConfigurations(null, parserContext, source);handlerMappingDef.getPropertyValues().add("corsConfigurations", corsConfigurationsRef);RuntimeBeanReference conversionService = getConversionService(element, source, parserContext);RuntimeBeanReference validator = getValidator(element, source, parserContext);RuntimeBeanReference messageCodesResolver = getMessageCodesResolver(element);RootBeanDefinition bindingDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);bindingDef.setSource(source);bindingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);bindingDef.getPropertyValues().add("conversionService", conversionService);bindingDef.getPropertyValues().add("validator", validator);bindingDef.getPropertyValues().add("messageCodesResolver", messageCodesResolver);ManagedList<?> messageConverters = getMessageConverters(element, source, parserContext);ManagedList<?> argumentResolvers = getArgumentResolvers(element, parserContext);ManagedList<?> returnValueHandlers = getReturnValueHandlers(element, parserContext);String asyncTimeout = getAsyncTimeout(element);RuntimeBeanReference asyncExecutor = getAsyncExecutor(element);ManagedList<?> callableInterceptors = getCallableInterceptors(element, source, parserContext);ManagedList<?> deferredResultInterceptors = getDeferredResultInterceptors(element, source, parserContext);RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);handlerAdapterDef.setSource(source);handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);addRequestBodyAdvice(handlerAdapterDef);addResponseBodyAdvice(handlerAdapterDef);if (element.hasAttribute("ignore-default-model-on-redirect")) {Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignore-default-model-on-redirect"));handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);}else if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {// "ignoreDefaultModelOnRedirect" spelling is deprecatedBoolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignoreDefaultModelOnRedirect"));handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);}if (argumentResolvers != null) {handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);}if (returnValueHandlers != null) {handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);}if (asyncTimeout != null) {handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout);}if (asyncExecutor != null) {handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);}handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);readerContext.getRegistry().registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME , handlerAdapterDef);String uriCompContribName = MvcUriComponentsBuilder.MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME;RootBeanDefinition uriCompContribDef = new RootBeanDefinition(CompositeUriComponentsContributorFactoryBean.class);uriCompContribDef.setSource(source);uriCompContribDef.getPropertyValues().addPropertyValue("handlerAdapter", handlerAdapterDef);uriCompContribDef.getPropertyValues().addPropertyValue("conversionService", conversionService);readerContext.getRegistry().registerBeanDefinition(uriCompContribName, uriCompContribDef);RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);csInterceptorDef.setSource(source);csInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, conversionService);RootBeanDefinition mappedCsInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);mappedCsInterceptorDef.setSource(source);mappedCsInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, csInterceptorDef);String mappedInterceptorName = readerContext.registerWithGeneratedName(mappedCsInterceptorDef);RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);exceptionHandlerExceptionResolver.setSource(source);exceptionHandlerExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);exceptionHandlerExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);exceptionHandlerExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0);addResponseBodyAdvice(exceptionHandlerExceptionResolver);if (argumentResolvers != null) {exceptionHandlerExceptionResolver.getPropertyValues().add("customArgumentResolvers", argumentResolvers);}if (returnValueHandlers != null) {exceptionHandlerExceptionResolver.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);}String methodExceptionResolverName = readerContext.registerWithGeneratedName(exceptionHandlerExceptionResolver);RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);responseStatusExceptionResolver.setSource(source);responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);responseStatusExceptionResolver.getPropertyValues().add("order", 1);String responseStatusExceptionResolverName =readerContext.registerWithGeneratedName(responseStatusExceptionResolver);RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);defaultExceptionResolver.setSource(source);defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);defaultExceptionResolver.getPropertyValues().add("order", 2);String defaultExceptionResolverName =readerContext.registerWithGeneratedName(defaultExceptionResolver);parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));parserContext.registerComponent(new BeanComponentDefinition(uriCompContribDef, uriCompContribName));parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"MvcNamespaceUtils.registerDefaultComponents(parserContext, source);parserContext.popAndRegisterContainingComponent();return null;}

可知解析器注册了多个bean,RequestMappingHandlerMappingBeanNameUrlHandlerMapping、RequestMappingHandlerAdapter、HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、ExceptionHandlerExceptionResolverResponseStatusExceptionResolverDefaultHandlerExceptionResolver  前两个是HandlerMapping接口的实现类,用来处理请求映射的。其中第一个是处理@RequestMapping注解的。第二个会将controller类的名字映射为请求url。中间三个是用来处理请求的。具体点说就是确定调用哪个controller的哪个方法来处理当前请求。第一个处理@Controller注解的处理器,支持自定义方法参数和返回值(很酷)。第二个是处理继承HttpRequestHandler的处理器。第三个处理继承自Controller接口的处理器。后面三个是用来处理异常的解析器。<context:component-scan/>标签是告诉Spring 来扫描指定包下的类,并注册被@Component,@Controller,@Service,@Repository等注解标记的组件。 而<mvc:annotation-driven/>是告知Spring,我们启用注解驱动。然后Spring会自动为我们注册上面说到的几个Bean到工厂中,来处理我们的请求。


2)自定义标签<view-controller>、<redirect-view-controller>,<status-controller>的解析器ViewControllerBeanDefinitionParser.java
public BeanDefinition parse(Element element, ParserContext parserContext) {Object source = parserContext.extractSource(element);// Register SimpleUrlHandlerMapping for view controllersBeanDefinition hm = registerHandlerMapping(parserContext, source);// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"MvcNamespaceUtils.registerDefaultComponents(parserContext, source);// Create view controller bean definitionRootBeanDefinition controller = new RootBeanDefinition(ParameterizableViewController.class);controller.setSource(source);HttpStatus statusCode = null;if (element.hasAttribute("status-code")) {int statusValue = Integer.valueOf(element.getAttribute("status-code"));statusCode = HttpStatus.valueOf(statusValue);}String name = element.getLocalName();if (name.equals("view-controller")) {if (element.hasAttribute("view-name")) {controller.getPropertyValues().add("viewName", element.getAttribute("view-name"));}if (statusCode != null) {controller.getPropertyValues().add("statusCode", statusCode);}}else if (name.equals("redirect-view-controller")) {controller.getPropertyValues().add("view", getRedirectView(element, statusCode, source));}else if (name.equals("status-controller")) {controller.getPropertyValues().add("statusCode", statusCode);controller.getPropertyValues().add("statusOnly", true);}else {// Should never happen...throw new IllegalStateException("Unexpected tag name: " + name);}Map<String, BeanDefinition> urlMap;if (hm.getPropertyValues().contains("urlMap")) {urlMap = (Map<String, BeanDefinition>) hm.getPropertyValues().getPropertyValue("urlMap").getValue();}else {urlMap = new ManagedMap<String, BeanDefinition>();hm.getPropertyValues().add("urlMap", urlMap);}urlMap.put(element.getAttribute("path"), controller);return null;}

private BeanDefinition registerHandlerMapping(ParserContext context, Object source) {if (context.getRegistry().containsBeanDefinition(HANDLER_MAPPING_BEAN_NAME)) {return context.getRegistry().getBeanDefinition(HANDLER_MAPPING_BEAN_NAME);}RootBeanDefinition beanDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);beanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);context.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME, beanDef);context.registerComponent(new BeanComponentDefinition(beanDef, HANDLER_MAPPING_BEAN_NAME));beanDef.setSource(source);beanDef.getPropertyValues().add("order", "1");beanDef.getPropertyValues().add("pathMatcher", MvcNamespaceUtils.registerPathMatcher(null, context, source));beanDef.getPropertyValues().add("urlPathHelper", MvcNamespaceUtils.registerUrlPathHelper(null, context, source));RuntimeBeanReference corsConfigurationsRef = MvcNamespaceUtils.registerCorsConfigurations(null, context, source);beanDef.getPropertyValues().add("corsConfigurations", corsConfigurationsRef);return beanDef;}private RootBeanDefinition getRedirectView(Element element, HttpStatus status, Object source) {RootBeanDefinition redirectView = new RootBeanDefinition(RedirectView.class);redirectView.setSource(source);redirectView.getConstructorArgumentValues().addIndexedArgumentValue(0, element.getAttribute("redirect-url"));if (status != null) {redirectView.getPropertyValues().add("statusCode", status);}if (element.hasAttribute("context-relative")) {redirectView.getPropertyValues().add("contextRelative", element.getAttribute("context-relative"));}else {redirectView.getPropertyValues().add("contextRelative", true);}if (element.hasAttribute("keep-query-params")) {redirectView.getPropertyValues().add("propagateQueryParams", element.getAttribute("keep-query-params"));}return redirectView;}





2 0
原创粉丝点击