01-SpringMVC简介
SpringMVC是隶属于Spring框架的一部分,主要是用来进行Web开发,是对Servlet进行了封装。
SpringMVC是处于Web层的框架,所以其主要的作用就是用来接收前端发过来的请求和数据然后经过处理并将处理的结果响应给前端,所以如何处理请求和响应是SpringMVC中非常重要的一块内容。
REST是一种软件架构风格,可以降低开发的复杂性,提高系统的可伸缩性,后期的应用也是非常广泛。
SSM整合是把咱们所学习的SpringMVC+Spring+Mybatis整合在一起来完成业务开发,是对我们所学习这三个框架的一个综合应用。
02-SpringMVC入门案例
知识点1:@Controller
名称 | @Controller |
类型 | 类注解 |
位置 | SpringMVC控制器类定义上方 |
作用 | 设定SpringMVC的核心控制器bean |
知识点2:@RequestMapping
名称 | @RequestMapping |
类型 | 类注解或方法注解 |
位置 | SpringMVC控制器类或方法定义上方 |
作用 | 设置当前控制器方法请求访问路径 |
相关属性 | value(默认),请求访问路径 |
知识点3:@ResponseBody
名称 | @ResponseBody |
类型 | 类注解或方法注解 |
位置 | SpringMVC控制器类或方法定义上方 |
作用 | 设置当前控制器方法响应内容为当前返回值,无需解析 |
03-入门案例工作流程
2.4.1 启动服务器初始化过程
服务器启动,执行ServletContainersInitConfig类,初始化web容器
功能类似于以前的web.xml
执行createServletApplicationContext方法,创建了WebApplicationContext对象
该方法加载SpringMVC的配置类SpringMvcConfig来初始化SpringMVC的容器
加载SpringMvcConfig配置类
执行@ComponentScan加载对应的bean
扫描指定包及其子包下所有类上的注解,如Controller类上的@Controller注解
加载UserController,每个@RequestMapping的名称对应一个具体的方法
此时就建立了 /save 和 save方法的对应关系
执行getServletMappings方法,设定SpringMVC拦截请求的路径规则
/代表所拦截请求的路径规则,只有被拦截后才能交给SpringMVC来处理请求
2.4.2 单次请求过程
发送请求http://localhost/save
web容器发现该请求满足SpringMVC拦截规则,将请求交给SpringMVC处理
解析请求路径/save
由/save匹配执行对应的方法save()
上面的第五步已经将请求路径和方法建立了对应关系,通过/save就能找到对应的save方法
执行save()
检测到有@ResponseBody直接将save()方法的返回值作为响应体返回给请求方
04-bean加载控制
方式一:修改Spring配置类,设定扫描范围为精准范围
@Configuration
@ComponentScan({"com.itheima.service","comitheima.dao"})
public class SpringConfig { }
说明:
上述只是通过例子说明可以精确指定让Spring扫描对应的包结构,真正在做开发的时候,因为Dao最终是交给MapperScannerConfigurer对象来进行扫描处理的,我们只需要将其扫描到service包即可。
方式二:修改Spring配置类,设定扫描范围为itheima,排除controller包中的bean(比第一种麻烦)
@Configuration
@ComponentScan(value="com.itheima",
excludeFilters=@ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
) )
public class SpringConfig { }
excludeFilters属性:设置扫描加载bean时,排除的过滤规则
type属性:设置排除规则,当前使用按照bean定义时的注解类型进行排除
ANNOTATION:按照注解排除
ASSIGNABLE_TYPE:按照指定的类型过滤
ASPECTJ:按照Aspectj表达式排除,基本上不会用
REGEX:按照正则表达式排除
CUSTOM:按照自定义规则排除
大家只需要知道第一种ANNOTATION即可
classes属性:设置排除的具体注解类,当前设置排除@Controller定义的bean
05-PostMan工具介绍\
对于PostMan如果觉得字小不好看,可以使用ctrl+=调大,ctrl+-调小
3.1 PostMan简介
代码编写完后,我们要想测试,只需要打开浏览器直接输入地址发送请求即可。发送的是GET请求可以直接使用浏览器,但是如果要发送的是POST请求呢?
如果要求发送的是post请求,我们就得准备页面在页面上准备form表单,测试起来比较麻烦。所以我们就需要借助一些第三方工具,如PostMan.
PostMan是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。
作用:常用于进行接口测试
特征: 简单 实用 美观 大方
06-设置请求映射路径
07-get请求与post请求发送普通参数
08-5种类型参数传递
常见的参数种类有:
普通参数
POJO类型参数
嵌套POJO类型参数
数组类型参数
集合类型参数
09-json数据传递参数
前面我们说过,流行的开发方式为异步调用。前后端以异步方式进行交换,前端如果发送JSON数据,后端如何接收?
对于JSON数据类型,我们常见的有三种:
json普通数组(["value1","value2","value3",...])
json对象({key1:value1,key2:value2,...})
json对象数组([{key1:value1,...},{key2:value2,...}])
10-日期型参数传递
11-响应
4.6.2 响应页面[了解]
步骤1:设置返回页面
@Controller
public class UserController {
@RequestMapping("/toJumpPage")
//注意
//1.此处不能添加@ResponseBody,如果加了该注入,会直接将page.jsp当字符串返回前端
//2.方法需要返回String
public String toJumpPage(){
System.out.println("跳转页面");
return "page.jsp";
} }
4.6.3 返回文本数据[了解]
步骤1:设置返回文本内容
@Controller
public class UserController {
@RequestMapping("/toText")
//注意此处该注解就不能省略,如果省略了,会把response text当前页面名称去查找,如果没有回报404错误
@ResponseBody
public String toText(){
System.out.println("返回纯文本数据");
return "response text";
} }
4.6.4 响应JSON数据
响应POJO对象
@Controller
public class UserController {
@RequestMapping("/toJsonList")
@ResponseBody
public List<User> toJsonList(){
System.out.println("返回json集合数据");
User user1 = new User();
user1.setName("传智播客");
user1.setAge(15);
User user2 = new User();
user2.setName("黑马程序员");
user2.setAge(12);
List<User> userList = new ArrayList<User>();
userList.add(user1);
userList.add(user2);
return userList;
} }
返回值为实体类对象,设置返回值为实体类类型,即可实现返回对应对象的json数据,需要依赖==@ResponseBody==注解和==@EnableWebMvc==注解
响应POJO集合对象
@Controller
public class UserController {
@RequestMapping("/toJsonList")
@ResponseBody
public List<User> toJsonList(){
System.out.println("返回json集合数据");
User user1 = new User();
user1.setName("传智播客");
user1.setAge(15);
User user2 = new User();
user2.setName("黑马程序员");
user2.setAge(12);
List<User> userList = new ArrayList<User>();
userList.add(user1);
userList.add(user2);
return userList;
} }
@ResponseBody
名称 | @ResponseBody |
类型 | 方法\类注解 |
位置 | SpringMVC控制器方法定义上方和控制类上 |
作用 | 设置当前控制器返回值作为响应体,写在类上,该类的所有方法都有该注解功能 |
相关属性 | pattern:指定日期时间格式字符串 |
说明:
该注解可以写在类上或者方法上
写在类上就是该类下的所有方法都有@ReponseBody功能
当方法上有@ReponseBody注解后
方法的返回值为字符串,会将其作为文本内容直接响应给前端
方法的返回值为对象,会将对象转换成JSON响应给前端
此处又使用到了类型转换,内部还是通过Converter接口的实现类完成的,所以Converter除了前面所说的功能外,它还可以实现:
对象转Json数据(POJO -> json)
集合转Json数据(Collection -> json)
12-REST风格简介
13-RESTful入门案例 (修改RESTful风格)
新增POST
@Controller
public class UserController {
//设置当前请求方法为POST,表示REST风格中的添加操作
@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String save() {
System.out.println("user save...");
return "{'module':'user save'}";
} }
将请求路径("/save")更改为/users
访问该方法使用 POST: http://localhost/users
使用method属性限定该方法的访问方式为POST
如果发送的不是POST请求,比如发送GET请求,则会报错
删除DELETE
@Controller
public class UserController {
//设置当前请求方法为DELETE,表示REST风格中的删除操作
@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id) {
System.out.println("user delete..." + id);
return "{'module':'user delete'}";
}
}
将请求路径更改为/users
访问该方法使用 DELETE: http://localhost/users
访问成功,但是删除方法没有携带所要删除数据的id,所以针对RESTful的开发,如何携带数据参数?
传递路径参数
前端发送请求的时候使用:http://localhost/users/1,路径中的1就是我们想要传递的参数。
后端获取参数,需要做如下修改:
修改@RequestMapping的value属性,将其中修改为/users/{id},目的是和路径匹配
在方法的形参前添加@PathVariable注解
思考如下两个问题:
(1)如果方法形参的名称和路径{}中的值不一致,该怎么办?
(2)如果有多个参数需要传递该如何编写?
前端发送请求的时候用:http://localhost/users/1/tom,路径中的1和tom就是我们想要传递的两个参数
后端获取参数,需要做如下修改:
@Controller
public class UserController {
//设置当前请求方法为DELETE,表示REST风格中的删除操作
@RequestMapping(value = "/users/{id}/{name}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id,@PathVariable String name) {
System.out.println("user delete..." + id+","+name);
return "{'module':'user delete'}";
}
}
修改PUT
@Controller
public class UserController {
//设置当前请求方法为PUT,表示REST风格中的修改操作
@RequestMapping(value = "/users",method = RequestMethod.PUT)
@ResponseBody
public String update(@RequestBody User user) {
System.out.println("user update..." + user);
return "{'module':'user update'}";
}
}
将请求路径更改为/users
访问该方法使用 PUT: http://localhost/users
根据ID查询GETGET
@Controller
public class UserController {
//设置当前请求方法为GET,表示REST风格中的查询操作
@RequestMapping(value = "/users/{id}" ,method = RequestMethod.GET)
@ResponseBody
public String getById(@PathVariable Integer id){
System.out.println("user getById..."+id);
return "{'module':'user getById'}";
}
}
将请求路径更改为/users
访问该方法使用 GET: http://localhost/users/666
查询所有GETGET
@Controller
public class UserController {
//设置当前请求方法为GET,表示REST风格中的查询操作
@RequestMapping(value = "/users" ,method = RequestMethod.GET)
@ResponseBody
public String getAll() {
System.out.println("user getAll...");
return "{'module':'user getAll'}";
}
}
将请求路径更改为/users
访问该方法使用 GET: http://localhost/users
关于接收参数,我们学过三个注解@RequestBody、@RequestParam、@PathVariable
这三个注解之间的区别和应用分别是什么?
区别
@RequestParam用于接收url地址传参或表单传参
@RequestBody用于接收json数据
@PathVariable用于接收路径参数,使用{参数名称}描述路径参数
应用
后期开发中,发送请求参数超过1个时,以json格式为主,@RequestBody应用较广
如果发送非json格式数据,选用@RequestParam接收请求参数
采用RESTful进行开发,当参数数量较少时,例如1个,可以采用@PathVariable接收请求路径变量,通常用于传递id值;超过1个用JSON@RequestBody
14-RESTful快速开发(标准开发)
问题1:每个方法的@RequestMapping注解中都定义了访问路径/books,重复性太高。
将@RequestMapping提到类上面,用来定义所有方法共同的访问路径。
问题2:每个方法的@RequestMapping注解中都要使用method属性定义请求方式,重复性太高。
使用@GetMapping @PostMapping @PutMapping @DeleteMapping代替
问题3:每个方法响应json都需要加上@ResponseBody注解,重复性太高。
1.将ResponseBody提到类上面,让所有的方法都有@ResponseBody的功能
2.使用@RestController注解替换@Controller与@ResponseBody注解,简化书写
@RestController //@Controller + ReponseBody
@RequestMapping("/books")
public class BookController {
//@RequestMapping(method = RequestMethod.POST)
@PostMapping
public String save(@RequestBody Book book){
System.out.println("book save..." + book);
return "{'module':'book save'}"; }
//@RequestMapping(value = "/{id}",method = RequestMethod.DELETE)
@DeleteMapping("/{id}")
public String delete(@PathVariable Integer id){
System.out.println("book delete..." + id);
return "{'module':'book delete'}";}
//@RequestMapping(method = RequestMethod.PUT)
@PutMapping
public String update(@RequestBody Book book){
System.out.println("book update..." + book);
return "{'module':'book update'}";}
//@RequestMapping(value = "/{id}",method = RequestMethod.GET)
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println("book getById..." + id);
return "{'module':'book getById'}";}
//@RequestMapping(method = RequestMethod.GET)
@GetMapping
public String getAll(){
System.out.println("book getAll...");
return "{'module':'book getAll'}";}
}
15-案例: 基于RESTful页面数据交互(后台接口开发)
5.4.2 后台接口开发
步骤1:编写Controller类并使用RESTful进行配置
@RestController
@RequestMapping("/books")
public class BookController {
@PostMapping
public String save(@RequestBody Book book){
System.out.println("book save ==> "+ book);
return "{'module':'book save success'}";
}
@GetMapping
public List<Book> getAll(){
System.out.println("book getAll is running ...");
List<Book> bookList = new ArrayList<Book>();
Book book1 = new Book();
book1.setType("计算机");
book1.setName("SpringMVC入门教程");
book1.setDescription("小试牛刀");
bookList.add(book1);
Book book2 = new Book();
book2.setType("计算机");
book2.setName("SpringMVC实战教程");
book2.setDescription("一代宗师");
bookList.add(book2);
Book book3 = new Book();
book3.setType("计算机丛书");
book3.setName("SpringMVC实战教程进阶");
book3.setDescription("一代宗师呕心创作");
bookList.add(book3);
return bookList;
} }
16-案例:基于RESTful页面数据交互(页面访问处理)
SpringMVC拦截了静态资源,根据/pages/books.html去controller找对应的方法,找不到所以会报404的错误。
(2)SpringMVC为什么会拦截静态资源呢?
(3)解决方案?
SpringMVC需要将静态资源进行放行。
@Configuration
@ComponentScan({"com.itheima.controller","com.itheima.config"})
@EnableWebMvc
public class SpringMvcConfig { }
或者
@Configuration
@ComponentScan("com.itheima")
@EnableWebMvc
public class SpringMvcConfig { }
17-SSM整合 (整合配置)
(1) 创建工程
创建一个Maven的web工程
pom.xml添加SSM需要的依赖jar包
编写Web项目的入口配置类,实现AbstractAnnotationConfigDispatcherServletInitializer重写以下方法
getRootConfigClasses() :返回Spring的配置类->需要==SpringConfig==配置类
getServletConfigClasses() :返回SpringMVC的配置类->需要==SpringMvcConfig==配置类
getServletMappings() : 设置SpringMVC请求拦截路径规则
getServletFilters() :设置过滤器,解决POST请求中文乱码问题
(2)SSM整合[==重点是各个配置的编写==]
SpringConfig
标识该类为配置类 @Configuration
扫描Service所在的包 @ComponentScan
在Service层要管理事务 @EnableTransactionManagement
读取外部的properties配置文件 @PropertySource
整合Mybatis需要引入Mybatis相关配置类 @Import
第三方数据源配置类 JdbcConfig
构建DataSource数据源,DruidDataSouroce,需要注入数据库连接四要素, @Bean @Value
构建平台事务管理器,DataSourceTransactionManager,@Bean
Mybatis配置类 MybatisConfig
构建SqlSessionFactoryBean并设置别名扫描与数据源,@Bean
构建MapperScannerConfigurer并设置DAO层的包扫描
SpringMvcConfig
标识该类为配置类 @Configuration
扫描Controller所在的包 @ComponentScan
开启SpringMVC注解支持 @EnableWebMvc
(3)功能模块[与具体的业务模块有关]
创建数据库表
根据数据库表创建对应的模型类
通过Dao层完成数据库表的增删改查(接口+自动代理)
编写Service层[Service接口+实现类]
@Service
@Transactional
整合Junit对业务层进行单元测试
@RunWith
@ContextConfiguration
@Test
编写Controller层
接收请求 @RequestMapping @GetMapping @PostMapping @PutMapping @DeleteMapping
接收数据 简单、POJO、嵌套POJO、集合、数组、JSON数据类型
@RequestParam
@PathVariable
@RequestBody
转发业务层
@Autowired
响应结果
@ResponseBody