SpringMVC静态资源处理

来源:互联网 发布:如何用java做网站 编辑:程序博客网 时间:2024/04/30 01:21
       在SpringMVC中,如果将 DispatcherServlet 请求映射配置为 /,则 Spring MVC 将捕 获 WEB 容器的所有请求,包括静态资源的请求, SpringMVC 会将他 们当成一个普通请求处理,因找不到对应处理器将导致错误。 
       可以在 SpringMVC 的配置文件中配置 <mvc:default-servlet-handler/> 的方式解决静态资源的问题: 
        <mvc:default-servlet-handler/> 将在 SpringMVC 上下文中注册一个SimpleUrlHandlerMapping,以及注册一个
DefaultServletHttpRequestHandler,它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由 WEB 应用服务器默认的 Servlet 处理,如果不是静态资源的请求,才由DispatcherServlet 继续处理。
        一般 WEB 应用服务器默认的 Servlet 的名称都是 default。若所使用的 WEB 服务器的默认 Servlet 名称不是 default,则需要通过 default-servlet-name 属性显式指定。

1)、  <mvc:default-servlet-handler/>标签处理
     <mvc:default-servlet-handler/>标签是MVC模块自定义标签,当Ioc容器解析BeanDefinition遇到<mvc:default-servlet-handler/>这个标签,将使用自定义标签解析机制处理这些标签。MvcNamespaceHandler类用于加载与Spring MVC模块相关的自定义标签解析器:
public class MvcNamespaceHandler extends NamespaceHandlerSupport {@Overridepublic void init() {      registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());  //这里注册<mvc:default-servlet-handlerv>标签解析器,该标签主要用与处理静态资源registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());    //这里注册<mvc:interceptors>标签解析器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());}}


在注册的DefaultServletHandlerBeanDefinitionParser类中主要的方法是parse方法:
class DefaultServletHandlerBeanDefinitionParser implements BeanDefinitionParser {@Overridepublic BeanDefinition parse(Element element, ParserContext parserContext) {      Object source = parserContext.extractSource(element);//获取指定的默认 Servlet 名称String defaultServletName = element.getAttribute("default-servlet-name");//这里定义DefaultServletHttpRequestHandler BeanDefinition,之后将注册这个BeanDefinition到应用上下文RootBeanDefinition defaultServletHandlerDef = new RootBeanDefinition(DefaultServletHttpRequestHandler.class);defaultServletHandlerDef.setSource(source);defaultServletHandlerDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);      if (StringUtils.hasText(defaultServletName)) {         defaultServletHandlerDef.getPropertyValues().add("defaultServletName", defaultServletName);}      String defaultServletHandlerName = parserContext.getReaderContext().generateBeanName(defaultServletHandlerDef);parserContext.getRegistry().registerBeanDefinition(defaultServletHandlerName, defaultServletHandlerDef);parserContext.registerComponent(new BeanComponentDefinition(defaultServletHandlerDef, defaultServletHandlerName));     //这里构建一个urlMap 以便于SimpleUrlHandlerMapping使用,完成请求到Handler的映射Map<String, String> urlMap = new ManagedMap<String, String>();urlMap.put("/**", defaultServletHandlerName);     //这里定义SimpleUrlHandlerMapping BeanDefinition,之后将注册这个BeanDefinition到应用上下文,用于将请求匹配"/**"静态资源的路径映射到DefaultServletHttpRequestHandler,使用默认的Servlet进行处理 RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);handlerMappingDef.setSource(source);handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);handlerMappingDef.getPropertyValues().add("urlMap", urlMap);String handlerMappingBeanName = parserContext.getReaderContext().generateBeanName(handlerMappingDef);parserContext.getRegistry().registerBeanDefinition(handlerMappingBeanName, handlerMappingDef);parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, handlerMappingBeanName));// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"MvcNamespaceUtils.registerDefaultComponents(parserContext, source);      return null;}}

2)、DefaultServletHttpRequestHandler
DefaultServletHttpRequestHandler实现HttpRequestHandler接口,重写handleRequest()方法实现请求处理:
public class DefaultServletHttpRequestHandler implements HttpRequestHandler, ServletContextAware {/** Default Servlet name used by Tomcat, Jetty, JBoss, and GlassFish */private static final String COMMON_DEFAULT_SERVLET_NAME = "default";/** Default Servlet name used by Google App Engine */private static final String GAE_DEFAULT_SERVLET_NAME = "_ah_default";/** Default Servlet name used by Resin */private static final String RESIN_DEFAULT_SERVLET_NAME = "resin-file";/** Default Servlet name used by WebLogic */private static final String WEBLOGIC_DEFAULT_SERVLET_NAME = "FileServlet";/** Default Servlet name used by WebSphere */private static final String WEBSPHERE_DEFAULT_SERVLET_NAME = "SimpleFileServlet";@Overridepublic void handleRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {   //通过servletContext获取默认Servlet的请求转发器      RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.defaultServletName);      if (rd == null) {throw new IllegalStateException("A RequestDispatcher could not be located for the default servlet '" +this.defaultServletName +"'");}   //将请求转发给默认的Servlet请求,以便处理静态资源等      rd.forward(request, response);}}



0 0
原创粉丝点击