1.基本概念
1.1三层架构
三层架构也就是我们常说的b/s架构中的表现层,业务层和持久层,每层都各司其职,下面来分别讲解这三层的作用。
表现层:
也就是我们常说的web层。它负责接收客户端的请求,向客户端响应结果,通常客户端向web层发送HTTP请求,web层需要接收HTTP请求。表现层包含展示层和控制层,控制层负责接收前端请求,展示层负责结果的展示。表现层依赖业务层,接收到客户端请求一般会调用业务层进行业务处理,并将处理结果响应给客户端。表现层的设计一般都使用MVC模型。
业务层:
也就是我们常说的service层。它负责业务逻辑的处理,和我们开发项目的需求息息相关。web层依赖业务层,但是业务层不依赖web层。业务层在业务处理是可能会依赖持久层。
持久层:
也就是我们常说的dao层。负责数据持久化,包括数据层即数据库和数据访问层。数据库是对数据进行持久化的载体,数据访问层是业务层和持久层的接口,业务层需要通过对数据访问层将数据持久化到数据库中,通俗的讲,持久化就是和数据库交互,对数据库进行增删改查的。
1.2MVC架构
MVC全名是Model View Controller.是模型(Model) 视图(view) 控制器 (controller)的缩写。
是一种用于创建web应用程序表现层的模式。
MVC中每个部分各司 其职:
Model(模型):
通常指的就是我们的数据模型,用来封装数据的。
View(视图):
通常指的是我们的jsp或者html。一般用来展示数据的,通常视图是依据模型数据创建的。
Controller(控制器):
是应用程序中处理用户交互的部分。用于接收前端请求。比如获取前端请求传递的参数并负责将请求交给业务层进行处理。业务层将业务结果处理完成以后,控制器接收业务 层的业务结果,并将业务数据存储在域对象,实现页面的跳转。
1.3什么是SpringMVC
SpringMVC是一种基于Java的实现MVC设计模型的请求驱动类型的轻量级web框架, 属于Spring FrameWork的后续产品,已经融合在Spring Web Flow里面。Spring框 架提供了构建web应用程序的全功能MVC模块。使用Spring可插入的MVC架构,从而在使用 Spring进行web开发时,可以选择使用Spring的Spring MVC框架或集成其他MVC开发框 架,比如Struts2等。
他其实就是基于servelet进行封装的一个框架。
SpringMVC已经成为目前最主流的MVC框架之一,并且随着Spring 3.0的发布,全 面超越Struts2,成为最优秀的web框架。它通过一套注解,让一个简单的Java类成为处理 请求的控制器,而无需事先任何接口,同时它还支持Restful编程风格
1.4SpringMVC的优势
1. 清晰的角色划分: 前端控制器(DispatcherServlet) 处理器映射器(HandlerMapping) 处理器适配器(HandlerAdpater) 视图解析器(ViewResolver) 控制器(Controller) 验证器(Validator) 命令对象(Command 请求参数绑定到的对象就叫做命令对象) 表单对象(Form Object 提供给表单展示和提交的对象就叫表单对象)
2. 分工明确,而且扩展点相当灵活,很容易进行功能扩展。
3. 由于命令对象就是一个POJO,无需继承框架特定的API,可以使用命令对象直接作为业 务对象。 4. 和Spring其他框架无缝集成,是其他web框架不具备的。
5. 可适配,通过HandlerAdapter可以支持任意的类作为处理器。
6. 可定制性,HandlerMapping ViewResolver等能够非常简单的定制。
7. 功能强大的数据验证、格式化、绑定机制。
8. 利用Spring提供的Mock对象能够非常简单的进行web层单元测试。
9. 本地化、主题的解析支持,使我们更容易进行国际化和主题的切换。
10. 强大的JSP标签库,使JSP编写更容易。 还有比如RESTFUL风格的支持,简单的文件上传、约定大于配置的契约式编程风格,基于注 解的零配置支持等。
2.SpringMVC入门环境的搭建
首先使用maven创建一个web项目(基于骨架创建)
然后pom.xml文件中导入相关依赖
<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/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.xq</groupId><artifactId>xq-springmvc-project</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>springmvc-project-quickstart</artifactId><packaging>war</packaging><name>springmvc-project-quickstart Maven Webapp</name><url>http://maven.apache.org</url>
<properties>
<spring.verion>5.0.2.RELEASE</spring.verion>
</properties>
<dependencies>
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.verion}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.verion}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.verion}</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><!--配置tomcat7插件-->
<build><finalName>springmvc-project-quickstart</finalName>
<plugins><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.2</version><configuration><path>/</path><port>8088</port><uriEncoding>UTF-8</uriEncoding></configuration></plugin>
</plugins>
</build>
</project>
至于用什么版本倒是无所谓,可以选更高的。
接着在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><servlet><servlet-name>SpringMVCDispatcherServlet</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><!-- 配置 servlet 的对象的创建时间点:应用加载时创建。
取值只能是非 0 正整数,表示启动顺序 --><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>SpringMVCDispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping></web-app>
<servlet-name>:为 Servlet 定义一个唯一的名称,这里是 SpringMVCDispatcherServlet,后续在 <servlet-mapping> 中会使用这个名称来映射 URL。
<servlet-class>:指定 Servlet 的全限定类名,这里使用的是 Spring MVC 的核心 Servlet org.springframework.web.servlet.DispatcherServlet。DispatcherServlet 是 Spring MVC 的前端控制器,负责接收所有的 HTTP 请求,并将请求分发给相应的处理器进行处理。
<init-param>:用于配置 Servlet 的初始化参数。
<param-name>:参数名称,这里是 contextConfigLocation,表示要指定 Spring MVC 的配置文件位置。
<param-value>:参数值,classpath:springmvc.xml 表示从类路径下加载 springmvc.xml 文件作为 Spring MVC 的配置文件。
<load-on-startup>:指定 Servlet 的加载顺序。取值为非 0 正整数,数值越小,Servlet 会越早被加载。这里设置为 1,表示在 Web 应用启动时就创建并初始化这个 Servlet。
<servlet-name>:指定要映射的 Servlet 的名称,这里要与前面 <servlet> 元素中定义的 servlet-name 一致,即 SpringMVCDispatcherServlet。
<url-pattern>:指定 Servlet 要处理的 URL 模式。/ 表示将所有的 HTTP 请求都映射到 SpringMVCDispatcherServlet 进行处理。
然后编写springmvc.xml文件
<?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/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"><!-- 配置创建 spring 容器要扫描的包 --><context:component-scan base-package="com.xq"></context:component-scan><!-- 配置视图解析器 --><bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/pages/"></property><property name="suffix" value=".jsp"></property></bean><!--开启springmvc注解支持--><mvc:annotation-driven></mvc:annotation-driven></beans>
接着在webapp的pages(自己创建)目录下,编写success.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head><title>Title</title></head><body><h2>欢迎你。这是一个成功页面</h2></body></html>
最后编写控制器代码
@Controllerpublic class HelloController {@RequestMapping("/hello")public String sayHello(){System.out.println("hello,springmvc");return "success";}}
编写控制器代码,用于接收前端发送的请求,并进行页面的跳转。
整体项目结构如下
2.1入门程序分析
首先来看SpringMVC的执行流程
具体执行步骤如下
第一步:发起请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求HandlerMapping查找 Handler (可以根据xml配 置、注解进行查找)
第三步:处理器映射器HandlerMapping向前端控制器返回Handler, HandlerMapping会把请求映射为HandlerExecutionChain对象(包含一个 Handler处理器(页面控制器)对象,多个HandlerInterceptor拦截器对 象),通过这种策略模式,很容易添加新的映射策略
第四步:前端控制器调用处理器适配器去执行Handler
第五步:处理器适配器HandlerAdapter将会根据适配的结果去执行 Handler
第六步:Handler执行完成给适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndView (ModelAndView是springmvc框架的一个底层对象,包括 Model和 view)
第八步:前端控制器请求视图解析器去进行视图解析 (根据逻辑视图名解 析成真正的视图(jsp)),通过这种策略很容易更换其他视图技术,只需要更 改视图解析器即可
第九步:视图解析器向前端控制器返回View
第十步:前端控制器进行视图渲染 (视图渲染将模型数据(在 ModelAndView对象中)填充到request域)
第十一步:前端控制器向用户响应结果
2.2SpringMVC核心组件
DispatcherServlet 前端控制器
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求, dispatcherServlet 的存在降低了组件之间的耦合性。
HandlerMapping 处理器映射器
HandlerMapping负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口 方式,注解方式等。
Handler 处理器
它就是我们开发中要编写的具体业务控制器。由DispatcherServlet 把用户 请求转发到 Handler。由Handler对具体的用户请求进行处理。
HandlAdapter 处理器适配器
通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩 展适配器可以对更多类型的处理器进行执行。
ViewResolver 视图解析器
View Resolver负责将处理结果生成View 视图,View Resolver首先根据逻 辑视图名解析成物理视图名即具体的页面地址,再生成 View视图对象,最 后对View进行渲染将处理结果通过页面展示给用户。
View 视图
SpringMVC框架提供了很多View视图类型的支持,包括:jstlView、 freemarkerView、pdfView等。我们最常用的视图就是jsp。一般情况下需 要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程 序员根据业务需求开发具体的页面。
2.3RequestMapping注解的使用
作用:用于建立请求URL和处理请求方法之间的对应关系
它可以作用在类上(用于请求URL的第一级访问目录),也可以作用在方法上(用于请求URL的第二级访问目录).
相关属性:
value:描述的是请求资源的URL路径.它和path属性的作用是一样的.
method:用于指定请求的方法,例如GET,POST方法
params:用于指定限制请求参数的条件
如果括号里只有一个属性,如果不指定具体的属性,那么默认就是value.
使用示例
@Controller
@RequestMapping("demo1")
public class HelloController{
@requestMapping("/hello")
public String sayHello(){
System.out.println("hello")
return "success";}
}
那么此时我们的访问路径应该是localhost:8088/demo1/hello
这里的'/'可要可不要
不知道有人会不会有点疑惑,为什么注解既可以放在方法上,又可以放在类上,为什么都不直接放在方法上,就不用放在类上了.
就像这里,三个模块都用一样的注解,这样在进行资源定位时就不知道到底是哪个模块的,所以要在每个类上面再分别加上注解来区分
变成这样就行了
再具体讲一下params
当它只指定了参数名时,只需要再路径名中加上该参数并给它赋值即可成功访问该方法,例如
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;@Controller
public class ParamController {@RequestMapping(value = "/test", params = "param1")@ResponseBodypublic String handleRequest() {return "Request contains param1";}
}
这里的访问路径就需要再在请求text 路径时包含 param1
参数,handleRequest
方法才会被调用。例如,/test?param1=value
会匹配该方法,但 /test
不会匹配。
它也可以给该参数限定范围,例如params="params=a",那么在请求时必须在写成/text?paraml=a才行
他也可以限定成params!="a",就是表示只要不等于a的值填上去就行
2.4请求参数绑定
我们都知道,用户请求参数都是基于key=value的。SpringMVC绑定请求参数的过程是通过把请求提交的参数,作为控制器中的方法参数进行绑定.
Springmvc支持的参数绑定类型:
基本类型参数: 包括基本类型和String类型
POJO类型参数:包括实体类及其关联的实体类
数组和集合类型的参数:包括List和Map结构的集合(包括数组)
SpringMVC绑定请求参数是自动实现的,但是使用必须遵循器使用要求:
如果是基本类型或者String类型: 要求我们的参数名称必须和控制器方法中 的形参名称保持一致,并严格区分大小写。
如果是POJO类型,或者其他关联对象:要求表单中的参数名称和POJO类的 属性名称一模一样,并且控制器方法的参数类型是POJO类型。
下面以基本参数类型为例
先编写一个超链接
<a href="${pageContext.request.contextPath}/demo1/getBasicParam?username=eric">[提交基本数据类型的参数]</a>
然后编写控制器方法
@Controller@RequestMapping("demo1")public class HelloController {@RequestMapping("getBasicParam")public String getBasicParam(String username){System.out.println("username: " + username);return "success";}
}
控制器会捕捉前端传过来的参数,用的是控制器下的方法来捕捉,这里的方法就是捕捉了String类型的参数。这里不仅要保持参数的类型保持一致,还要保持参数的名称保持一致才能被自动绑定,不然就要采取其他方法来实现。