REST简介
REST(Representational State Transfer),表现形式状态转换,它是一种软件架构风格。当我们像表示一个网络资源的时候,可以使用两种方式:
- 传统风格资源描述形式:
http://localhost:8080/springmvc/user/getById?id=1 查询id为1的用户信息
http://localhost:8080/springmvc/user/saveUser 保存用户信息 - REST风格
http://localhost/user/1
http://localhost:user
相比起传统风格资源描述形式,REST的优点有:
- 隐藏资源的访问行为,无法通过地址地址对资源是何种操作
- 简化书写
按照REST风格访问资源时,使用行为动作(请求方式)区分对资源进行何种操作,通常情况下:GET表示查询、POST表示新增、PUT表示修改、DELETE表示删除。
需要注意的是:REST是一种风格而不是规范。并且REST中描述模块的方式通常使用复数,比如users…
REST提供了对应的架构方式,按照这种架构设计项目可以降低开发的复杂性,提高系统的伸缩性。
根据REST风格对资源进行访问称为RESTful。
REST入门案例
环境准备
- 创建maven结构的web项目(略)
- 配置tomcat服务器(略)
- 在pom.xml配置坐标
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
- 创建并编写web配置类
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
//使用过滤器解决post请求中文乱码问题
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("utf-8");
return new Filter[]{filter};
}
}
- 创建并编写SpringMVC配置类
@Configuration
@ComponentScan("com.itheima.controller")
@EnableWebMvc
public class SpringMvcConfig {
}
- 编写UserController类
@Controller
public class UserController {
@RequestMapping(value = "/save",produces = "application/json;charset=utf-8")
@ResponseBody
public String save(){
System.out.println("调用UserController下的save,,,");
return "{'姓名':'kouchiyo'}";
}
}
@RequestMapping注解中的produces = "application/json;charset=utf-8"
是为了解决json的中文数据返回前端乱码。
- 启动服务器,使用PostMan发送请求
修改为REST风格
接下来在原先代码的基础上修改成REST风格。接下来我们修改新增和删除方法。
新增:
@RequestMapping(value = "/users",produces = "application/json;charset=utf-8",method = RequestMethod.POST)
@ResponseBody
public String save(){
System.out.println("调用UserController下的save,,,");
return "{'姓名':'kouchiyo'}";
}
删除:
@RequestMapping(value = "/users/{id}",produces = "application/json;charset=utf-8",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id){
System.out.println("调用UserController下的delete方法,删除id为"+id+"的记录...");
return "{'姓名':'kouchiyo'}";
}
可以看到,在新增方法中通过在@RequestMapping中添加method = RequestMethod.POST
,并修改value = "/users"
即可变成Rest风格。在删除方法中,因为涉及到参数传递,需要获取前端发送的id值。因此比起新增方法@RequestMapping中的value = "/users/{id}"
,并且需要在方法的形参前添加注解@PathVariable
。对于修改和查询也进行类似的修改即可。
UserController代码如下:
//RESTful入门案例
@Controller
public class UserController {
@RequestMapping(value = "/users",produces = "application/json;charset=utf-8",method = RequestMethod.POST)
@ResponseBody
public String save(){
System.out.println("调用UserController下的save,,,");
return "{'姓名':'kouchiyo'}";
}
@RequestMapping(value = "/users/{id}",produces = "application/json;charset=utf-8",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id){
System.out.println("调用UserController下的delete方法,删除id为"+id+"的记录...");
return "{'姓名':'kouchiyo'}";
}
}
REST快速开发
通过查看上面的REST开发入门中UserController的代码我们可以发现:代码中存在大量重复的注解。比如所有方法前都有@ResponseBody。所有方法的@RequestMapping中都存在相同的部分。为了解决代码中存在重复注解的问题。SpringMVC专门为REST风格提供了一系列注解。演示代码如下:
//RESTful快速开发
@RestController //等于ResponseBody + Controller
@RequestMapping(value = "/account",produces = "application/json;charset=utf-8")
public class AccountController {
@GetMapping
public String findAll(){
System.out.println("调用AccountController下的findAll,,,");
return "{'姓名':'kouchiyo'}";
}
@PostMapping
public String save(){
System.out.println("调用AccountController下的save,,,");
return "{'姓名':'kouchiyo'}";
}
@DeleteMapping("/{id}")
public String delete(@PathVariable Integer id){
System.out.println("调用AccountController下的delete方法,删除id为"+id+"的记录...");
return "{'姓名':'kouchiyo'}";
}
}
从上面的演示代码可以发现,Controller类中的所有方法上的@ResponseBody
都省略了,取而代之的是使用@RestController
替换@Controller
。@RestController
等于@ResponseBody
+ @Controller
使用@GetMapping/@PostMapping/@PutMapping/@DeleteMapping
来代替@RequestMapping
中的method属性。
案例:基于RESTful页面数据交互
需求分析
- 需求一:图片列表查询,从后台返回数据,将数据展示在页面上
- 需求二:新增图片,将新增图书的数据传递到后台,并在控制台中打印
说明:此次案例的重点是在SpringMVC中如何使用RESTful实现前后台交互,所以本案例中没有和数据库进行交互。
项目构建
本次案例是在REST快速开发的基础上所构建。以下是步骤分析:
- 编写Controller类,提供两个方法,一个用来做列表查询,一个用来做新增
- 在方法上使用RESTful进行路径设置
- 完成请求、参数的接收和结果的响应
@RestController
@RequestMapping("/books")
public class BookController {
@PostMapping
public String save(@RequestBody(required = false) 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 = new Book();
book.setId(1);
book.setName("书名");
book.setType("书的类型");
book.setDescription("书的描述");
bookList.add(book);
return bookList;
}
}
-
使用PostMan进行测试
使用GET方法对getAll进行测试:
使用POST方法对save进行测试:
-
将前端页面拷贝到项目中
当我们把前端页面拷贝到项目中后,启动服务器并访问pages文件夹下的books.html页面。我们会发现页面无法访问会报404错误。
出现错误的原因是:在web配置类中,我们设置了所有资源都会被SpringMVC拦截。当我们在地址栏中输入http://localhost:8080/springmvc2/pages/books.html
后,SpringMVC会去Controller类中找对应的方法,没有该方法所以报错。
解决方案:SpringMVC需要将静态资源放行,需要专门为静态资源放行创建一个配置类继承WebMvcConfigurationSupport。
@Configuration //设置静态资源访问过滤,当前类需要被设置为配置类,并被扫描加载
public class SpringMVCSupport extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
//当访问/pages/??时候,从/pages目录下查询内容
registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
}
}
在创建完以上的配置类以后,还需要被SpringMVC的配置类扫描到,修改SpringMVC配置类的注解为:@ComponentScan({"com.itheima.controller","com.itheima.config"})
在地址栏中驶输入http://localhost:8080/springmvc2/pages/books.html
测试页面能否正常访问。
- 页面发送ajax请求
- 完成页面数据的展示
页面显示所有数据:
前端通过新建功能向后端传值:
后端控制台打印前端发送结果
学习总结
REST是一种风格而不是规范。
使用REST风格对资源进行描述的好处有两个:1.简化书写 2.隐藏资源访问行为
如果想使用REST风格,可以在传统方式访问资源的基础上,修改@RequestMapping中的value属性以及添加method属性。当需要传递单个参数时,还需要在方法的形参前添加@PathVariable注解。