学习由springMVC自带的开源项目jpetstore---学习笔记一之spring-mvc.xml配置文件解析

在写这篇博客之前我先大致介绍一下在ssm框架中web.xml、spring-mvc.xml、applicationContext.xml配置文件所充当的角色,如有不到位的地方欢迎批评指正。
1.web.xml配置文件是每个web项目中必须存在的配置文件,在服务器开启时,服务器容器就会加载解析这个配置文件,并且将配置信息转换成键值对的形式,交给创建的ServletContext对象,以供整个项目程序使用,web.xml配置文件可以说是整个web项目的入口,所以在ssm框架项目中一般会在web.xml文件中配置:前端控制器DispatcherServlet、编码处理CharacterEncodingFilter、上下文监听器、jsp文件属性设置、错误处理、spring配置文件加载属性等
2.spring-MVC.xml配置文件:其实springMVC是spring的一个模块,理论上是可以把springMVC中的配置信息和application.xml中的配置信息放在同一个配置文件中的,但是为了体现程序的模块化、增强项目的可维护性等,一般会将springMVC的配置信息和spring的配置信息放在两个不同的xml 文件中。在spring-mvc.xml配置文件中会比较偏向于前台的请求映射、后台对前台的响应跳转等,所以在spring-mvc.xml配置文件中配置信息大致包括:前端控制器InternalResourceViewResolver、将controller层的的类交给spring容器管理、前台请求URL和后台controller的映射配置等。
3.applicationContext.xml配置文件(spring的配置文件):application单词的意思是应用,我们从单词的意思上就可以看出applicationContext.xml配置文件更加偏向于程序资源的配置而不再关注于请求和响应。所以说在applicationContext.xml配置文件中一般会存在的配置信息有:数据源的配置、除controller层类的其他所有类资源、和mybatis的整合配置、事务管理的配置等。
下面就来解析一下开源项目jpetstore的spring-mvc.xml配置文件:
1.InternalResourceViewResolver(视图解析器)的配置以及作用:
原配置文件:

<bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
        <property name="order" value="2" />
    </bean>

大体来说视图解析器是接受来自controller层对前台的响应信息,并且对这些信息进行解析,最终向前台返回一个视图。InternalResourceViewResolver会把返回的视图名称都解析为InternalResourceView对象,InternalResourceView会把Controller处理器方法返回的模型属性都存放到对应的request属性中,然后通过RequestDispatcher在服务器端把请求forword重定向到目标URL。比如在InternalResourceViewResolver中定义了prefix=/WEB-INF/views,suffix=.jsp,然后请求的Controller处理器方法返回的视图名称为test,那么这个时候InternalResourceViewResolver就会把test解析为一个InternalResourceView对象,先把返回的模型属性都存放到对应的HttpServletRequest属性中,然后利用RequestDispatcher在服务器端把请求forword到/WEB-INF/views/test.jsp。我们可以查看源码会发现这样两个方法:

@Override
    protected View createView(String viewName, Locale locale) throws Exception {
        // If this resolver is not supposed to handle the given view,
        // return null to pass on to the next resolver in the chain.
        if (!canHandle(viewName, locale)) {
            return null;
        }
        // Check for special "redirect:" prefix.
        if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
            String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
            RedirectView view = new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());
            return applyLifecycleMethods(viewName, view);
        }
        // Check for special "forward:" prefix.
        if (viewName.startsWith(FORWARD_URL_PREFIX)) {
            String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
            return new InternalResourceView(forwardUrl);
        }
        // Else fall back to superclass implementation: calling loadView.
        return super.createView(viewName, locale);
    }
