2014/3/10 SpringMVC中DispatcherServlet理解

一:笔者对于Spring MVC配置文件这块遇到了些问题,之前都是用的别人搭好的环境

感悟一:

1.对于一个Http请求,MVC会寻找DispatcherServlet这个类,所以需要先如下配置,在web.xml中配置DispatcherServlet

web.xml

<servlet>
    <servlet-name>sample</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:conf/spring/sample-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

指定DispatcherServlet,引入sample-servlet.xml配置文件,启动顺序为最优先

2.freemarker解析配置代码

我的<servlet-name>是sample,故在

sample-servlet.xml:

<!-- 针对freemarker的视图配置 -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
		<property name="order" value="1" />
		<property name="cache" value="true" />
		<property name="suffix" value=".ftl" />
		<property name="contentType" value="text/html;charset=UTF-8"></property>
		<property name="requestContextAttribute" value="request" />
		<property name="exposeSpringMacroHelpers" value="true" />
		<property name="exposeRequestAttributes" value="true" />
		<property name="exposeSessionAttributes" value="true" />
	</bean>

	<bean id="freemarkerConfig"
		class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
		<property name="templateLoaderPath" value="/WEB-INF/freemarker/" />
		<property name="defaultEncoding" value="UTF-8" />
		<property name="freemarkerVariables">
			<map>
				<entry key="datetime_format" value="${datetime_format}"></entry>
				<entry key="date_format" value="${date_format}"></entry>
			</map>
		</property>
	</bean>
<property name="order" value="1" />
当有多个viewResolver时候,1表示优先级最大


<property name="suffix" value=".ftl" />

表示请求后缀,会自动加上的,所以在controller中不需要写后缀.ftl了


<property name="templateLoaderPath" value="/WEB-INF/freemarker/" />

请求的相对路径,指定好后controller中不需要写相对路径了



3.下面结合一个具体的Http请求来说明自己对MVC原理的理解

首先:浏览器中输入如下地址:


这个Http请求,MVC根据web.xml中配置寻找DispatcherServlet,然后该Http请求会交给DispatcherServlet来处理。


DispatcherServlet会进行路径匹配,查找对应的控制器,至于怎么查找的,就是@controller和@RequestMapping这些标签的功能了,以后再研究。如下图:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.suning.framework.dal.client.DalClient;
import org.apache.log4j.Logger;

@Controller
@RequestMapping("/admin")
public class IndexController {
    /**
     * 
     * 测试ztree搭建效果controller: <br>
     * 〈功能详细描述〉
     *
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @RequestMapping("/ztree.action")
    public ModelAndView ztree(){
        return new ModelAndView("index");
    }
}

IndexController也没处理什么业务逻辑,就是返回一个ModelAndView视图对象给DispatcherServlet。其中

 return new ModelAndView("index");
其中index被称为逻辑视图名,DispatcherServlet借助于sample-servlet.xml中的viewResolver(代码在上面),找到真正的视图对象freemarker/index.ftl



DispatcherServlet会接着对这个ftl页面进行渲染之类的处理,页面返回给浏览器客户端,这里我的页面就只是ztree的测试页面



以下是该Http请求过程中console的输出日志,学习下,看日志其实很重要

11:21:48.866 [http-bio-8080-exec-10] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'sample' processing GET request for [/snf-helloworld-sample/admin/ztree.action]
11:21:48.866 [http-bio-8080-exec-10] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /admin/ztree.action
11:21:48.866 [http-bio-8080-exec-10] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Returning handler method [public org.springframework.web.servlet.ModelAndView com.suning.sample.web.IndexController.ztree()]
11:21:48.866 [http-bio-8080-exec-10] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'indexController'
11:21:48.867 [http-bio-8080-exec-10] DEBUG o.s.web.servlet.DispatcherServlet - Last-Modified value for [/snf-helloworld-sample/admin/ztree.action] is: -1
[10 11:21:48,867 DEBUG] [http-bio-8080-exec-10] interceptor.ControlInterceptor - 这里进行controller类检查
[10 11:21:48,881 DEBUG] [http-bio-8080-exec-10] freemarker.cache - Could not find template in cache, creating new one; id=["index.ftl"["zh_CN",UTF-8,parsed] ]
[10 11:21:48,884 DEBUG] [http-bio-8080-exec-10] freemarker.cache - Compiling FreeMarker template "index.ftl"["zh_CN",UTF-8,parsed]  from "D:\\sts\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp2\\wtpwebapps\\snf-helloworld-sample\\WEB-INF\\freemarker\\index.ftl"
11:21:48.889 [http-bio-8080-exec-10] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request

功能一致,就不详解了。就此一个Http请求,DispatcherServlet功能就此结束了.一句话,DispatcherServlet很像是一个大管家。


感悟二:servlet-mapping和welcome-file-list之间关系

笔者遇到了一个问题就是无论如何都访问不index.htm页面,既http://10.22.2.74:8080/snf-helloworld-sample,后才知道是xml配置中出了问题

正确的web.xml:

 <servlet-mapping>
    <servlet-name>sample</servlet-name>
    <url-pattern>*.action</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.htm</welcome-file>
  </welcome-file-list>


之前我写的是:

<servlet-mapping>
    <servlet-name>sample</servlet-name>
    <url-pattern>/</url-pattern>
 </servlet-mapping>
 <welcome-file-list>
    <welcome-file>index.htm</welcome-file>
 </welcome-file-list>
也就是说对于这样一个http://10.22.2.74:8080/snf-helloworld-sample请求,会被DispatcherServlet捕获,/代表拦截所有的请求。然后日志记录错误信息如下:

14:42:50.100 [http-bio-8080-exec-4] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'sample' processing GET request for [/snf-helloworld-sample/]
14:42:50.101 [http-bio-8080-exec-4] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /index.htm
14:42:50.105 [http-bio-8080-exec-4] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Did not find handler method for [/index.htm]
14:42:50.105 [http-bio-8080-exec-4] WARN  o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/snf-helloworld-sample/] in DispatcherServlet with name 'sample'
14:42:50.106 [http-bio-8080-exec-4] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
DispatcherServlet会默认寻找index.htm这个控制器去了,所以自然是失败错误的。


当拦截的换为*.action的时候查看记录日志:
日志为空,DispatcherServlet就没接手这个Http请求,反而之是使用了welcome-file-list的配置,获取了WEB-INF下的index.htm



小拓展:当输入如下url时候也是可以的哦


道理一样哦





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值