一:笔者对于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时候也是可以的哦
道理一样哦