1.SpringMVC简介
1.1、什么事MVC
MVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分
M:Model,模型层,指工程中的JavaBean,作用是处理数据
JavaBean分为两类:
- 一类称为实体类Bean:专门存储业务数据的,如 Student、User 等
- 一类称为业务处理 Bean:指 Service 或 Dao 对象,专门用于处理业务逻辑和数据访问。
V:View,视图层,指工程中的html或jsp等页面,作用是与用户进行交互,展示数据
C:Controller,控制层,指工程中的servlet,作用是接收请求和响应浏览器
MVC的工作流程: 用户通过视图层发送请求到服务器,在服务器中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕将结果返回到Controller,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器
1.2、什么是SpringMVC
SpringMVC是spring的一个后续产品,是Spring的一个子项目
SpringMVC 是 Spring 为表述层(表述层包含前台页面和servlet)开发提供的一整套完备的解决方案。在表述层框架历经 Strust、WebWork、Strust2 等诸多产品的历代更迭之后,目前业界普遍选择了 SpringMVC 作为 Java EE 项目表述层开发的首选方案。
注:三层架构分为表述层(或表示层)、业务逻辑层、数据访问层,表述层表示前台页面和后台
servlet
1.3、SpringMVC的特点
- Spring 家族原生产品,与 IOC 容器等基础设施无缝对接
- 基于原生的Servlet,通过了功能强大的前端控制器DispatcherServlet,对请求和响应进行统一
处理 - 表述层各细分领域需要解决的问题全方位覆盖,提供全面解决方案
- 代码清新简洁,大幅度提升开发效率
- 内部组件化程度高,可插拔式组件即插即用,想要什么功能配置相应组件即可
- 性能卓著,尤其适合现代大型、超大型互联网项目要求
1.4、创建一个简单项目
- 普通的maven项目只是一个java项目,没有web目录
- 在pom文件中设置打包方式为war包
创建完成的工程路径
- 引入依赖
<dependencies>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- ServletAPI -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Spring5和Thymeleaf整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
</dependencies>
- 配置web.xml
<!-- 配置springMVC的前端控制器DispatcherServlet-->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<!-- url-pattern中/和/*的区别
/表示匹配浏览器向服务器发送的所有请求(不包括.jsp结尾的请求)
/*表示匹配浏览器向服务器发送的所有请求(包括.jsp结尾的请求)
DispatcherServlet无法处理jsp的请求
jsp的执行原理:先把jsp翻译成一个servlet,访问这个servlet把jsp页面中的所有内容以响应的方式响应到浏览器,才能看到这个页面
.jsp的请求是通过tomcat中的原生servlet访问的,tomcat的web.xml文件中配置了专门的jsp的servlet
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
5. 创建请求控制器
6. 创建SpringMVC的配置文件
配置SpringMVC的配置文件默认的位置和名称:
- 位置 WEB-INF下
- 名称:<servlet-name>-servlet.xml 当前配置下的配置文件名为springMVC-servlet.xml但是我们不会把配置文件放在WEB-INF下,要放置在resources下,这里只是测试一下,会放在WEB-INF下
<context:component-scan base-package="com.tdh.springmvc"/>
<!-- 配置Thymeleaf视图解析器 -->
<bean id="viewResolver"
class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean
class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
配置好tomcat后,运行,成功运行
注意配置在WEB-INF下的html都是被保护的,浏览器上无法直接访问,只能通过服务器进行跳转,就像上面这种条件方式。
- 在index页面中创建两个超链接
点击超链接,发现测试绝对路径的超链接无法跳转
总结:
浏览器发送请求,若请求地址符合前端控制器的url-pattern,该请求就会被前端控制器DispatcherServlet处理。前端控制器会读取SpringMVC的核心配置文件,通过扫描组件找到控制器,将请求地址和控制器中@RequestMapping注解的value属性值进行匹配,若匹配成功,该注解所标识的控制器方法就是处理请求的方法。处理请求的方法需要返回一个字符串类型的视图名称,该视图名称会被视图解析器解析,加上前缀和后缀组成视图的路径,通过Thymeleaf对视图进行渲染,最终转发到视图所对应页面
1.5、如果springmvc的配置文件不想放在WEB-INF下而是resources下,就需要如下配置
然后将springmvc的配置文件放在resources下即可
1.6、配置DispatcherServlet时候的load-on-startup标签的作用
Servlet默认的初始化是在第一次访问的时候进行的,而DispatcherServlet在进行初始化的时候又进行了很多的操作,所以会导致第一次请求服务器响应的时候会花费很长的时间,使用load-on-startup标签设置以后,可以让服务器在启动的时候就初始化DispatcherServlet这样可以减少第一次访问服务器的时候所花费的时间
2.@RequestMapping注解
2.1、@RequestMapping注解的功能
从注解名称上我们可以看到,@RequestMapping注解的作用就是将请求和处理请求的控制器方法相关联起来,建立映射关系,SpringMVC 接收到指定的请求,就会来找到在映射关系中对应的控制器方法来处理这个请求。
2.2@RequestMapping注解的位置
- @RequestMapping标识一个类:设置映射请求的请求路径的初始信息
- @RequestMapping标识一个方法:设置映射请求请求路径的具体信息
@Controller
@RequestMapping("/test")
public class RequestMappingController {
//此时请求映射所映射的请求的请求路径为:/test/testRequestMapping
@RequestMapping("/testRequestMapping")
public String testRequestMapping(){
return "success";
}
}
2.3、@RequestMapping注解的value属性
-
@RequestMapping注解的value属性通过请求的请求地址匹配请求映射
-
@RequestMapping注解的value属性是一个字符串类型的数组,表示该请求映射能够匹配多个请求地址所对应的请求
-
@RequestMapping注解的value属性必须设置,至少通过请求地址匹配请求映射
2.4 @RequestMapping注解的method属性
-
@RequestMapping注解的method属性通过请求的请求方式(get或post)匹配请求映射
-
@RequestMapping注解的method属性是一个RequestMethod类型的数组,表示该请求映射能够匹配
多种请求方式的请求
-
若当前请求的请求地址满足请求映射的value属性,但是请求方式不满足method属性,则浏览器报错
405:Request method ‘POST’ not supported
注:
1、对于处理指定请求方式的控制器方法,SpringMVC中提供了@RequestMapping的派生注解
处理get请求的映射-->@GetMapping
处理post请求的映射-->@PostMapping
处理put请求的映射-->@PutMapping
处理delete请求的映射-->@DeleteMapping
2、常用的请求方式有get,post,put,delete
但是目前浏览器只支持get和post,若在form表单提交时,为method设置了其他请求方式的字符
串(put或delete),则按照默认的请求方式get处理
若要发送put和delete请求,则需要通过spring提供的过滤器HiddenHttpMethodFilter,在
RESTful部分会讲到
2.5 @RequestMapping注解的params属性(了解)
- @RequestMapping注解的params属性通过请求的请求参数匹配请求映射
- @RequestMapping注解的params属性是一个字符串类型的数组,可以通过四种表达式设置请求参数
和请求映射的匹配关系 - “param”:要求请求映射所匹配的请求必须携带param请求参数
- “!param”:要求请求映射所匹配的请求必须不能携带param请求参数
- “param=value”:要求请求映射所匹配的请求必须携带param请求参数且param=value
- “param!=value”:要求请求映射所匹配的请求必须携带param请求参数但是param!=value
2.6 @RequestMapping注解的Header属性(了解)
- @RequestMapping注解的headers属性通过请求的请求头信息匹配请求映射
- @RequestMapping注解的headers属性是一个字符串类型的数组,可以通过四种表达式设置请求头信息和请求映射的匹配关系
“header”:要求请求映射所匹配的请求必须携带header请求头信息
“!header”:要求请求映射所匹配的请求必须不能携带header请求头信息
“header=value”:要求请求映射所匹配的请求必须携带header请求头信息且header=value
“header!=value”:要求请求映射所匹配的请求必须携带header请求头信息且header!=value
若当前请求满足@RequestMapping注解的value和method属性,但是不满足headers属性,此时页面
显示404错误,即资源未找到
2.7、SpringMVC支持ant风格的路径
?:表示任意的单个字符
*:表示任意的0个或多个字符
**:表示任意层数的任意目录
注意:在使用**时,只能使用/**/xxx的方式,两个星的前后不能有任何字符
2.8、SpringMVC支持路径中的占位符(重点)
- 原始方式:/deleteUser?id=1
- rest方式:/deleteUser/1
SpringMVC路径中的占位符常用语RESTful风格中,当请求路径综中将某些数据通过路径的方式传输到服务器上,就可以在相应的@RequestMapping注解的value属性中通过占位符(xxx)表示传输的数据,在通过@PathVariable注解,将占位符所表示的数据赋值给控制器方法的形参
3.SpringMVC获取请求参数
3.1、 通过ServletAPI获取(不常用)
- 在前端页面写一个form表单
- 在后端Controller层中使用ServletAPI接受参数
3.2、 通过控制器方法的形参获取(常用)
- 写一个前端form表单
- 在后端写控制器方法
- 前端输入框输入以后提交,后端能够获取到参数
- 当传递的参数名与控制器方法形参的方法名称不一样时,可以使用@RequestParam注解,该注解的参数
- required 表示这个参数是必须要传输的,如果前端没有传输这个形参会直接报错,默认是true,当设置成为false时,前端如果没有传递这个参数,后端使用默认值null
- defaultValue设置默认值,如果没有接收到这个参数就使用这个默认值
与@RequestParam相类似功能的参数还有@RequestHeader和@CookieValue,都有required属性和defaultValue属性
-
@RequestHeader将请求头信息和控制器方法的形参绑定
-
@CookieValue将Cookie数据和控制器方法的形参绑定
3.3、 通过控制器方法的pojo获取参数(常用)
- 创建一个pojo对象
- 在前端写一个form表单用于提交测试参数
- 在后端控制器创建方法接收参数
注意:需要确保实体类中的属性名与要获取的参数的名字一致才行
4.解决获取请求参数的乱码问题
在web.xml中设置spring自带的过滤器
<!-- 配置spring编码过滤器 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<!-- spring提供的过滤器-->
<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>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
源码
springmvc中处理编码的过滤器一定要配置在其他过滤器之前,否则无效
5.域对象共享数据
5.1、 使用ServletAPI向request域对象共享数据
5.2、使用ModelAndView向request域对象共享数据(不管使用什么方式实现都是在底层封装成了一个ModelAndView对象)
- 前端页面中
- 后端controller层中方法
- 在success页面中获取到当前的值
5.3、使用Model向request域对象共享数据
-
前端页面中
-
后端controller层中方法
-
在success页面中获取到当前的值
5.4、使用ModelMap向request域对象共享数据
-
前端页面中
-
后端controller层中方法
-
在success页面中获取到当前的值
5.5、使用Map向request域对象共享数据
-
前端页面中
-
后端controller层中方法
-
在success页面中获取到当前的值
Model和ModelMap和Map的关系
其实在底层中,这些类型的形参最终都是通过BindingAwareModelMap创建的
public class BindingAwareModelMap extends ExtendedModelMap
public class ExtendedModelMap extends ModelMap implements Model
public class ModelMap extends LinkedHashMap<String, Object>
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
5.6、向session域共享数据
-
前端页面中
-
后端controller层中方法
-
在success页面中获取到当前的值
有效期,浏览器开启到浏览器关闭
5.7、向application域共享数据
-
前端页面中
-
后端controller层中方法
-
在success页面中获取到当前的值
有效期在服务器关闭之前
6.SpringMVC的视图
SpringMVC中的视图是View接口,视图的作用渲染数据,将模型Model中的数据展示给用户
SpringMVC视图的种类很多,默认有转发视图和重定向视图
当工程引入jstl的依赖,转发视图会自动转换为JstlView
若使用的视图技术为Thymeleaf,在SpringMVC的配置文件中配置了Thymeleaf的视图解析器,由此视图解析器解析之后所得到的是ThymeleafView
- forward转发视图,创建的是InternalResourceView
2.redirect重定向视图,创建的是RedirectView,为我们当前设置的绝对路径上自动加上上下文路径
6.1 视图控制器view-controller
在控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理方法使用view-controller标签来表示
启动程序,发现成功跳转了
此时再点其他链接,发现均报错,无法跳转,原因是:SpringMVC中设置任何一个view-controller时,其他控制器中的请求映射将全部失效,此时需要在Springmvc的核心配置文件中设置开启mvc注解驱动的标签
<mvc:annotation-driven />
设置完成以后发现成功跳转
7. RESTful
7.1、RESTful简介
REST:Representational State Transfer,表现层资源状态转移。
- 资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源组成。每个资源是服务器上一个可命名的抽象概念。因为资源是一个抽象的概念,所以它不仅仅能代表服务器文件系统中的一个文件、数据库中的一张表等等具体的东西,可以将资源设计的要多抽象有多抽象,只要想象力允许而且客户端应用开发者能够理解。与面向对象设计类似,资源是以名词为核心来组织的,首先关注的是名词。一个资源可以由一个或多个URI来标识。URI既是资源的名称,也是资源在Web上的地址。对某个资源感兴趣的客户端应用,可以通过资源的URI与其进行交互。
- 资源的表述是一段对于资源在某个特定时刻的状态的描述。可以在客户端-服务器端之间转移(交换)。资源的表述可以有多种格式,例如HTML/XML/JSON/纯文本/图片/视频/音频等等。资源的表述格式可以通过协商机制来确定。请求-响应方向的表述通常使用不同的格式。
- 状态转移说的是:在客户端和服务器端之间转移(transfer)代表资源状态的表述。通过转移和操作资
源的表述,来间接实现操作资源的目的。
7.2、RESTful的实现
- 重新创建一个项目spring_mvc_rest
- 创建如下目录
- 在controller层中使用rest风格实现获取前端数据
- 在前端写post请求用于存储数据
- 在controller层中写方法使用rest风格保存数据
- 如何使用put请求实现修改,form表单中的method只有post和get,这里我们强硬设置为put
- 在后端写对应的方法测试一下,发现控制台打印的并不是这个方法所对应的sout,而是查询所有用于对应的sout,并且请求方便匹配成了get请求
- 解决这个问题,在web.xml文件中写入一个hiddenHttpMethodFilter过滤器,一定要写在解决乱码问题过滤器的下面
前端界面
后端
发现成功了
总结:
若要发送put和delete请求,需要在web.xml中配置一个过滤器HiddenHttpMethodFilter
配置过滤器之后,发送的请求要满足两个条件,才能将请求方式转换为put和delete
- 当前请求必须为post
- 当期请求必须传输请求参数_method,值是put或者delete
- 测试delete方法
运行程序,发现成功
- 看过HiddenHttpMethodFilter滤器源码
- 之所以这个过滤器必须配置在处理乱码问题过滤器之后,是因为处理乱码过滤器之前不能获取请求参数,而HiddenHttpMethodFilter过滤器中获取了_method的请求参数,也就能够获取到其他的请求参数,所以解决乱码的过滤器效果无法实现
处理静态资源,在springmvc的配置文件中加如下代码
回顾axios
8. springMVC处理ajax请求
- 前端
- 后端
- 前端
8.1、 @RequestBody
将请求体中的内容和控制器方法的形参进行绑定
使用@RequestBody注解将json格式的请求参数转换为java对象
- 导入jackson的依赖,默认使用的是这个去处理json数据
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.1</version>
</dependency>
- 在springmvc的配置文件中设置<mvc:annotation-driven/>
- 在处理请求的控制器方法的形参位置,直接设置json格式的请求参数要转换的java类型的形参,使用@RequestBody注解标识即可
使用map集合也可以
8.2、 @RsponseBody
将所标识的控制器方法的返回值作为响应报文的响应体响应到浏览器
- 前端
- 后端
- 前端
使用ajax请求接受后端传递的数据 - 前端
- 后端
- 前端
8.3、 @RestController注解
@RestController注解是SpringMVC提供的一个复合注解,标识在控制器的类上,就相当于为类添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解
9、文件上传和下载
9.1、 文件下载
@RequestMapping("/test/down")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("img");
// File.separator当不知道文件路径使用什么分割符的时候就使用这个,这个可以自动匹配不同系统的分隔符
realPath=realPath+ File.separator+"7.jpg";
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组 is.available()获取输入流所对应文件的字节数
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字 Content-Disposition固定的 attachment;filename=固定的
headers.add("Content-Disposition", "attachment;filename=1.jpg");
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers,
statusCode);
//关闭输入流
is.close();
return responseEntity;
}
9.2、 文件上传
- 前端
- 后端
- 引入文件上传依赖
<!-- 文件上传依赖-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
- 在springmvc配置文件中创建文件上传解析器
- 在后端这样接收数据
- 实现上传文件
- 上传文件的位置
9.3、 解决文件名字重复问题
当文件名字重复的时候,会将原来文件的内容替换掉,不是覆盖了文件,而是将其中的内容替换掉了
10、拦截器
10.1、拦截器
SpringMVC中的拦截器用于拦截控制器方法的执行
SpringMVC中的拦截器需要实现HandlerInterceptor
SpringMVC的拦截器必须在SpringMVC的配置文件中华进行配置
配置一个简单的拦截器测试一下
- 前端
- 后端
- 创建一个类实现简单的功能
- 在springmvc中使用mvc:interceptors进行配置
- 第一种配置方式
- 第二种配置方式
- 第三种配置方式
- 第一种配置方式
- 当prehandel中的返回值是false时,会阻塞下面程序的执行
会发现只有preHandle中的输出了,并且页面显示为空白
- 当preHandel中的返回值是false的时候
发现程序能够正常运行,三个方法中的输出都被打印在了控制台上吗,并且页面也能够显示
- 上面的配置都是对所有的DispatcherServlet处理的请求都生效
<!-- bean和ref标签所配置的拦截器默认对DispatcherServlet处理的所有请求进行拦截-->
- 下面的配置方式,可以个性化的设置拦截器在哪些地方生效,注意/*和/**的区别
10.2、 当有多个拦截器时,拦截器方法的执行顺序
发现除了preHandle方法以外另外两种方法都是反着执行的
当将springmvc中的拦截器配置顺序更改
证明有多个拦截器时,拦截器执行的方法和配置文件中配置拦截器的顺序有关系,preHandel会按照配置的顺序执行,而postHandle 和afterCompletion会按照配置的相反顺序去执行
10.3、如果有一个拦截器的preHandle方法返回的是false
若拦截其中某个拦截器的preHandle方法返回了false,
拦截器的preHandle返回false和它之前的拦截器preHandel都会执行。当前所有的拦截器的postHandle都不会执行,拦截器的preHandler返回false之前的拦截器的afterCompletion会执行
11、异常处理器
DefaultHandlerExceptionhResolver是springmvc默认的异常处理解析器
SimpleMappingExceptionResolver是我们自己可以自定义的异常处理
11.1、基于配置文件的异常处理类
11.2、基于注解的异常处理类
12、SSM整合
12.1、ContextLoaderListener
Spring和SpringMVC均提供了ioc容器,其中Spring中负责管理service组件,SpringMVC中负责管理Controller组件,因为Controller组件中要自动装配Service组件,所以Spring的容器一定要比SpringMVC容器创建的早,SpringMVC容器的创建是在DispatcherServlet初始化的时候创建的,所以Spring的ioc容器要在DispatcherServlet初始化之前创建,DispatcherServlet配置的时候加了一个load-on-startup为1,所以DispatcherServlet初始化就是在服务器启动的时候完成的。监听器是最早被执行的,其次是过滤器,最后是servlet。过滤器作用的过滤目标资源,而servlet就是服务器中的资源,所以过滤器也是在servlet之前执行。所以我们可以将获取spring的ioc容器的代码,放在监听器或者过滤器中。过滤器的功能是过滤请求和响应,我们不能为了实现一个功能,就忽略了他最原始的意义。这里使用监听器。默认的监听器有三种,第一种ServletContextListener来监听ServletContext的状态,第二种是HttpSessionListener,第三个HttpSessionAttributeListener,后两个都是监听httpSession的状态的。我们一般使用的是ServletContextListener,里面有两个方法,一个是ServletContext初始化方法,一个是ServletContext销毁方法。初始化负责监听服务器的启动,销毁方法负责监听服务器的销毁。Spring已经为我们创建好了应对Spring的ioc创建的监听器交ContextLoaderListener,实现ServletContextListener接口,可监听ServletContext的状态,在web服务器的启动,读取Spring的配置文件,创建Spring的IOC容器。web应用中必须在web.xml中配置。监听器中的初始化方法只会执行一次,并且是在服务器启动时最先执行的。
在web.xml中进行配置
Spring和Springmvc的容器是有父子关系的,Spring是父容器,Springmvc是子容器,父容器不能访问子容器中的bean,子容器可以访问父容器中的bean
12.2、准备工作
- 创建MavenModule
- 导入依赖
<packaging>war</packaging>
<properties>
<spring.version>5.3.1</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-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<!--springmvc-->
<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>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Mybatis核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!--mybatis和spring的整合包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- ServletAPI -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!-- Spring5和Thymeleaf整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
</dependencies>
12.3、创建表
CREATE TABLE t_emp
(
emp_id
int(11) NOT NULL AUTO_INCREMENT,
emp_name
varchar(20) DEFAULT NULL,
age
int(11) DEFAULT NULL,
sex
char(1) DEFAULT NULL,
email
varchar(50) DEFAULT NULL,
PRIMARY KEY (emp_id
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
12.4、在web.xml文件中进行配置
12.5 搭建springmvc框架(需要什么就配置什么)
- 扫描控制层组件
<!-- springmvc组件控制层扫描 spring与springmvc有父子关系,官方推荐springmvc只去管理controller层的组件,spring负责管理所有非controller层的组件 子容器可以访问父容器,父容器无法访问子容器的bean-->
<context:component-scan base-package="com.tdh.ssm.controller"/>
- 配置视图解析器
<!-- 配置Thymeleaf视图解析器 -->
<bean id="viewResolver"
class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean
class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
- 配置默认servlet去处理静态资源
<!-- 配置默认的servlet来处理静态资源 如果只配置了默认servlet,不配置springmvc的注解驱动,那么所有请求都将被默认的servlet去处理,不会使用dispatcherServlet去处理-->
<mvc:default-servlet-handler/>
- 开启mvc的注解驱动
<!-- 开启mvc的注解驱动 如果配置注解驱动,那么浏览器到服务器的请求都会被默认的servlet所处理,并且所有的请求都只会被视图控制器所处理-->
<mvc:annotation-driven/>
- 配置视图控制器
<!-- 创建视图控制器 ,如果只配置了视图控制器,不配置springmvc的注解驱动,那么只有被试图控制器所配置的视图才会被解析,其他的所有请求映射都处理不了-->
<mvc:view-controller path="/" view-name="index"/>
- 配置文件上传解析器
<!-- 配置文件上传解析器 id是个固定值-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
- 拦截器(有需要就配置)
- 异常处理解析器(有需要就配置)
12.6 创建controller层
12.7 创建Service层
12.8 配置Spring框架
- 扫描除了controller层以外的所有组件,控制层由springmvc扫描
<!-- 扫描除了controller层以外的其它层的组件-->
<context:component-scan base-package="com.tdh.ssm">
<!-- 根据注解排除扫描-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
- 创建jdbc.properties
- 配置数据源
<!-- 引入jdbc.properties classpath 指的是类路径也就是war包下的WEB-INF下的classes路径-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
12.8 配置Mybatis配置文件
12.9 创建Mapper层
12.10 继续配置spring配置文件
- 我们利用mybatis访问数据库的时候还要获取SqlSession来实现,正常是在controller层中调用Service层方法,然后获取SqlSessionFactoryBean等一系列操作,才能生成SqlSession,这样太过麻烦,既然SqlSession是一个类,那么他也能被Spring管理,配置SqlSessionFactoryBean
查看SqlSessionFactoryBean源码
- 配置mapper接口的扫描,可以将指定包下所有的mapper接口,通过sqlSession创建代理实现类对象,并将这些对象交给IOC容器管理
<!-- MapperScannerConfigurer mapper扫描,可以将指定路径下的所有mapper接口通过上面配置SqlSessionFactoryBean所提供的SqlSessionFactory所创建出来的SqlSession获取指定路径下的所有mapper接口的代理实现类对象
并将这些对象交给ioc容器管理,所以可以在service中直接使用@Autowired直接获取mapper接口对象
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 配置了这个,即可以扫描也可以配置mapper映射文件,上面上面SqlSessionFactoryBean中的mapperLocations属性就可以不设置,但是当resources目录下的mapper文件夹与java目录中的mapper文件夹不在同一个位置,上面SqlSessionFactoryBean中的mapperLocations属性则必须匹配-->
<property name="basePackage" value="com.tdh.ssm.mapper"/>
</bean>
- 配置事务管理
<!-- 配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 事务管理是基于连接对象的,这里使用的是数据源管理的 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务注解驱动 将使用注解@Transactional标识的方法或类中所有的方法进行事务管理-->
<tx:annotation-driven transaction-manager="transactionManager"/>