一个简单的SpringMVC程序:
我们先通过创建一个简单的动态的JavaWeb项目“springmvc01”来认识一下SpringMVC,这样方便我们对其进行分析。
1、拷贝jar包:
对于所有框架而言,这一步都是必不可少的,我们需要在web工程的“WEB-INF”的目录下的lib文件夹中拷贝下列jar包,由于SpringMVC是spring家族的,使用它就必不可少的要拷贝spring框架的jar包:
- a.Spring框架的jar包:
- b.Spring框架的依赖包:
- c.SpringMVC框架的jar包:
- d.SpringMVC框架的依赖包:
2、创建一个JSP视图:
在“WEB-INF”目录下新建一个文件夹“jsp”用于存放JSP视图,在此目录下的视图非常安全,只能通过请求转发的方式访问。我们在此创建一个视图“hello.jsp”,该视图用于在浏览器客户端响应给用户。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
${msg }
</body>
</html>
3、定义一个控制器Controller:
这一步是SpringMVC框架的集中体现,之前众多Servlet现在都可以写在一个类(控制器)中,大大的简化了代码。我们在src目录下新建一个包“cn.jingpengchong.hello.controller”,在该包中新建一个类HelloController:
package cn.jingpengchong.hello.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class HelloController {
@RequestMapping("hello")
public ModelAndView hello() {
ModelAndView mav = new ModelAndView();
mav.setViewName("/WEB-INF/jsp/hello.jsp");
mav.addObject("msg", "Hello SpringMVC");
return mav;
}
}
- @Controller:添加该注解后该类可以被Spring扫描器到,并且告诉Spring该类是一个控制器;
- @RequestMapping():该注解用于使处理器映射器将其value属性值与请求地址进行匹配,以确定应该执行的方法;
- ModelAndView:该类见名知意,是一个封装模型和试图的类,其中可以封装了响应视图的地址和该视图所需的一些对象属性;
- setViewName():该方法的最终目的是要告诉处理器适配器要响应的视图的地址;
- addObject():该方法可以看作是request的setAttribute()方法,这样一来其作用便显而易见。
4、配置spring的xml核心配置文件:
这一步在Spring框架的学习中已经知晓,我们驾轻就熟的在其中配置一个扫描器即可,毕竟这只是一个HelloWorld程序:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<!-- 配置controller包扫描 -->
<context:component-scan base-package="cn.jingpengchong.hello"></context:component-scan>
</beans>
5、配置web.xml核心配置文件:
要发挥控制器的作用,在这里需要配置核心控制器(或称前端控制器),并且设置哪些请求路径会被匹配到并进行处理:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>springmvc01</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 核心控制器的配置 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- DispatcherServlet继承了父类FrameworkServlet的contextConfigLocation属性,因此这里可以给个初始值 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
6、测试:
将此项目添加进tomcat服务器并启动tomcat服务器,打开浏览器,并在地址栏输入“http://127.0.0.1/springmvc01/hello.do”后回车,结果如下:
请求的执行过程:
1、从在地址栏输入“http://127.0.0.1/springmvc01/hello.do”并回车,发送请求;
2、首先找到web.xml文件:
用于该请求以“.do”结尾,所以被url-pattern标签匹配到,然后根据servlet-name标签找到核心处理器“DispatcherServlet”。
3、然后找到springmvc.xml文件:
为核心处理器“DispatcherServlet”初始化contextConfigLocation属性时找到springmvc.xml文件。
4、然后找到HelloController.java文件:
由于springmvc.xml文件中配置了Spring扫描器,扫描器会去“cn.jingpengchong.hello”包下逐一查找添加了特定注解的类,由于类HelloController添加了@Controller注解,所以便被扫描到,并且根据该注解断定该类是一个处理器。
5、DispatcherServlet内部代码流程:
DispatcherServlet继承了FrameworkServlet的service():
从@Override注解我们知道该方法还是父类的,由于“HttpMethod.PATCH == httpMethod || httpMethod == null”的返回值时false,所以调用了父类的service()方法,我们点开其父类HttpServletBean发现并没有service()方法,由此我们推断可能在HttpServletBean的父类中,因此我们再次点开HttpServletBean的父类HttpServlet,果然在此找到了service()方法:
又由于我们的方法是get类型,因此执行“doGet(req, resp);”,又由于FrameworkServlet类中覆写了该方法,就近原则,必定调用的是FrameworkServlet中的doGet()方法:
我们看到该方法又调用了processRequest()方法,我们点开看看:
我们看到该方法内又调用了doService()方法,同时我们想到DispatcherServlet类继承了FrameworkServlet类,FrameworkServlet类中的这个doService()方法,应该调用的是DispatcherServlet类中的,我们观察该方法又调用了doDispatch()方法:
我们点开doDispatch()方法,发现里面获得了一个处理器适配器HandlerAdapter:
接着往下找,发现其又获得了一个处理器映射器:
该方法执行完毕。