前文咱们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那咱们如何更好的构建下层的利用呢(比方web 利用),这便是SpringMVC;Spring MVC是Spring在Spring Container Core和AOP等技术根底上,遵循上述Web MVC的标准推出的web开发框架,目标是为了简化Java栈的web开发。 本文次要介绍SpringMVC次要的流程和根底案例的编写和运行。@pdai
Spring框架系列(5) - 深入浅出SpringMVC申请流程和案例
- 引入
- 什么是MVC
- 什么是Spring MVC
Spring MVC的申请流程
- 外围架构的具体流程步骤
- 对上述流程的补充
Spring MVC案例
- Maven包引入
- 业务代码的编写
- webapp下的web.xml
- springmvc.xml
- JSP视图
- 部署测试
- 示例源码
- 更多文章
引入
前文咱们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),同时咱们也通过几个Demo利用了Core Container中包
Demo中core container中包应用如下
那么问题是,咱们如何更好的构建下层的利用呢?比方web 利用?
针对下层的Web利用,SpringMVC诞生了,它也是Spring技术栈中最为重要的一个框架。
所以为了更好的帮忙你串联整个常识体系,我列出了几个问题,通过如下几个问题帮你深入浅出的构建对SpringMVC的认知。
- Java技术栈的Web利用是如何倒退的?
- 什么是MVC,什么是SpringMVC?
- SpringMVC次要的申请流程是什么样的?
- SpringMVC中还有哪些组件?
- 如何编写一个简略的SpringMVC程序呢?
什么是MVC
MVC英文是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计规范。实质上也是一种解耦。
用一种业务逻辑、数据、界面显示拆散的办法,将业务逻辑汇集到一个部件外面,在改良和个性化定制界面及用户交互的同时,不须要从新编写业务逻辑。MVC被独特的倒退起来用于映射传统的输出、解决和输入性能在一个逻辑的图形化用户界面的构造中。
- Model(模型)是应用程序中用于解决应用程序数据逻辑的局部。通常模型对象负责在数据库中存取数据。
- View(视图)是应用程序中解决数据显示的局部。通常视图是根据模型数据创立的。
- Controller(控制器)是应用程序中解决用户交互的局部。通常控制器负责从视图读取数据,管制用户输出,并向模型发送数据。
什么是Spring MVC
简略而言,Spring MVC是Spring在Spring Container Core和AOP等技术根底上,遵循上述Web MVC的标准推出的web开发框架,目标是为了简化Java栈的web开发。@pdai
(PS:从我的了解就上述一句话,为了读者学习,这里找了下kaitao老师写的SpringMVC的介绍)
Spring Web MVC 是一种基于Java 的实现了Web MVC 设计模式的申请驱动类型的轻量级Web 框架,即应用了MVC 架
构模式的思维,将 web 层进行职责解耦,基于申请驱动指的就是应用申请-响应模型,框架的目标就是帮忙咱们简化开
发,Spring Web MVC 也是要简化咱们日常Web 开发的。
相干个性如下:
- 让咱们能非常简单的设计出洁净的Web 层和薄薄的Web 层;
- 进行更简洁的Web 层的开发;
- 天生与Spring 框架集成(如IoC 容器、AOP 等);
- 提供弱小的约定大于配置的契约式编程反对;
- 能简略的进行Web 层的单元测试;
- 反对灵便的URL 到页面控制器的映射;
- 非常容易与其余视图技术集成,如 Velocity、FreeMarker 等等,因为模型数据不放在特定的 API 里,而是放在一个
Model 里(Map 数据结构实现,因而很容易被其余框架应用); - 非常灵活的数据验证、格式化和数据绑定机制,能应用任何对象进行数据绑定,不用实现特定框架的API;
- 提供一套弱小的JSP 标签库,简化JSP 开发;
- 反对灵便的本地化、主题等解析;
- 更加简略的异样解决;
- 对动态资源的反对;
- 反对Restful 格调。
Spring MVC的申请流程
Spring Web MVC 框架也是一个基于申请驱动的Web 框架,并且也应用了前端控制器模式来进行设计,再依据申请映射
规定分发给相应的页面控制器(动作/处理器)进行解决。
外围架构的具体流程步骤
首先让咱们整体看一下Spring Web MVC 解决申请的流程:
外围架构的具体流程步骤如下:
- 首先用户发送申请——>DispatcherServlet,前端控制器收到申请后本人不进行解决,而是委托给其余的解析器进行
解决,作为对立拜访点,进行全局的流程管制; - DispatcherServlet——>HandlerMapping, HandlerMapping 将会把申请映射为 HandlerExecutionChain 对象(蕴含一
个Handler 处理器(页面控制器)对象、多个HandlerInterceptor 拦截器)对象,通过这种策略模式,很容易增加新
的映射策略; - DispatcherServlet——>HandlerAdapter,HandlerAdapter 将会把处理器包装为适配器,从而反对多种类型的处理器,
即适配器设计模式的利用,从而很容易反对很多类型的处理器; - HandlerAdapter——>处理器性能解决办法的调用,HandlerAdapter 将会依据适配的后果调用真正的处理器的性能处
理办法,实现性能解决;并返回一个ModelAndView 对象(蕴含模型数据、逻辑视图名); - ModelAndView 的逻辑视图名——> ViewResolver,ViewResolver 将把逻辑视图名解析为具体的View,通过这种策
略模式,很容易更换其余视图技术; - View——>渲染,View 会依据传进来的Model 模型数据进行渲染,此处的Model 理论是一个Map 数据结构,因而
很容易反对其余视图技术; - 返回控制权给DispatcherServlet,由DispatcherServlet 返回响应给用户,到此一个流程完结。
对上述流程的补充
上述流程只是外围流程,这里咱们再补充一些其它组件:
- Filter(ServletFilter)
进入Servlet前能够有preFilter, Servlet解决之后还可有postFilter
- LocaleResolver
在视图解析/渲染时,还须要思考国际化(Local),显然这里须要有LocaleResolver.
- ThemeResolver
如何管制视图款式呢?SpringMVC中还设计了ThemeSource接口和ThemeResolver,蕴含一些动态资源的汇合(款式及图片等),用来管制利用的视觉格调。
- 对于文件的上传申请?
对于惯例申请上述流程是正当的,然而如果是文件的上传申请,那么就不太一样了;所以这里便呈现了MultipartResolver。
Spring MVC案例
这里次要向你展现一个根本的SpringMVC例子,后文中将通过以Debug的形式剖析源码。
本例子中次要文件和构造如下:
Maven包引入
次要引入spring-webmvc包(spring-webmvc包中曾经蕴含了Spring Core Container相干的包),以及servlet和jstl(JSP中应用jstl)的包。
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>tech-pdai-spring-demos</artifactId> <groupId>tech.pdai</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>011-spring-framework-demo-springmvc</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <spring.version>5.3.9</spring.version> <servlet.version>4.0.1</servlet.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> </dependencies></project>
业务代码的编写
User实体
package tech.pdai.springframework.springmvc.entity;/** * @author pdai */public class User { /** * user's name. */ private String name; /** * user's age. */ private int age; /** * init. * * @param name name * @param age age */ public User(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}
Dao
package tech.pdai.springframework.springmvc.dao;import org.springframework.stereotype.Repository;import tech.pdai.springframework.springmvc.entity.User;import java.util.Collections;import java.util.List;/** * @author pdai */@Repositorypublic class UserDaoImpl { /** * mocked to find user list. * * @return user list */ public List<User> findUserList() { return Collections.singletonList(new User("pdai", 18)); }}
Service
package tech.pdai.springframework.springmvc.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import tech.pdai.springframework.springmvc.dao.UserDaoImpl;import tech.pdai.springframework.springmvc.entity.User;import java.util.List;/** * @author pdai */@Servicepublic class UserServiceImpl { /** * user dao impl. */ @Autowired private UserDaoImpl userDao; /** * find user list. * * @return user list */ public List<User> findUserList() { return userDao.findUserList(); }}
Controller
package tech.pdai.springframework.springmvc.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;import tech.pdai.springframework.springmvc.service.UserServiceImpl;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.Date;/** * User Controller. * * @author pdai */@Controllerpublic class UserController { @Autowired private UserServiceImpl userService; /** * find user list. * * @param request request * @param response response * @return model and view */ @RequestMapping("/user") public ModelAndView list(HttpServletRequest request, HttpServletResponse response) { ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("dateTime", new Date()); modelAndView.addObject("userList", userService.findUserList()); modelAndView.setViewName("userList"); // views目录下userList.jsp return modelAndView; }}
webapp下的web.xml
(创立上图的文件构造)
webapp下的web.xml如下:
<?xml version="1.0" encoding="UTF-8"?><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"> <display-name>SpringFramework - SpringMVC Demo @pdai</display-name> <servlet> <servlet-name>springmvc-demo</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 通过初始化参数指定SpringMVC配置文件的地位和名称 --> <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-demo</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <filter> <filter-name>encodingFilter</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>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping></web-app>
springmvc.xml
web.xml中咱们配置初始化参数contextConfigLocation,门路是classpath:springmvc.xml
<init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value></init-param>
在resources目录下创立
<?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" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="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.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 扫描注解 --> <context:component-scan base-package="tech.pdai.springframework.springmvc"/> <!-- 动态资源解决 --> <mvc:default-servlet-handler/> <!-- 开启注解 --> <mvc:annotation-driven/> <!-- 视图解析器 --> <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean></beans>
JSP视图
创立userList.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><!DOCTYPE html><html lang="zh-CN"><head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>User List</title> <!-- Bootstrap --> <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"></head><body> <div class="container"> <c:if test="${!empty userList}"> <table class="table table-bordered table-striped"> <tr> <th>Name</th> <th>Age</th> </tr> <c:forEach items="${userList}" var="user"> <tr> <td>${user.name}</td> <td>${user.age}</td> </tr> </c:forEach> </table> </c:if> </div></body></html>
部署测试
咱们通过IDEA的tomcat插件来进行测试
下载Tomcat:tomcat地址
下载后给tomcat/bin执行文件赋权
pdai@MacBook-Pro pdai % cd apache-tomcat-9.0.62 pdai@MacBook-Pro apache-tomcat-9.0.62 % cd bin pdai@MacBook-Pro bin % lsbootstrap.jar makebase.shcatalina-tasks.xml setclasspath.batcatalina.bat setclasspath.shcatalina.sh shutdown.batciphers.bat shutdown.shciphers.sh startup.batcommons-daemon-native.tar.gz startup.shcommons-daemon.jar tomcat-juli.jarconfigtest.bat tomcat-native.tar.gzconfigtest.sh tool-wrapper.batdaemon.sh tool-wrapper.shdigest.bat version.batdigest.sh version.shmakebase.batpdai@MacBook-Pro bin % chmod 777 *.shpdai@MacBook-Pro bin %
配置Run Congfiuration
增加Tomcat Server - Local
将咱们下载的Tomcat和Tomcat Server - Local关联
在Deploy中增加咱们的我的项目
运行和治理Tomcat Sever(留神context门路)
运行后拜访咱们的web程序页面(留神context门路)
PS:是不是so easy~ @pdai
示例源码
https://github.com/realpdai/t...
注:
本文中SpringMVC流程图来源于kaitao的博客,如果你心愿全面学习SpringMVC能够查看kaitao总结的跟开涛学 SpringMVC (向已经的大佬致敬)
更多文章
首先, 从Spring框架的整体架构和组成对整体框架有个认知。
Spring根底 - Spring和Spring框架组成
- Spring是什么?它是怎么诞生的?有哪些次要的组件和外围性能呢? 本文通过这几个问题帮忙你构筑Spring和Spring Framework的整体认知。
其次,通过案例引出Spring的外围(IoC和AOP),同时对IoC和AOP进行案例应用剖析。
Spring根底 - Spring简略例子引入Spring的外围
- 上文中咱们简略介绍了Spring和Spring Framework的组件,那么这些Spring Framework组件是如何配合工作的呢?本文次要承接上文,向你展现Spring Framework组件的典型利用场景和基于这个场景设计出的简略案例,并以此引出Spring的外围要点,比方IOC和AOP等;在此基础上还引入了不同的配置形式, 如XML,Java配置和注解形式的差别。
Spring根底 - Spring外围之管制反转(IOC)
- 在Spring根底 - Spring简略例子引入Spring的外围中向你展现了IoC的根底含意,同时以此发散了一些IoC相干知识点; 本节将在此基础上进一步解读IOC的含意以及IOC的应用形式
Spring根底 - Spring外围之面向切面编程(AOP)
- 在Spring根底 - Spring简略例子引入Spring的外围中向你展现了AOP的根底含意,同时以此发散了一些AOP相干知识点; 本节将在此基础上进一步解读AOP的含意以及AOP的应用形式。
基于Spring框架和IOC,AOP的根底,为构建下层web利用,须要进一步学习SpringMVC。
Spring根底 - SpringMVC申请流程和案例
- 前文咱们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那咱们如何更好的构建下层的利用呢(比方web 利用),这便是SpringMVC;Spring MVC是Spring在Spring Container Core和AOP等技术根底上,遵循上述Web MVC的标准推出的web开发框架,目标是为了简化Java栈的web开发。 本文次要介绍SpringMVC的申请流程和根底案例的编写和运行。
Spring进阶 - IoC,AOP以及SpringMVC的源码剖析
Spring进阶 - Spring IOC实现原理详解之IOC体系结构设计
- 在对IoC有了初步的认知后,咱们开始对IOC的实现原理进行深刻了解。本文将帮忙你站在设计者的角度去看IOC最顶层的结构设计
Spring进阶 - Spring IOC实现原理详解之IOC初始化流程
- 上文,咱们看了IOC设计要点和设计构造;紧接着这篇,咱们能够看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的
Spring进阶 - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)
- 上文,咱们看了IOC设计要点和设计构造;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中寄存的是Bean的定义即BeanDefinition放到beanDefinitionMap中,实质上是一个
ConcurrentHashMap<String, Object>
;并且BeanDefinition接口中蕴含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文次要钻研的内容?
- 上文,咱们看了IOC设计要点和设计构造;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中寄存的是Bean的定义即BeanDefinition放到beanDefinitionMap中,实质上是一个
Spring进阶 - Spring AOP实现原理详解之切面实现
- 前文,咱们剖析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的。本文次要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理加强实现做筹备的过程)。
Spring进阶 - Spring AOP实现原理详解之AOP代理
- 上文咱们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面办法依据应用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor)。本文在此基础上持续介绍,代理(cglib代理和JDK代理)的实现过程。
Spring进阶 - Spring AOP实现原理详解之Cglib代理实现
- 咱们在前文中曾经介绍了SpringAOP的切面实现和创立动静代理的过程,那么动静代理是如何工作的呢?本文次要介绍Cglib动静代理的案例和SpringAOP实现的原理。
Spring进阶 - Spring AOP实现原理详解之JDK代理实现
- 上文咱们学习了SpringAOP Cglib动静代理的实现,本文次要是SpringAOP JDK动静代理的案例和实现局部。
Spring进阶 - SpringMVC实现原理之DispatcherServlet初始化的过程
- 前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第一篇:DispatcherServlet的初始化过程的源码解析。
Spring进阶 - SpringMVC实现原理之DispatcherServlet解决申请的过程
- 前文咱们有了IOC的源码根底以及SpringMVC的根底,咱们便能够进一步深刻了解SpringMVC次要实现原理,蕴含DispatcherServlet的初始化过程和DispatcherServlet解决申请的过程的源码解析。本文是第二篇:DispatcherServlet解决申请的过程的源码解析。