目录:
1. WebMVC介绍
2. Spring MVC体系结构
3. DispatcherServlet类
4. 一个简单的Spring MVC实例(使用IDEA实现)
1. WebMVC介绍
MVC是一种使用MVC(Model View Controller 模型-视图-控制器)设计创建Web应用程序的模式:
- Model(模型) 应用程序核心(比如数据库记录列表)
- View(视图)显示数据
- Controller(控制器)处理输入
常用的MVC框架有Struts和SpringMVC。
Struts是MVC框架中不争的王者,但是其在某些技术特性上落后新兴的MVC框架。
Spring MVC框架是一个MVC框架,通过实现Model-View-Controller模式来很好地将数据、业务与展现进行分离。
MVC模式的优缺点:
优点:
- 耦合性低
- 重用性高
- 生命周期成本低
- 部署快
- 可维护性高
- 有利于软件工程化管理
缺点:
- 没有明确的定义
- 不适合小型,中等规模的应用程序
- 增加系统结构和实现的复杂性
- 视图与控制器间的过于紧密的连接
- 视图对模型数据的低效率访问
Spring MVC框架
Spring MVC,基于MVC设计理念,此外,还采用了送上耦合可插拔组件结构,比其他MVC框架更具扩展性和灵活性。
Spring MVC在数据绑定、视图解析、本地化处理及静态资源处理上都有不俗的表现。
Spring3.0版本中,定义控制器类,必须以@Controller注解进行标注。当控制器接收到一个请求时,它会在自己内部寻找一个合适的方法来处理请求。使用@RequestMapping注解,可以将方法映射都某个特定请求上,用于对该请求的处理。
Spring MVC处理流程
Spring MVC的设计是围绕DispatcherServlet展开的,DispatcherServlet负责将请求派发到特定的handler。通过可配置的handler mappings、view resolution完成Web请求,并且转到对应的视图。
Spring MVC请求处理的整体流程如图。
2.Spring MVC体系结构
SpringMVC是基于Model2实现的技术框架。
Spring MVC框架整个处理响应的步骤如下:
第一步:客户端发送HTTP请求;
第二步:DispatcherServlet接受请求后,将请求委托给具体的处理器Handler,后者将处理请求并执行响相应的业务逻辑;DispatcherServlet根据请求信息(URL或请求参数等)找到请求对应的Handler,通过查找HandlerMapping完成这一工作;
第三步:Dispatcher找到请求对应的Handler后,将请求分配给这个处理器,执行相应的业务逻辑;
第四步:Handler处理完业务逻辑后,将返回ModelAndView对象,给DispatcheServlet,ModelAndView中包含了视图逻辑名和渲染视图时需要用到的模型数据对象;
第五步:进行视图解析,调用Viewresolver,知道视图逻辑名对应的真实视图对象;
第六步:得到真实的视图对象后,DispatcherServlet将请求分配给这个对象,由其完成VModel数据的渲染工作;
第七步:最终客户端得到返回的响应,可能是HTML,Excel,PDF等形式。
3. DispatcherServlet类
- 配置DispatcherServlet
DispatcherServlet的父类继承了HTTPServlet类,所以DispatcherServlet核心本质是一个Servlet。
要使用Spring MVC,必须在web.xml中配置DispatcherServlet类:
下面是web.xml的具体配置:
<!-- 加载spring上下文 -->
<!-- 1 配置Spring,指定applicationContext.xml为业务层和持久层的Spring配置文件,这些配置文件被父Spring容器使用 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 2 声明DispatcherServlet -->
<servlet>
<servlet-name>myDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value> <!-- SpringMVC配置文件 -->
</init-param>
<load-on-startup>1</load-on-startup> <!—Web应用启动时优先加载 -->
</servlet>
<servlet-mapping>
<servlet-name>myDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern> <!-- 3 请求后缀 -->
</servlet-mapping>
- DispatcherServlet类的继承体系:
– DispatcherServlet类的运行体系:
— DispatcherServlet的核心本质:是一个Servlet
— init方法在整个系统启动时运行,且只运行一次,在init方法中,对整个应用程序进行初始化操作;
— service()方法在系统运行的过程中处于侦听模式,侦听并处理所有的Web请求;
对于Spring MVC而言,用于对不同的逻辑职责进行划分,形成两条互不相关的逻辑运行主线:初始化主线,负责对Spring MVC的运行要素进行初始化;HTTP请求处理主线,负责对Spring MVC中的组件进行逻辑调度,完成HTTP请求的处理。
Spring MVC运行主线的划分,依据Servlet对象中不同方法的生命周期进行划分,几乎所有MVC框架都是根据这一原理进行划分。
– DispatcherServlet类的继承体系:
— 依次继承FrameworkServlet和HTTPServletBean
— HTTPServletBean是Spring对于Servlet最底层的抽象
— FrameworkServlet则是在HTTPServletBean的基础上的进一步抽象,通过FrameworkServlet真正初始化了一个Spring的容器(WebApplicationContext)并引入到Servlet对象中
— DispatcherServlet通过initStrategies方法查找并装配Spring容器中用户定义的组件Bean
4. 一个简单的Spring MVC实例
如下图所示,实现一个简单的登录系统:
开发环境如下:IntelliJ IDEA,Tomcat8.5,Maven,JDK1.8。
在创建项目前,确保maven,jdk都已安装好。
1 打开IDEA,new一个project,选择Maven,勾选Create from archetype,选中maven-archetype-webapp,next,输入GroupId为com.feng,ArtifactId为springmvc_simpleLogin,next,选中项目地址,Finish,然后开始自动下载Maven相关文件,加载完成后,就创建了一个Maven管理的Web项目。
2 然后添加Tomcat服务器,选中工具栏小锤子右边的Add Configuration,点击+好,选中Tomcat Server,选中local,输入一个名字,在Deployment下选中+,选择Artifact,选择下方的exploded结尾的选项,点击ok,完成Tomcat的配置。
然后点击绿色小三角,出现HelloWorld页面,项目便运行起来了。
3 添加Spring MVC的相关Jar包 spring-webmvc spring-tx,通过pom.xml添加相关的dependencies。
打开MavenRepository,搜索Spring webmvc和Spring transaction,选择5.1.5版本的把依赖拷贝到pom.xml中
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
下面是配置好的pom.xml
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.feng</groupId>
<artifactId>springmvc_simpleLogin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>springmvc_simpleLogin Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- Spring webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!-- Spring Transaction -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
</dependencies>
<build>
<finalName>springmvc_simpleLogin</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
4 配置web.xml,在其中配置好Spring上下文,DispatcherServlet,如下所示:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<context-param> <!-- 这一段没加报错了 所以后来又加上了,运行之后报错找不到这个xml,然后在WEB-INF目录下创建applicationContext.xml,点击Configurate Spring Context 即可 -->
<param-name>ContextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- spring mvc的前端控制器 -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value> <!-- Spring MVC配置文件 -->
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.html</url-pattern> <!-- 处理的请求为html -->
</servlet-mapping>
</web-app>
5 编写spring-mvc.xml文件,在WEB-INF目录下,new一个XMLConfiguration File 选择Spring config,新建一个spring-mvc.xml,添加自动扫描包,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns="http://www.springframework.org/schema/beans"
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">
<!-- 自动扫描包,使SpringMVC认为该包下面具有@Controller注解的类的控制器 -->
<context:component-scan base-package="com.feng"/>
</beans>
右键项目名,选择 Open Module Settings,选择Spring,界面如下:
配置工作到现在就完成了,下面开始编写代码。
6 编写显示层代码。编写login.jsp和success.jsp两个jsp页面,在web目录下新建jsp目录,创建login.jsp用于登录,在其中添加一个form表单,点击登录提交用户名和密码,代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<form action="login.html" method="post">
<p>
用户名:<input name="username" type="text">
</p>
<p>
密 码:<input name="password" type="password">
</p>
<p>
<input type="submit" value="登录">
</p>
</form>
<font color="red">${error }</font>
</body>
</html>
同理,创建一个success.jsp,作为登录成功后的页面,代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功</title>
</head>
<body>
您已登录!
</body>
</html>
7 编写业务层和模型层代码,创建Controller和Service。
在main下新建一个java目录,右键 选择 Make Directory as Sources Root。
接下来在java目录下new一个Java Class,package为com.feng.demo.springmvc.controller,类名LoginController,用作Controller;同理创建LoginService,package为com.feng.demo.springmvc.service,用作Service。
编写LoginController,在class上方添加Controller注解,创建两个方法,用于显示登录页面和处理登录,并添加RequestMapping注解,代码如下:
/**
* Copyright (C), 2015-2019, XXX有限公司
* FileName: LoginController
* Author: cfl
* Date: 2019/8/9 22:32
* Description: 控制器实现
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.feng.demo.springmvc.controller;
import com.feng.demo.springmvc.service.LoginService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
* 〈一句话功能简述〉<br>
* 〈控制器实现〉
*
* @author cfl
* @create 2019/8/9
* @since 1.0.0
*/
@Controller
public class LoginController {
@Resource
LoginService loginService;
@Resource
HttpServletRequest request;
@RequestMapping("index")
public ModelAndView toLoginPage(){
return new ModelAndView("WEB-INF/jsp/login.jsp");
}
@RequestMapping("login")
public ModelAndView doLogin(){
String loginPageUrl = "/WEB-INF/jsp/login.jsp";
String successUrl = "/WEB-INF/jsp/success.jsp";
String name = request.getParameter("username");
String password = request.getParameter("password");
//具体处理交由LoginService
return loginService.doLogin(loginPageUrl, successUrl, name, password);
}
}
编写Service,在LoginService的class上方添加Service注解,并编写doLogin方法,处理登录的业务逻辑,如果用户名为admin,密码为123456,则登录成功。代码如下:
/**
* Copyright (C), 2015-2019, XXX有限公司
* FileName: LoginService
* Author: cfl
* Date: 2019/8/9 22:33
* Description: Service实现
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.feng.demo.springmvc.service;
/**
* 〈一句话功能简述〉<br>
* 〈Service实现〉
*
* @author cfl
* @create 2019/8/9
* @since 1.0.0
*/
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;
@Service
public class LoginService {
public ModelAndView doLogin(String loginPageUrl, String successUrl, String name, String password) {
if (name == null ||"".equals(name)){
return new ModelAndView(loginPageUrl, "error", "用户名不能为空");
}
if(password == null || "".equals(password)){
return new ModelAndView(loginPageUrl, "error", "密码不能为空");
}
// 假设用户名为admin,密码为123456
if (name.equals("admin") && password.equals("123456")){
return new ModelAndView(successUrl);
}
return new ModelAndView(loginPageUrl, "error", "用户名或密码错误");
}
}
最终得到的工程目录如下:
现在可以运行项目了,在地址栏输入index.html
项目成功运行。
写在最后:编写完代码运行项目时遇到了两个问题:
- connot resolve symbol ‘HttpServletRequest’
百度之后说是需要添加servlet-api.jar。 参考 - EL表达式直接显示${error }
在jsp页面最前面的<@page>里面加上了isELIgnored=“false”,成功解决。参考
注:第四部分Spring MVC实现参考了使用IntelliJ IDEA开发SpringMVC网站