目录
第一章 SpringMVC概念
0.引言
1.MVC
2.SpringMVC
3.SpringMVC的特点
4.JavaSE、JavaEE、javaME的区别
第二章 Spring MVC的使用
1.SpringMVC的配置
2.web.xml配置
3. 创建当前的请求控制器
4. 创建SpringMVC的配置文件
5.实现对首页index.xml的访问
6.@RequestMapping注解
7.@RequesrMapping注解的用法(针对RequestMapping中的value属性而言)
1.SpringMVC支持ant风格的路径
2.SpringMVC支持路径中的占位符(重点)
8.SpringMVC获取请求参数
1. 通过Servlet API获取
2. 通过控制器的形参获取
3. 通过控制器方法的实体类类型的形参获取请求参数
4. 解决获取请求参数的乱码问题
9.域对象共享数据
1. 使用servelet API向request域中共享数据
2. 使用ModelAndView向request域中共享数据
3. 使用Model向request域对象共享数据
4. 使用ModelMap向request域对象共享数据
5. 使用map 向request域对象共享数据
6.向session域共享数据
7.向application域共享数据
10.SpringMVC的视图
11.默认三种视图
1.设置视图没有任何前缀:ThymeleafView
2.默认转发视图:InternalResourceView(用得很少)
3.默认重定向视图:RedirectView
4.视图控制器:view-controller(用得多)
12.RESTful
1.REST:Representational State Transfer
13.RESTful案例
1.处理静态资源
2.实现curd操作
3.html中的@{}和${}
14.SpringMVC处理Ajax请求
1.通过浏览器向服务器发送请求的两种方式
2.html文件的写法
3.由Ajax发送的异步请求
4.@ResponseBody注解(用得很多)
5.常见的Java对象转换为json的结果
5.@RestController注解
15.SpringMVC实现文件上传和文件下载
1.文件上传与文件下载的概念
2.SpringMVC实现文件下载
3..SpringMVC实现文件上传
17.注解配置SpringMVC(重要)
1.用一个类代替实现web.xml的功能
2.用一个类代替实现Spring的配置文件
3.用一个类代替实现SpringMVC配置文件
18.SpringMVC执行流程
1.SpringMVC常用组件
2.DispatcherServlet初始化过程
3.Dispatcherservlet调用组件处理请求
4.SpringMVC的执行流程
总结!!!
第一章 SpringMVC概念
0.引言
在SSM整合中,Mybatis担任的角色是持久层框架,帮助我们访问数据库,操作数据库中的数据;Spring利用两大核心进行整合框架的功能,比如IOC用来管理对象;当Spring整合第三方框架Mybatis时,可以将其中的一些对象交给IOC容器管理,比如操作数据库的对象SqlSession及Mapper接口对象;将这些对象交给IOC容器管理之后,在使用数据直接通过自动装配就可以获取到了;而Mybatis中的事务就可以交给AOP-声明式事务来实现。至于处理浏览器和服务器之间的请求关系,就需要引入SpringMVC的概念。
1.MVC
* MVC是一种软件架构的思想,将软件按照模型Model、视图View、控制器Controller来划分
* M:Model,模型层,指JavaBean,作用是处理数据
* JavaBean分为两类:
* 实体类Bean:专门存储业务数据,如Student,User等
* 业务处理Bean:指Service或DAO对象,用于处理业务逻辑和数据访问
* V:View,视图层,指工程中的html或jsp等页面,作用是与用户进行交互,展示数据
* C:Controller,控制层,指工程中的servlet,作用是接受请求和响应浏览器
* MVC的工作流程:用户通过视图层发送请求到服务器,在服务器中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕后将结果返回到Controller,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器
2.SpringMVC
* SpringMVC是Spring的一个后续产品,是Spring的一个子项目
* SpringMVC是Soring为表述层开发提供的一整套完备的解决方案。
* 三层架构分为:表述层、业务逻辑层、数据访问层,表述层表示前台页面和后台servlet
3.SpringMVC的特点
* Spring家族产品,可与IOC容器等为基础设施对接
* 基于原生的Servlet,将servlet封装为前端控制器DispatcherServlet,对请求与响应进行统一处理
* 对表述层领域问题全方位覆盖
* 代码清新简洁
* 内部组件化程度高,可插拔式组件即插即用
* 性能卓越,适合大型互联网项目要求
4.JavaSE、JavaEE、javaME的区别
* JavaSE-Java Platform Standard Edition
* javaSE是java的基础
* javaSE之前被称为J2SE
* JavaSE包含了支持javaWeb服务开发的类,为javaEE提供基础
* 包含:面向对象、多线程、IO流等
* JavaEE-Java Platform Enterprise Edition
* java平台企业版,也叫做J2EE
* 用来开发B/S架构软件
* 包含:servlet、jstl、jsp、spring、mybatis
* JavaME- java platform Micro Edition
* 为机顶盒、PDA之类嵌入式消费电子设备提供的java平台(了解)
第二章 Spring MVC的使用
1.SpringMVC的配置
* 创建module时,注意web.xml默认位于WEB-INF下,此时要先在WEB-INF前输入src/main/webapp,将其放入main文件下的webapp中
* 配置步骤
1. 配置web.xml:注册当前SpringMVC所封装之后的前端控制器DispatcherServlet
2. 创建当前的请求控制器
3. 创建SpringMVC的配置文件
* 配置完成后,就可以使用SpringMVC处理当前的请求和响应
2.web.xml配置
* 配置servlet只需配置一个servlet标签,一个servlet-mapping标签即可
*servlet-mapping中的servlet-name存在一个default配置:
是tomcat的web.xml中所配置的一个servlet,默认的一个servlet,用来处理当前的静态资源;我们使用自己注册的servlet- name;
* 要保证配置中:Deployment的Applicationcontext与Server的URL地址一致
* url-pattern中需要写SpringMVC的前端控制器要来处理的一个请求的路径模型,当浏览器所发送的请求符合url- pattern时,当前的请求就会被前端控制器DispatcherSevlet进行处理
/:匹配浏览器向服务器发送的所有请求,但无法匹配 .jsp 方式的请求
/*:当前所有的请求都需要进行处理(可以匹配任意请求)
*.do:后缀匹配,如果浏览器所发送的请求路径以 .do 结尾,则会被DispatcherSevlet处理
/hello:只有访问的路径为hello时才会被DispatcherSevlet处理
* 此时使用 / 是因为 .jsp 的本质是servlet,而该路径是无法被DispatcherSevlet处理的;而在Tomcat的web.xml中,已经配置过一个servlet,专门用来处理 .jsp的请求的,叫做JspServlet
<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>/</url-pattern>
</servlet-mapping>
3. 创建当前的请求控制器
* 即创建创制层,而该控制层只需要创建一个处理具体请求的类POJO,不需要有任何继承与实现,只需要标识为@Controller-控制层组件
@Controller
public class UserController {
}
4. 创建SpringMVC的配置文件
* 该配置文件在DispatchServlet初始化时自动加载,不需要再手动加载,在Spring中是调用new ClassPathXmlApplicationContext(配置文件名)
* SpringMVC的配置文件默认的位置和名称(一般放在resources下)
* 位置:WEB-INF下
* 名称:<servlet-name>-servlet.xml
* 配置文件中需配置:
* 扫描控制层组件
* Thymeleaf视图解析器(复制即可)配置好后就可以使用SpringMVC提供的方式来进行视图渲染,并实现页面跳转;
* 视图解析器中的templateResolver:模版解析器中的属性:
* 物理视图=视图前缀+逻辑视图+视图后缀
* 采用此方式可以直接通过逻辑视图访问到物理视图(文件的全路径名)
<!-- 扫描控制器-->
<context:component-scan base-package="com.gz.controller"></context:component-scan>
<!-- 配置视图解析器-->
<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>
5.实现对首页index.xml的访问
* 浏览器无法直接访问WEB-INF下的资源,因为WEB-INF下的资源具有一定的安全性,只能通过服务器来访问,然后服务器转发给浏览器访问
* 使用@RequestMapping来将当前浏览器所发送的请求映射到标识到的方法中执行,然后让该方法来处理请求
* @RequestMapping的value属性值中需要设置请求路径
* 设置为 / 时,由于是在服务器中写的,被解析为:localhost:8080:上下文路径
* 使用@RequestMapping且设置好请求路径后,该方法即是用来处理请求的方法
* return中将逻辑视图返回,该逻辑视图会被配置文件中的视图解析器解析,在解析器中加上视图前缀与后缀,变为完整的物理视图,后通过thymeleaf的渲染,跳转到页面
// @RequestMapping("/")
public String testSpringMvc(){
return "index";
}
解析器中的前缀与后缀
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
6.@RequestMapping注解
* RequestMapping注解的作用:将请求和处理请求的控制器方法关联起来,建立映射关系。
* SpringMVC接收到指定的请求,就会找到在映射关系中对应的控制器方法来处理这个请求。
* RequestMapping注解的位置
* RequestMapping标识一个类:设置映射请求的请求路径的初始信息
* RequestMapping标识一个方法:设置映射请求的请求路径的具体信息
* RequestMapping的value属性值
* 作用:通过请求的请求路径匹配请求
* value属性是数组类型,即当前浏览器所发送请求的请求路径匹配value属性中的任何一个值,则当前请求就会被注解所表示的方法进行处理
* RequestMapping的method属性值
* 作用:通过请求的请求方式来匹配请求
* Method类型为:RequestMethod-枚举类的数组,当前浏览器所发送请求的请求方式匹配method属性中任何一个方式,则当前请求会被注解所标识的方法处理。
* RequestMethod:提供了:get、post、head、options、put、patch、delete、trace等方式
* 只有表单提交时将method设置为post,其他方式基本为get方式(比如超链接、浏览器中地址栏直接访问)
@RequestMapping(
value = {"/success","/hello"},
method = {RequestMethod.GET,RequestMethod.POST,
RequestMethod.PUT,RequestMethod.DELETE}
)
public String testSuccess(){
return "success";
}
* 若浏览器所发送的请求的请求路径和@RequestMapping注解value属性匹配,但是请求方式不匹配,此时页面报错:405-Requeat method … not supported
* @RequestMapping的基础上,结合请求方式的一些派生注解:@GetMapping、
@PostMapping、@DeleteMapping、@PutMapping;即注解的方法只适合一些固定请求方式
@GetMapping("/success")
public String testGetMapping(){
return "success";
}
* params属性不匹配报错:400
* headers属性不匹配报错:404-资源未找到
7.@RequesrMapping注解的用法(针对RequestMapping中的value属性而言)
1.SpringMVC支持ant风格的路径
* ?:任意单个字符(但不包含?本身)
* *:任意0个或多个字符(但不包含?和/)
* **:任意层数的任意目录,使用时只能将**写在双斜线中,前后不能有任何其他字符(但不包含?本身)
// requestMapping的value属性:数组类型
@RequestMapping(
value = {"/demo3", "/a?a","/demo4"},
method = RequestMethod.GET
)
public String testThree() {
return "demo3";
}
@RequestMapping("/**/ant")
public String testFour(){
return "demo3";
}
2.SpringMVC支持路径中的占位符(重点)
* 传统方式:/deleteUser?id=1
* rest:/user/delete/1
* 需要在@RequestMappibg注解的value属性中所设置的路径中,使用{…}的方式表示路径中的数据,再通过@PathVariable注解,将占位符所标识的值与控制器方法的形参进行绑定
@RequestMapping("/aaa/{id}/{name}")
public String testFive(@PathVariable("id") String id,@PathVariable("name") String name){
System.out.println("id = " + id + ",name = " + name);
return "demo3";
}
8.SpringMVC获取请求参数
1. 通过Servlet API获取
* 只需要在控制层方法的形参中设置HttpServletRequest类型的形参即可,就可以在控制器方法中使用request对象获取请求参数(用得不多)
<form th:action="@{/param/pojo}" method="post">
用户名:<input type="text" name="username"><br/>
密码: <input type="password" name="password"><br/>
<input type="submit" value="登录"><br/>
</form>
2. 通过控制器的形参获取
* 只需要在控制器方法的形参位置,设置一个形参,形参的名字和请求参数的名字一致即可
* 当二者名字不一致时,使用@RequestParam将请求参数和控制器方法的形参绑定
* @RequestParam有三个属性:
* value:设置和形参绑定的请求参数的名字
* required:设置是否必须传输value所对应的请求参数,默认值为true,表示value所对应的请求参数必须传输,否则报错:400;若为false,则表示不是必须传输,未传输的形参值为null
* defaultValue:设置当没有传输value所对应的请求参数时,为形参设置的默认值,此时与required设置无关
* @RequestHeader:将请求头信息与控制器方法形参绑定
* @CookieValue:将cookie数据与控制器方法形参绑定
* 二者与@RequestParam用法一摸一样,属性也一样
3. 通过控制器方法的实体类类型的形参获取请求参数
* 需要在控制器方法的形参位置设置实体类类型的形参,要保证实体类中的属性的属性名和请求参数的名字一致,可以通过实体类类型的形参获取请求参数
public class User {
private Integer id;
private String username;
private String password;
}
<form th:action="@{/param/pojo}" method="post">
用户名:<input type="text" name="username"><br/>
密码: <input type="password" name="password"><br/>
<input type="submit" value="登录"><br/>
</form>
@RequestMapping("/param/pojo")
public String testSeven(User user){
System.out.println(user);
return "demo3";
}
4. 解决获取请求参数的乱码问题
* 在web.xml中注册SpringMvC提供的编码过滤器CharacterEncodingFilter
* Spring MVC中处理编码的过滤器一定要配置到其他过滤器之前,否则无效
<!-- 解决乱码问题-->
<filter>
<filter-name>characterEncodingFilter</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>
9.域对象共享数据
1. 使用servelet API向request域中共享数据
springMVC中不用
2. 使用ModelAndView向request域中共享数据
* ModelAndView包含model和view两个功能
* model:向请求域中共享数据
* view:设置逻辑视图实现页面跳转
* 将ModelAndView作为方法的返回值
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
ModelAndView mav = new ModelAndView();
//向请求域共享数据
mav.addObject("testRequestScope","hello,ModelAndView");
//设置视图,实现页面跳转
mav.setViewName("demo4");
return mav;
}
3. 使用Model向request域对象共享数据
@RequestMapping("/testModel")
public String testModel(Model model){
model.addAttribute("testModel","hello,Model");
return "demo4";
}
4. 使用ModelMap向request域对象共享数据
@RequestMapping("/testModelMap")
public String testModelMap(ModelMap modelMap){
modelMap.addAttribute("testModelMap","hello,ModelMap");
return "demo4";
}
5. 使用map 向request域对象共享数据
@RequestMapping("/testMap")
public String testMap(Map<String,Object> map){
map.put("testMap","hello,Map");
return "demo4";
}
* model、modelMap和map在底层中,形参都是根据BindungAwareModelMap创建的
注意:addAttribute中的attributeName要和中mav.setViewName()中的文件属性名一致
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>demo4</title>
</head>
<body>
<h1>demo4</h1>
<p th:text="${testRequestScope}"></p>
<p th:text="${testModel}"></p>
<p th:text="${testModelMap}"></p>
<p th:text="${testMap}"></p>
<p th:text="${session.testSession}"></p>
<p th:text="${application.testApplication}"></p>
</body>
</html>
6.向session域共享数据
* 使用servlet API更简单
* session是基于会话的,网页关闭后数据消失,session清空
@RequestMapping("/testSession")
public String testSession(HttpSession session){
session.setAttribute("testSession","hello,session");
return "demo4";
}
7.向application域共享数据
* 使用servlet API更简单
* application是基于服务器的,服务器(如tomcat)关闭后,内部的application域数据清空
@RequestMapping("/testApplication")
public String testApplication(HttpSession session){
ServletContext servletContext = session.getServletContext();
servletContext.setAttribute("testApplication","hello,application");
return "demo4";
}
10.SpringMVC的视图
* 视图为View接口
* 视图的作用:渲染数据,将模型model中的数据展示给用户
* 视图的种类(默认):转发视图,重定向视图
11.默认三种视图
1.设置视图没有任何前缀:ThymeleafView
用得最多,也是一种转发,作为视图解析技术的基础,InternalResourceView转发后会再次进行一次Thymeleaf解析来渲染页面)
2.默认转发视图:InternalResourceView(用得很少)
* 前缀为:forward,使用转发视图
* 只能实现转发效果,页面中的thymeleaf语法不会被解析
* 转发后的地址与RequestMapping中处理请求的路径相同
3.默认重定向视图:RedirectView
* 前缀为:redirect
* 转发后的地址会变成redirect后的地址
4.视图控制器:view-controller(用得多)
* 在配置文件中设置view-controller标签即可
* 当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称,可将处理器方法使用mvc命名空间中的标签:view-controller标签表示
* 但存在一个问题:只有设置了视图控制器的请求才会被处理;因此需要mvc命名空间中的标签:annotation- driven标签
* 设置annotation- driven标签,开启mvc的注解驱动
<!--
开启mvc的注解驱动
因为配置视图控制器时,只有设置了view-name的才能被处理
开启mvc的注解驱动后,就能够处理view-name中超链接的页面
-->
<mvc:annotation-driven />
<!-- 配置视图控制器:为当前的请求直接设置视图名称实现页面跳转-->
<mvc:view-controller path="/" view-name="demo1"></mvc:view-controller>
12.RESTful
1.REST:Representational State Transfer
表现层资源状态转移;是一种开发风格
* 资源:将服务器看作是资源组成的。服务器中的一切就是每一个资源。资源由一个或多个URL来标识,通过资源的URL与资源交互
* 资源的表述:多种格式:如html/xml/json/文本/图片/视频等
* 状态转移:客户端与服务器之间转移资源状态,实现操作资源的目的
* 访问同一个资源,使用同一个路径
* RESTful实现:使用四个基本操作
* get:获取资源
// 查询所有的用户信息
@RequestMapping(value = "/user" , method = RequestMethod.GET)
public String testGet(){
System.out.println("查询所有的用户信息-->/user-->get");
return "success";
}
// 根据id查询用户信息
@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
public String testGetById(@PathVariable("id")Integer id){
System.out.println("根据id查询用户信息-->/user/"+id+"-->get");
return "success";
}
* post:新建资源
// 添加用户信息
@RequestMapping(value = "/user",method = RequestMethod.POST)
public String testPost(){
System.out.println("添加用户信息-->/user-->post");
return "success";
}
* put:更新资源
// 修改用户信息
@RequestMapping(value = "/user",method=RequestMethod.PUT)
public String testPut(){
System.out.println("修改用户信息-->/user-->put");
return "success";
}
* delete:删除资源
// 删除用户信息
@RequestMapping(value = "/user/{id}",method = RequestMethod.DELETE)
public String testDelete(@PathVariable("id" )Integer id){
System.out.println("删除用户信息-->/user/"+ id +"-->delete");
return "success";
}
* 注意:浏览器只能发送get和post请求,若要发送put和delete请求,则
* 要在web.xml中设置处理请求方式的过滤器HiddenhttpMethodFilter(注意:有多个过滤器时,编码过滤器要放在最前面)
* 配置过滤器后,发送请求要满足两个条件,才能将请求方式转换为put/delete
1. 当前请求的method必须为post
2. 保证传输请求参数为_method,值为put/delete
<form th:action="@{/user}" method="post">
<input type="submit" value="添加用户信息">
</form>
<hr/>
<form th:action="@{/user}" method="post">
<input type="hidden" name="_method" value="put">
<input type="submit" value="修改用户信息">
</form>
<hr/>
<form th:action="@{/user/1}" method="post">
<input type="hidden" name="_method" value="delete">
<input type="submit" value="删除用户信息">
</form>
* 提倡URL地址统一的风格设计,将资源作为URL路径的一部分,前后的单词用 / 分开
* 可以用派生注解将requestmapping转化为对应的Getmapping等
13.RESTful案例
1.处理静态资源
比如加上前端样式时需要静态资源static
* 当本工程下的web.xml和tomcat自带的web.xml的url- pattern相同时,会以本工程下的web.xml为准,但本工程处理时使用DispatcherSevlet无法处理静态资源,因此需要在配置文件中配置默认的servlet处理静态资源(注意:和视图控制器一样,需要开启mvc的注解驱动)
* 当前工程的web.xml配置的前端控制器DispatcherServlet的urL-pattern是/,tomcat的web.xml配置的Defaultservlet的url-pattern也是/。此时,浏览器发送的请求会优先被DispatcherServlet进行处理,但是DispatcherServlet无法处理静态资源,若配置了<mvc;default-servlet-handler />,此时浏览器发送的所有请求都会被Defaultservlet处理,若配置了<mvc;default-servlet-handler />和<mvcannotation-driven />,浏览器发送的请求会先被DispatcherServlet处理,无法处理在交给Defaultservlet处理
<!-- 处理静态资源的方式-->
<mvc:default-servlet-handler/>
<mvc:annotation-driven />
2.实现curd操作
* 查
* 增
* 改
1. 获取要修改的员工信息
2. 将要修改的信息放在请求域中,跳转到修改页面
3. 在修改页面中先回显,回显后进行修改
* 删
3.html中的@{}和${}
* @{}:用于获取链接地址
* ${}:用于对象获取、字符串的替换、属性绑定
14.SpringMVC处理Ajax请求
1.通过浏览器向服务器发送请求的两种方式
第一种:同步请求
第二种:由Ajax发送的异步请求;Ajax请求的特点:在页面不刷新的情况下与服务器进行交互
2.html文件的写法
1)在自定义文件中发送一个Ajax请求
2)引入需要的.js文件
3) 创建vue对象,为页面中的某个标签绑定事件,然后创造它所对应的函数
a>创建一个div,id设置为:app
b>设置挂在容器el:#app
c>设置methods:为当前事件所绑定的函数
d>设置一个按钮(超链接绑定事件执行Ajax需要阻止默认行为,按钮不在表单中就没有相应的功能),绑定一个点击事件@click
e>在methods中使用axios.post或get 发送一个Ajax请求;
注意:该axios.post先加上应用的上下文路径/SpringMVC
3.由Ajax发送的异步请求
Ajax请求的特点:在页面不刷新的情况下与服务器进行交互
/*
将请求体中的内容和控制器方法的形参进行绑定,将json格式的请求参数转换为Java对象需要满足三个条件:
1.导入jackson依赖
2.在springmvc的配置文件中开启mvc的注解驱动
3.在控制方法形参位置设置一个json格式的请求参数要转换的Java类型的形参,并使用@RequestBody标识
*/
@RequestMapping("/test/RequestBody/json")
public void testRequestBody(@RequestBody Uesr user, HttpServletResponse response) throws IOException {
System.out.println(user);
response.getWriter().write("hello,ResponseBody");
}
4.@ResponseBody注解(用得很多)
* 用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器
* 即将返回值作为结果响应到浏览器,而非未加注解时,将跳转到对应的页面
* 使用@ResponseBody注解响应浏览器json格式的注解,三步:
* 一:导入jackson的依赖
* 二:在springMVC的配置文件中开启mvc的注解驱动
* 三:在处理请求的控制器方法形参位置设置一个json格式的请求参数要转换的java类型的形参,使用@RequestBody标识即可
5.常见的Java对象转换为json的结果
* 实体类——json对象
* map——json对象
* list——json数组
5.@RestController注解
* SpringMVC的一个复合注解,标识在控制器的类上,相当于为类添加了@Controller注解,并为其中的每个方法添加了@ResponseBody注解
15.SpringMVC实现文件上传和文件下载
1.文件上传与文件下载的概念
文件下载:将文件从服务器下载到浏览器中
文件上传:将文件从浏览器上传到服务器中
本质:都是文件复制的过程
2.SpringMVC实现文件下载
1.需要使用ResponseEntity类,ResponseEntity类用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文。
2.文件下载的步骤一般都是固定的,唯一不同的只是服务器中文件的下载路径,可以作为一个模板,以后只改该路径即可。
我的文件路径为:
@RequestMapping("/testDown")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws
IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("/img/1.jpg");
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
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;
}
3.文件的真实路径若不知分隔符的情况下,可以使用File.separator来进行拼接,该方法能够自动匹配当前的系统需要的分隔符
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("img");
realPath = realPath + File.separator + "1.jpg";
3..SpringMVC实现文件上传
准备工作:导入依赖commons-fileupload
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
1.实现上传功能时必须要有表单,表单中要有文件域:type=file,且必须满足两个两个条件:
1)method必须为post
2)enctype,即浏览器向服务器传输请求参数的方式:文件上传时必须将参数设置为:multipart/form-data(以二进制的形式上传)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<form th:action="@{/test/up}" method="post" enctype="multipart/form-data">
头像:<input type="file" name="photo"><br/>
<input type="submit" value="上传">
</form>
</body>
2.实现文件上传功能时必须配置文件上传解析器;必须设置id为:multipartResolver;因为在自动装配时是根据id来匹配的,而不是根据类型匹配的
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
3.将文件上传至为photo的文件夹中
@RequestMapping("/test/up")
public String testUp(MultipartFile photo,HttpSession session) throws IOException {
//获取上传的文件的文件名
String fileName = photo.getOriginalFilename();
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取当前工程下photo目录的真实路径
String photoPath = servletContext.getRealPath("photo");
//创建photoPath所对应的File对象
File file = new File(photoPath);
//判断目录是否存在
if(!file.exists()){
file.mkdir();
}
String finalPath = photoPath + File.separator + fileName;
//上传文件
photo.transferTo(new File(finalPath));
return "success";
}
4.解决文件上传功能时文件重名的问题:
使用UUID作为文件名,保证文件名不会重复,从而解决重名问题。
/*
为解决上传文件的文件名重名的问题,将上传文件的文件名使用uuid与后缀进行拼接
*/
//获取上传的文件的文件名
String fileName = photo.getOriginalFilename();
//获取上传的文件的后缀名
String hzName = fileName.substring(fileName.lastIndexOf("."));
//获取uuid
String uuid = UUID.randomUUID().toString();
//拼接一个新的文件名
fileName = uuid + hzName;
注意:UUID 是 通用唯一识别码(Universally Unique Identifier)
5.效果展示:
上传后的文件位于:
17.注解配置SpringMVC(重要)
1.用一个类代替实现web.xml的功能
* web.xml中实现的功能:
* 注册DispatcherServelet
* 编码过滤器
* 处理请求方式的过滤器
/**
*代替web.xml的配置文件:注册DispatcherServelet、编码过滤器、处理请求方式的过滤器
*/
//@Configuration
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
//设置一个配置类代替Spring的配置文件
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
@Override
//设置一个配置类代替SpringMVC的配置文件
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
//设置SpringMVC的前端控制器DispatcherServlet的url-pattern
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
//设置当前的过滤器
protected Filter[] getServletFilters() {
//创建编码过滤器
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
//创建处理请求方式的过滤器
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
return new Filter[]{characterEncodingFilter,hiddenHttpMethodFilter};
}
}
2.用一个类代替实现Spring的配置文件
/**
* 代替Spring的配置文件
*/
//将该类设置为配置类
@Configuration
public class SpringConfig {
}
3.用一个类代替实现SpringMVC配置文件
* 需要实现接口:WebMvcConfigurer
* springmvc配置文件的功能
* 扫描组件
* 视图解析器:直接复制即可
* 默认的servlet处理器
* mvc的注解驱动
* 视图控制器
* 文件上传解析器
* 拦截器
* 异常解析器
/**
* 代替SpringMVC的配置文件:扫描组件、DispatcherServlet、开启SpringMVC的注解驱动
* 视图解析器、默认的Servlet、文件上传解析器、拦截器、异常解析器
*/
//将类标识为配置类
@Configuration
//扫描组件
@ComponentScan("com.gz.controller")
//开启mvc的注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
//默认的servlet处理静态资源
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
//配置视图解析器
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
@Bean
//@Bean注解可以将标识的方法的返回值作为bean进行管理,bean的id为方法的方法名
public CommonsMultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
//配置拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
FirstInterceptor firstInterceptor = new FirstInterceptor();
registry.addInterceptor(firstInterceptor).addPathPatterns("/**");
}
@Override
//配置异常解析器
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
Properties prop = new Properties();
prop.setProperty("java.lang.ArithmeticException", "error");
exceptionResolver.setExceptionMappings(prop);
exceptionResolver.setExceptionAttribute("ex");
resolvers.add(exceptionResolver);
}
//配置生成模板解析器
@Bean
public ITemplateResolver templateResolver() {
WebApplicationContext webApplicationContext =
ContextLoader.getCurrentWebApplicationContext();
// ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(webApplicationContext.getServletContext());
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setTemplateMode(TemplateMode.HTML);
return templateResolver;
}
//生成模板引擎并为模板引擎注入模板解析器
@Bean
public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
return templateEngine;
}
//生成视图解析器并未解析器注入模板引擎
@Bean
public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setCharacterEncoding("UTF-8");
viewResolver.setTemplateEngine(templateEngine);
return viewResolver;
}
}
18.SpringMVC执行流程
1.SpringMVC常用组件
* DispatcherServelt:前端控制器,无需工程师开发,框架提供
* 作用:统一处理请求和响应,整个流程控制的中心,由它调度其它组件处理用户请求
* HandlerMapping:处理器映射器,无需工程师开发,框架提供
* 作用:根据请求的url、method、等信息查找Handler,即控制器方法
* Handler:处理器,需要工程师开发
* 作用:在DispatcherSevlet控制下Handler对具体的用户请求进行处理
* HandlerAdapter:处理器适配器,无需工程师开发,框架提供
* 作用:通过HandlerAdapter对控制器方法进行执行
* ViewResolver:视图解析器,无需工程师开发,框架提供
* 作用:进行视图解析,得到相应的视图,如ThemeleafView
* View:视图
* 作用:将模型数据通过页面展示给用户,自己开发
2.DispatcherServlet初始化过程
* 通过SpringMVC所创建出来的IOC容器和Spring的IOC容器之间的关系为子容器与父容器的关系,SpringMVC为子容器,Spring为父容器;wac.setParent(Parent)用来设置Spring的IOC容器的
3.Dispatcherservlet调用组件处理请求
* 看源码,在DispatcherServelet的doDispatch中处理发送的各种请求
4.SpringMVC的执行流程
1. 用户向服务器发送请求,请求被SpringMVC前端控制器DispatcherServelet捕获
2. DisoatcherServelet对请求URL进行解析,得到请求资源标识符URI,判断请求URI对应的映射是否存在
3. 不存在时:判断是否配置了mvc:default-servlet-handler;如果没有配置,则无法查到映射,客户端展示404错误;如果有配置,则访问目标资源(一般为静态资源,JS,CSS,HTML),找不到客户端也会展示404错误
4. 存在则继续执行下去
5. 根据该URI,调用HandlerMapping获得该Handler(控制器方法)配置的所有相关对象,然后以HandlerExecutionChain执行链对象返回
6. DispatcherServlet根据获得的Handler,选择合适的HandlerAdapter
7. 成功获得HandlerAdapter,此时开始执行拦截器的preHandler(…)方法
8. 听进去Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法处理请求。填充Handler入参的过程中,根据配置Spring会执行以下操作:
1. HttpMessageConver:将请求消息转换成一个对象,将对象转换为指定的响应信息
2. 数据转换:对请求消息进行数据转换
3. 数据格式化:对请求消息进行去数据格式化
4. 数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult中
9. Handler执行完成后,向DispatcherServlet返回一个ModelAndView对象
10. 此时开始执行lanjieqidewpostHandler方法
11. 根据返回的ModelAndView选择合适的ViewResolver进行视图解析,根据Model和View渲染视图
12. 渲染视图完毕执行拦截器的afterCompletion方法
13. 将渲染结果返回给客户端
总结!!!
浏览器发送请求,被DispatcherServlet处理,DispatcherServlet处理请求时,要先找到该请求所对应的请求映射;此时看存不存在该请求映射,不存在时观察有没有配置默认的servlet,没配置则返回404,配置了则交给默认的servlet继续处理(一般处理的是静态资源),若默认的servlet处理不了则还是返回404;存在请求映射,则通过HandlerMapping匹配当前的控制器方法,再通过HandlerAdapter调用执行控制器方法;在执行控制器方法之前,会按照SpringMVC配置文件中所配置的拦截器的顺序去执行拦截器的preHandler(…)方法;然后再调用控制器方法,控制器方法执行后,调用拦截器的postHandle方法,然后再处理ModelAndView进行渲染视图,渲染完视图后执行拦截器的afterCompletion方法,最终将渲染结果响应给浏览器。