一:SpingMVC请求过程
1:(发起请求——寻找控制器)
SpringMVC所有请求都会通过一个前端调度Servlet : DispatcherServlet,他的任务是将客户请求转发给SpringMVC控制器。常规的应用中控制器一般会有多个,所以DispatcherServlet会查询一个或多个处理器映射来确定将请求发往何处。在这个过程里,处理器映射将根据请求所携带的URL信息来进行判断。
DispaterServlet --------处理器映射---------控制器
2:(请求到达控制器)
找到正确的目标控制器后,DispatcherServlet把请求发送给它,到达控制器的请求会将它承载的请求信息保留下来,等待控制器处理。(此时DispatcherServlet等待返回)
3:(控制器处理完成之后)
控制完成相关业务逻辑处理,将需要返回给用户的信息打包,并标出用于渲染输出的视图名称,然后将“原始请求”、“返回信息(模型)”和“视图名称”移送给DispatcherServlet
4:(返回信息离开控制器——响应)
DispatcherServlet承载着上述的返回信息,将使用“视图解析器”来为视图名称匹配一个特定的视图实现(比如一个jsp页面)。在找到正确匹配的视图之后,DispatcherServlet将完成它的最后使命——将返回信息交给视图。视图会根据返回信息进行输出。
总结:在springMVC中,请求将由DispatcherServlet分配给控制器,在控制器完成处理以后。请求会被发送给一个视图来呈现输出结果。换句话说springMVC会将请求在DispatcherServlet、处理器映射、控制器和视图解析器之间移动。
二:搭建SpringMVC
1:首先在web.xml中进行配置
<servlet> <servlet-name>springMVC</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:config/spring/mvc-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
<servlet-name>在默认情况下,DispatcherServlet在加载时会从基于Servlet-name名字的文件中加载Spring应用上下文。(即:springMVC-servlet.xml) 本例中已经在<init-param>对文件名进行了修改。
<servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
这一段声明调度Servlet将处理哪些URL请求 。
2:配置应用上下文(mvc-servlet.xml)
<!-- ico --> <mvc:resources mapping="/*.ico" location="/images/" /> <!-- js --> <mvc:resources mapping="/js/**" location="/js/" /> <!-- images --> <mvc:resources mapping="/images/**" location="/images/" /> <!-- css --> <mvc:resources mapping="/css/**" location="/css/" /> <!--后面再说--> <mvc:annotation-driven />
<mvc:resources>会奖励一个服务于静态资源的处理器,来处理针对静态资源的请求。
3:编写控制器:
package com.services.days.controller; import java.util.Date; import javax.annotation.Resource; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.services.days.controller.base.BaseController; import com.services.days.domain.TestUser; import com.services.days.service.IUsersService; @Controller public class TestController extends BaseController{ private static Logger logger = Logger.getLogger(TestController.class); @Resource(name = "usersService") private IUsersService usersService; @RequestMapping(value = "/doTest") public String doTest() { TestUser testUser = new TestUser(); testUser.setCode("00221"); testUser.setEmail("[email protected]"); testUser.setPassword("pandy"); testUser.setState("001"); testUser.setCreateBy("01"); testUser.setCreateDatetime(new Date()); testUser.setModifyBy("001"); testUser.setModifyDatetime(new Date()); usersService.saveUser(testUser); System.out.println(testUser.toString()); testUser = usersService.queryUsersById(3); // System.out.println(user.toString()); System.out.println("Test success......."); return "success"; } @RequestMapping(value="/investList") public ModelAndView investList() { return new ModelAndView("/shop/investList"); } }
上面是一个针对用户的简单控制器,作用是我们在发起对http://******/doTest.do 的请求后,springMVC会将请求发送到这个控制器并调用doTest()方法,向数据库中插入一个新的TestUser。
关于dispatcherServlet如何寻找正确的处理器,springMVC提供了多种处理器实现,在这里我且不一 一表述,我们使用:DefaultAnnotationHandlerMapping,即:将请求映射给使用了@RequestMapping注解的控制器和控制器方法。
DefaultAnnotationHandlerMapping会将请求映射到使用@RequestMapping注解的控制器方法。但是在一个构建控制器的时候,我们还需要使用注解,将请求参数绑定到控制器的方法参数上,进行校验和信息转换,此时需要在我们的mvc-servlet.xml加上一句:
<mvc:annotation-driven />
<mvc:annotation-driven />具体功能略。
再来看我们上面的用户控制器。
@Controller很熟悉,它属于@Component注解,配置文件中的<context:component-scan>将会查找使用了这此注解的类,并将它注册为Bean,所以我们需要在mvc-servlet.xml配置文件中,加入<context:component-scan>片段。(当然,一般我们习惯将它写在application.xml中)
<context:component-scan base-package="com.services.days" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" /> </context:component-scan>
在这个用户控制器中:doTest()方法使用了注解@RequestMapping(value = "/doTest")
即针对http://******/doTest.do的请求会被发送到此处。在这里我们只是简单的测试,并没有为该控制器加入相关@RequestMapping来作为请求的上级命名空间。