@Override
    protected void renderMergedOutputModel(
            Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

        // Determine which request handle to expose to the RequestDispatcher.
        HttpServletRequest requestToExpose = getRequestToExpose(request);

        // Expose the model object as request attributes.
        exposeModelAsRequestAttributes(model, requestToExpose);

        // Expose helpers as request attributes, if any.
        exposeHelpers(requestToExpose);

        // Determine the path for the request dispatcher.
        String dispatcherPath = prepareForRendering(requestToExpose, response);

        // Obtain a RequestDispatcher for the target resource (typically a JSP).
        RequestDispatcher rd = getRequestDispatcher(requestToExpose, dispatcherPath);
        if (rd == null) {
            throw new ServletException("Could not get RequestDispatcher for [" + getUrl() +
                    "]: Check that the corresponding file exists within your web application archive!");
        }

        // If already included or response already committed, perform include, else forward.
        if (useInclude(requestToExpose, response)) {
            response.setContentType(getContentType());
            if (logger.isDebugEnabled()) {
                logger.debug("Including resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
            }
            rd.include(requestToExpose, response);
        }

        else {
            // Note: The forwarded resource is supposed to determine the content type itself.
            exposeForwardRequestAttributes(requestToExpose);
            if (logger.isDebugEnabled()) {
                logger.debug("Forwarding to resource [" + getUrl() + "] in InternalResourceView '" + getBeanName() + "'");
            }
            rd.forward(requestToExpose, response);
        }
    }

从这些源码中我们就可以看出,在InternalResourceViewResolver将controller层返回的响应信息进一步解析封装后会运用服务器端跳转的方式向前台返回视图。
这就是InternalResourceViewResolver一个非常重要的特性,我们都知道存放在/WEB-INF/下面的内容是不能直接通过request请求的方式请求到的,为了安全性考虑,我们通常会把jsp文件放在WEB-INF目录下,而InternalResourceView在服务器端跳转的方式可以很好的解决这个问题。
2. <context:component-scan base-package="包名" />标签的配置和作用:
该标签主要用于自动扫描base-package报名下的所有类,将其交给spring容器进行管理。
3.<mvc:annotation-driven></mvc:annotation-driven>标签的配置和作用:
<mvc:annotation-driven></mvc:annotation-driven>会自动注册RequestMappingHandlerMapping与RequestMappingHandlerAdapter两个Bean,这是Spring MVC为@Controller分发请求所必需的,并且提供了数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持读写XML的支持(JAXB)和读写JSON的支持(默认Jackson)等功能。也就是说配置这个标签以后spring会给我自动的配置一些必须的Bean.这些Bean就包括运用注解requestMapping进行和controller层映射必须的Bean。
4.<mvc:default-servlet-handler /> 标签的配置和作用:
由于在web.xml 配置文件中我们配置的是拦截所有请求,也就是/*,这就会导致静态资源也被拦截,所以在springMVC.xml中配置<mvc:default-servlet-handler />后,会在Spring MVC上下文中定义一个org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler,它会像一个检查员,对进入DispatcherServlet的URL进行筛查,如果发现是静态资源的请求,就将该请求转由Web应用服务器默认的Servlet处理,如果不是静态资源的请求,才由DispatcherServlet继续处理。
5.<mvc:resources/> 标签的配置和使用:
该标签也是用于处理静态资源的,这里有一篇博客主要写了该标签和<mvc:default-servlet-handler /> 的作用和区别:https://blog.csdn.net/xiao______xin/article/details/54093355
6.如下原配置文件配置代码片的作用解析:

<bean
        class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="order" value="1" />
        <property name="exceptionMappings">
            <util:map>
                <entry key="ResourceNotFoundException" value="notFoundError" />
            </util:map>
        </property>
        <property name="statusCodes">
            <util:map>
                <entry key="notFoundError" value="404" />
            </util:map>
        </property>
        <property name="defaultStatusCode" value="500" />
        <property name="defaultErrorView" value="systemError" />
        <property name="warnLogCategory"
            value="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" />
    </bean>

SimpleMappingExceptionResolver只能简单的处理异常当发生异常的时候,根据发生的异常类型跳转到指定的页面来显示异常信息。这里我们可以和web.xml中的 <error-page></error-page> 标签做比较,这两个标签都是用来处理异常的标签,但是<error-page></error-page>标签只能处理在前端请求过程中发生的错误,并且不能打印错误信息,SimpleMappingExceptionResolver可以处理服务器中发生的异常,并且能在处理页面打印异常信息,也就是说SimpleMappingExceptionResolver其实更加专注于异常处理。

猜你喜欢

转载自blog.csdn.net/qq_40400960/article/details/80051902