三层架构
在B/S架构中,系统的三层架构包括:表现层、业务层、持久层。
表现层
表现层也就是web层,负责接收客户端请求,响应结果给客户端,通常使用HTTP协议完成请求与响应。
表现层包括展示层和控制层:控制层负责接收请求,展示层负责展示结果。
表现层的设计一般使用的是MVC模型。
业务层
业务层也就是service层,负责处理业务逻辑
持久层
持久层也就是DAO(Data Access Object)层,负责数据持久化(对数据库表的CRUD操作)。持久成包括数据层(即数据库)和数据访问层,数据层是对数据进行持久化的载体,数据访问层是业务层和持久层交互的接口,即业务层通过数据访问层将数据持久化到数据库中。
其中,表现层依赖业务层,客户端的请求需要业务层进行逻辑处理,并将结果返回给客户端,业务层在处理业务逻辑时可能会依赖持久层,将数据持久化。
MVC模型
MVC全称Model View Controller,即模型、视图、控制器,可以看做是构建WEB应用表现层的一种模式。
Model
模型通常指的是数据模型,用于封装请求和响应的数据,如JavaBean对象
View
视图通常指的是JSP或者HTM, 展示数据给客户端
视图依据模型数据创建
Controller
应用程序中处理用户交互的部分,即处理程序逻辑,充当Servlet
举例:
用户提交一个包含年龄、姓名、性别等消息的表单 ,控制器接受提交表单的请求后对表单数据做校验,校验失败,控制器负责响应错误页面给客户端,或者校验成功,控制器负责把数据填充到模型,然后调用业务层实现完整的业务需求,视图层负责展示响应信息给客户端。
SpringMVC
SpringMVC是一种基于MVC模式的轻量级Web框架,也就是说它可以用来接收客户端请求,拿到参数,经过处理之后,返回数据模型和视图,渲染之后返回响应给客户端。
提供了构建Web应用程序的全功能MVC模块,在使用Spring框架开发Web应用程序时,选择SpringMVC框架是一种很好的选择,当然,也可以选择其他MVC框架如Struts2,但是SpringMVC是目前主流的MVC框架之一。
SpringMVC的优点:
(1)清晰的角色划分:有前端控制器、处理器映射器、处理器适配器、视图解析器、处理器或页面控制器、验证器等,基于这些模块开发,请求依次经过这些模块处理之后,一个请求到响应就处理完整了
(2)分工明细
(3)和Spring空间无缝集成
SpringMVC和Struts2优劣分析:
共同点:
(1)都是表现层框架,都是基于MVC模型编写的
(2)底层都依赖ServletAPI
(3)都有个核心控制器用于整个功能模块的调度,只不过SpringMVC是Servlet,Struts2是Filter
区别:
(1)SpringMVC的入口是Servlet,Struts2是Filter
(2)SpringMVC是基于方法设计的,而Struts2是基于类的,Struts2每次处理请求都会创建一个相关类对象,它是多例的,而SpringMVC是单例的,请求用方法处理就行,所以SpringMVC比Struts2稍微快点
(3)SpringMVC编码更加简洁,支持JSR303(JSR303是JavaBean参数的校验标准,定义了很多常用的校验注解,我们可以直接将这些注解加在我们的JavaBean的属性上,就可以在需要校验的时候进行校验了),处理ajax方便
使用
pom.xml的基本配置:
<properties>
<!--锁定编译器版本和spring版本-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
在src/main下创建目录 java,并设置为源码路径
在src/main下创建目录resources,并设置为资源路径
配置web.xml
<!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>
<!--配置前端控制器
url-pattern为“/”,即发任何请求都会经过这个前端控制器
当第一次发请求的时候创建servlet类对象,配置load-on-startup表示服务启动的时候创建servlet类对象
-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--让前端控制器加载springmvc.xml-->
<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>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
在resources目录下创建文件springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解扫描-->
<context:component-scan base-package="cn.ith" />
<!--配置视图解析器对象
当控制器中的页面跳转的时候,视图解析器就会帮助程序跳转到指定页面
-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
</bean>
<!--开启springmvc框架注解的支持-->
<mvc:annotation-driven/>
</beans>
在java目录下创建包,并且创建HelloController控制器:
package cn.ith.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping(path="/hello")
public String sayHello() {
System.out.println("hello");
return "success"; //返回success.jsp页面
}
}
在WEB-INF下创建pages目录,并创建success.jsp文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
成功
</body>
</html>
将webapp下的index.jsp文件内容改为:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="hello">入门程序</a>
</body>
</html>
配置IDEA集成Tomcat
配置完毕,运行
流程总结
1 启动服务器,加载配置文件
因为在web.xml中配置了<load-on-startup>1</load-on-startup>
,因此当服务器启动的时候,就会创建servlet类对象。然后根据配置<param-value>classpath:springmvc.xml</param-value>
去加载springmvc.xml配置文件。
在springmvc.xml中配置了注解的扫描包名,这样,打上了@Controller注解的HelloController类对象就会被放入IOC容器中。
因为在springmvc.xml中配置了视图解析器,因此视图解析器类InternalResourceViewResolver也会被实例化成对象放入IOC容器中,当控制器中的页面跳转的时候,视图解析器对象就能工作了。
在springmvc.xml中配置开启springmvc框架注解的支持,因此@RequestMapping注解也会生效,当请求XXX/hello的时候,就会执行sayHello方法。
2 发送请求,后台处理请求
当点击index.jsp超链接标签的时候,会发送请求,接下来:
(1)首先是执行servlet中的程序,web.xml中的配置<url-pattern>/</url-pattern>
表明拦截所有请求
(2)servlet类DispatcherServlet相当于指挥中心,根据发来的XXX/hello中的hello匹配到sayHello方法,然后执行该方法
(3)sayHello方法执行完返回"success",由于在springmvc.xml中配置了视图解析器InternalResourceViewResolver
,因此DispatcherServlet指挥中心去找到视图解析器,视图解析器会帮助Web应用程序将页面跳转到success.jsp
(4)servlet把请求响应给客户端,客户端看到最终的页面
流程图如下:
SpringMVC框架中的组件
SpringMVC框架是基于组件方式执行流程的,基本组件如下:
- 前端控制器(DispatcherServlet)
控制整个流程的执行,相当于MVC中的C。DispatcherServlet是整个流程的控制中心,由它调用其它组件处理应用请求。 - 处理器映射器(HandlerMapping)
DispatcherServlet需要将请求发送给SpringMVC的控制器(Controller),由控制器处理请求。程序中可能会有多个控制器,DispatcherServlet需要知道应该将请求发送给那个控制器。所以DispatcherServlet会以查询一个或或者处理器映射器(HandlerMapping)来确定请求的下一站在哪里。处理器映射器会根据请求所携带的URL信息来进行决策。 - 处理器适配器(HandlerAdapter)和Handler处理器(即控制器)
处理器适配器使用的是设计模式中的适配器模式,通过该适配器,可以执行任意的Controller方法。一旦处理器映射器选择了合适的控制器,DispatcherServlet会将请求发送给处理器适配器,然后交给Handler处理器处理请求。
控制器完成逻辑处理后,通常会产生一些信息,这些信息需要返回给用户并在浏览器上显示。这些信息被称为模型(Model)。不过仅仅给用户返回原始信息是不够的——这些信息需要以用户友好的方式进行格式化,一般会是HTML。所以,信息需要发送给一个视图(View),通常会是JSP。
控制器所做的最后一件事就是将模型数据打包,并且标示出用于渲染输出的视图名。它接下来会将请求连同模式和视图名(ModelAndView)发送回DispatcherServlet。 - 视图解析器(ViewResolver)
传递给DispatcherServlet的视图名并不直接表示某个特定的JSP。实际上,它甚至并不能确定视图就是JSP。相反,它仅仅传递了一个逻辑名称,这个名字将会用来查找产生结果的真正视图。DispatcherServlet将会使用视图解析器来将逻辑视图名匹配为一个特定的视图实现。
如你在Controller的某个方法中写上
return "index";
,这个index就是视图名,根据你的配置,这个视图名会被解析为实际的视图,比如你在xml中做了如下配置:
<property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp"/>
,则视图解析器会将视图对应到/WEB-INF/pages/index.jsp
- 视图
既然DispatcherServlet已经知道有哪个视图渲染结果,那请求的任务基本上也就完成了。请求的最后一站是视图的实现(可能是JSP、pdf、excel等),在这里它交付模型数据。请求的任务完成了。视图将使用模型数据渲染输出,这个输出会通过响应对象传递给客户端。
处理器映射器、处理器适配器、视图解析器是SpringMVC中的三大组件,springmvc.xml中配置的<mvc:annotation-driven/>
就相当于配置了这些组件。
图解如下: