今天我们来理一下web服务器请求和响应的整个完整过程。先来放两张图。
首先浏览器发送请求,请求到达web服务器(比如apache服务器),然后到达servlet容器(比如tomcat),然后就到springmvc的DispatcherServlet,当然此时数据的表现形式已经早就不是url了,是对象了(万物皆对象,java的金句)。然后就开始springmvc的表演了,第一步DispatcherServlet调用映射处理器handleMapping,通过url找到对应的controller类,HandlerMapping接口的实现(只举了我认识的几个) :
-
BeanNameUrlHandlerMapping :通过对比url和bean的name找到对应的对象
SimpleUrlHandlerMapping :也是直接配置url和对应bean,比BeanNameUrlHandlerMapping功能更多
DefaultAnnotationHandlerMapping : 主要是针对注解配置@RequestMapping的,已过时
RequestMappingHandlerMapping :取代了上面一个
在编写handler时要使用@Controller标识 它是一个控制器
如下:
@Controller
public class ItemsController3 {
}
类结构如下:
1、SimpleServletHandlerAdapter实际就是执行HttpServlet的service方法 springMVC源码分析--SimpleServletHandlerAdapter(二)
2、SimpleControllerHandlerAdapter实际就是执行Controller的handleRequest方法 springMVC源码分析--SimpleControllerHandlerAdapter(三)
3、HttpRequestHandlerAdapter实际就是执行HttpRequestHandler的handleRequest方法 springMVC源码分析--HttpRequestHandlerAdapter(四)
4、RequestMappingHandlerAdapter实际就是执行@RequestMapping注解的方法。
5、AnnotationMethodHandlerAdapter已结被废弃,就不做过多介绍
HandlerAdapter的接口中定义了三个方法:
(1)boolean supports(Object handler); 判断是否支持传入的Handler
(2)ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) 用来使用Handler处理请求
(3)long getLastModified(HttpServletRequest request, Object handler); 用来获取资料的Last-Modified值。
接口源码如下:
HandlerAdapter的执行操作,其执行过程在DispatcherServlet的doDispatch中,执行流程如下:
getHandlerAdapter的操作就是选择合适的HandlerAdapter来执行,设计模式中的适配器模式,handlerAdapters中的内容就是所有的HandlerAdapter的实现类。
这样就完成了Handler的真正调用过程,最终调用过程是返回一个ModelAndView对象。
然后就到了视图解析器了,在项目中用到了Velocity。首先需要配置Velocity,在wepapp-servlet.xml中是这样的
<bean id="velocityConfigurer"
class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath" value="/WEB-INF/velocity/" />
<property name="configLocation" value="/WEB-INF/velocity.properties" />
<property name="velocityProperties">
<props>
<prop key="input.encoding">utf-8</prop>
<prop key="output.encoding">utf-8</prop>
<prop key="velocimacro.library">velocity-macro.vm</prop>
</props>
</property>
</bean>
<!-- 配置VelocityConfigurer,负责在spring中设置Velocity引擎。通过属性resourceLoaderPath告诉Velocity到哪里寻找它的模板。 通常将模板放到WEB-INF下的某个子目录下,可以保证这些模板不能被直接访问。-->设置了属性文件的内容velocity.properties
当然在maven的依赖管理中也要加入Velocity的依赖。
<dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-tools</artifactId> <version>2.0</version> </dependency>
配置视图解析器
<bean id="velocityViewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"> <property name="suffix"> <value>.vm</value> </property> <property name="exposeSpringMacroHelpers" value="true" /> <property name="contentType" value="text/html;charset=utf-8" /> <property name="attributes"> <props> <prop key="webServerUrl">${tkm.web.server.url}</prop> <prop key="staticServerUrl">${tkm.static.server.url}</prop> <prop key="photoServerUrl">${tkm.photo.server.url}</prop> </props> </property> <property name="toolboxConfigLocation" value="/WEB-INF/vm/toolbox.xml" /> </bean>
在webapp-servlet.xml文件中,还可以看到<property name="toolboxConfigLocation" value="/WEB-INF/toolbox.xml"/>,在web-inf路径下,建一个toolbox.xml文件,如下:
<?xml version="1.0" encoding="UTF-8" ?> <toolbox> <tool> <key>UrlUtil</key> <class>com.nali.common.util.UrlUtil</class> <scope>application</scope> </tool> <tool> <key>VersionUtil</key> <class>com.ximalaya.shop.api.domain.util.VersionUtil</class> <scope>application</scope> </tool> </toolbox>
这个配置文件可以让我们在vm中使用后台java类中定义的方法.
说了半天不知道视图解析器是干嘛用的。
视图解析器就找到对应的view的,然后把模型的数据渲染到视图中,然后把视图返回会浏览器。那么viewresolver是怎么找到对应的视图的呢,视图和模型数据是怎么对应上的呢?
我的理解是这样:
浏览器发送了请求,servlet根据url找到了controller的类,在controller类中有这么一行代码 return "/tkm/mobile_main";
按我的理解这就是一个string,是一个modelandview,是一个逻辑视图名称,然后我们的视图处理器viewresolver就需要拿着这个去找真正的物理视图,是怎么找的呢,在我看的项目中用的是velocity框架。这部分不深究了,后期再理。不了解的东西有点多。