Spring Web MVC是基于Servlet API构建的原始Web框架,从一开始就包含在Spring框架中。正式的名称“Spring Web MVC”来自于它的源模块(spring-webmvc)的名称,常被人们称为“Spring MVC”。html
本文经过一个简单的增删改查demo切入,对SpringMVC源码进行解读,Spring Framework版本是4.3.7前端
开发工具IntelliJ IDEA 2017.1,JDK1.8java
Spring4.3.7,Hibernate 4.3.8,其他组件能够在pom.xml找到git
项目文件目录以下:github
源码请点击这里,在idea中导入web
输入git容器地址,点击clonespring
要让idea识别这是Web项目,打开File->Project Structure,通常idea会自动检测配置文件,提示你设置为spring配置文件,咱们也能够手动添加sql
再选中Web,将WEB-INF下的web.xml选中,并识别webapp根目录(idea会帮咱们自动配置)json
将Modules打成war_exploded浏览器
初始化数据,sql文件在/sql下,先运行table.sql,再运行init.sql
配置Tomcat,网上教程不少,再也不赘述
为web.xml配置入口Servlet
contextConfigLocation是上下文位置,读取了咱们的spring上下文配置文件
设置了编码过滤器CharacterEncodingFilter
咱们还配置了DispatcherServlet,这是SpringMVC的核心类,后续咱们会详细讲解,url-pattern配置"/","/"表明映射全部请求地址,如Controller请求路径/user/login,而不包括*.jsp,*.ftl等
<?xml version="1.0" encoding="UTF-8"?> <!--suppress ALL --> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springConfig/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>Set Character Encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>Set Character Encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springConfig/dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
写一个简单的Controller
@Controller表明这个类是个Controller,在dispatcher-servlet.xml中被<context:component-scan base-package="org.format.demo.controller" />扫描到,并识别成是"Controller",在Spring容器中初始化
@RequestMapping意思是请求映射,@RequestMapping("/")中的"/"的意义就是contextPath后面的路径;也就是 http://host:port/contextPath 后面的路径
ModelAndView是一个模型视图类,由handler返回,并有DispatcherServlet解析,咱们往view加入了key为"welcome",value为"hello"的Object
@Controller
@RequestMapping("/") public class IndexController { @RequestMapping public ModelAndView index() { ModelAndView view = new ModelAndView("index"); view.addObject("welcome", "hello"); return view; } }
在前端页面咱们能够看到key="welcome"
由于在前台咱们能够用EL表达式取出来
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>This is freemarker file</title> </head> <body> <h2>Welcome to user SpringMVC</h2> <h3>your welcome param: ${welcome}</h3></body> </html>
IndexController中ModelAndView view = new ModelAndView("viewName"); ,viewName="index"
根据freemarker.xml最终解析成/WEB-INF/view/{viewName}.ftl,因此找到了/WEB-INF/view/index.ftl
简单看下EmployeeController
package org.format.demo.controller; import org.format.demo.model.Employee; import org.format.demo.service.IDeptService; import org.format.demo.service.IEmployeeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import java.util.HashMap; import java.util.List; import java.util.Map; @Controller @RequestMapping(value = "/employee") public class EmployeeController { @Autowired private IEmployeeService employeeService; @Autowired private IDeptService deptService; @RequestMapping public ModelAndView index() { ModelAndView view = new ModelAndView("employee/list"); List<Employee> employees = employeeService.list(); view.addObject("list", employees); return view; } @RequestMapping(method = RequestMethod.POST, value = "/delete/{employeeId}") @ResponseBody public String delete(@PathVariable Integer employeeId) { employeeService.delete(employeeId); return "success"; } @RequestMapping(method = RequestMethod.GET, value = "/add") public ModelAndView add(ModelAndView view) { view.setViewName("employee/form"); view.addObject("depts", deptService.listAll()); return view; } @RequestMapping(method = RequestMethod.GET, value = "/detail/{employeeId}", produces={"application/json; charset=UTF-8"}) @ResponseBody public ModelAndView detail(@PathVariable Integer employeeId, ModelAndView view) { view.setViewName("employee/form"); view.addObject("employee", employeeService.getById(employeeId)); view.addObject("depts", deptService.listAll()); return view; } @RequestMapping(method = RequestMethod.POST, value = "/update") public String add(Employee employee) { if(employee.getDept().getId() == null) { employee.setDept(null); } employeeService.saveOrUpdate(employee); return "redirect:/employee/"; } }
1.@RequestMapping
这个注解会将 HTTP 请求映射到 MVC 和 REST 控制器的处理方法上,它既能够用在类上也能够用在方法上
2.@PathVariable
获取请求参数的值,这样每一个员工都有独立的URI资源
3.@ResponseBody
将Request的Accept设置为"application/json",就是把在@RequestMapping中produces加入"application/json";这里一样要将Response的Content-Type设置成"application/json",即加上@ResponseBody
Accept和Content-Type的区别?
Accept表示浏览器/客户端支持的类型,Content-Type表示发送端发送的数据类型
工欲善其事,必先利其器,这里我使用idea
理论以官方文档和源码为准
在阅读源码前,请你们下载源码,能够在Maven中下载,请你们自行百度如何下载源码。读.class文件没有意义,源码有丰富的注释
DispatcherServlet.class,我以为我没法读下去
DispatcherServlet.java,方法和变量都有详细的注释
记住快捷键会让你事半功倍
ctrl+n:快速进入类
ctrl+shift+n:进入普通文件
ctrl+f12:查看该类方法
在阅读源码的时候特别方便,由于你不可能每一个方法都细细品读
ctrl+alt+u:查看类结构图,这些类均可以点击进入,我比较喜欢用这个
ctrl+shift+alt+u:查看类结构图,这些类不能进入
alt+f7:查看方法引用位置,以doDispatch()为例,能够看到DispatcherServlet 897行被引用,858行注释被引用
ctrl+alt+b:跳转到方法实现处,对者接口方法点击,会弹出来在哪里实现。
接下来是我不得不说的idea神器---书签,bookmark能够对代码行进行标记,并进行快速切换
ctrl+f11:显示bookmark标记状况,土黄色表明该字符已被占用,输入或者点击1表明在此位置书签为1
咱们以processDispatchResult()方法为例
ctrl+标记编号 快速回到标记处,如我刚才在这留下了书签,ctrl+1,DispatcherServlet 1018行
shift+f11:显示全部书签,左栏是我打过书签的类、行信息,右边是代码详情
当你全部书签都用完,0-9,a-z所有用完,能够直接ctrl+f11,记录普通书签,虽然没法用ctrl快速跳转,在shift+f11仍是能够找到
alt+f8:启用Evaluate窗口
当咱们想看返回值,没法声明变量查看该变量的时候(源码不可更改)
可使用Evaluate表达式
SpringMVC是一个优秀的Web框架,简化了开发流程
接下来咱们将进入源码分析部分,待续...
http://www.cnblogs.com/fangjian0423/p/springMVC-introduction.html