写点什么

[SpringMVC]REST 入门案例与优化

作者:fake smile by
  • 2022 年 9 月 21 日
    黑龙江
  • 本文字数:5075 字

    阅读完需:约 17 分钟

REST 入门案例

案例需求与思路分析

需求:将之前的增删改查替换成 RESTful 的开发方式。


1.之前不同的请求有不同的路径,现在要将其修改为统一的请求路径


修改前: 新增: /save ,修改: /update,删除 /delete...


修改后: 增删改查: /users


2.根据 GET 查询、POST 新增、PUT 修改、DELETE 删除对方法的请求方式进行限定


3.发送请求的过程中如何设置请求参数?

环境准备

  • 创建一个 Web 的 Maven 项目

  • pom.xml 添加 Spring 依赖


  <?xml version="1.0" encoding="UTF-8"?>    <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/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>      <groupId>com.nefu</groupId>    <artifactId>springmvc_try</artifactId>    <version>1.0-SNAPSHOT</version>    <packaging>war</packaging>      <dependencies>      <dependency>        <groupId>javax.servlet</groupId>        <artifactId>javax.servlet-api</artifactId>        <version>3.1.0</version>        <scope>provided</scope>      </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>    </dependencies>      <build>      <plugins>        <plugin>          <groupId>org.apache.tomcat.maven</groupId>          <artifactId>tomcat7-maven-plugin</artifactId>          <version>2.1</version>          <configuration>            <port>80</port>            <path>/</path>          </configuration>        </plugin>      </plugins>    </build>  </project>
复制代码


  • 创建对应的配置类


  public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {      protected Class<?>[] getRootConfigClasses() {          return new Class[0];      }        protected Class<?>[] getServletConfigClasses() {          return new Class[]{SpringMvcConfig.class};      }        protected String[] getServletMappings() {          return new String[]{"/"};      }        //乱码处理      @Override      protected Filter[] getServletFilters() {          CharacterEncodingFilter filter = new CharacterEncodingFilter();          filter.setEncoding("UTF-8");          return new Filter[]{filter};      }  }    @Configuration  @ComponentScan("com.nefu.controller")  //开启json数据类型自动转换  @EnableWebMvc  public class SpringMvcConfig {  }
复制代码


  • 编写模型类 User


  public class User {      private String name;      private int age;      //getter...setter...toString省略  }
复制代码


  • 编写 UserController 和 BookController


  @Controller  public class UserController {    @RequestMapping("/save")      @ResponseBody      public String save(@RequestBody User user) {          System.out.println("user save..."+user);          return "{'module':'user save'}";      }        @RequestMapping("/delete")      @ResponseBody      public String delete(Integer id) {          System.out.println("user delete..." + id);          return "{'module':'user delete'}";      }        @RequestMapping("/update")      @ResponseBody      public String update(@RequestBody User user) {          System.out.println("user update..." + user);          return "{'module':'user update'}";      }        @RequestMapping("/getById")      @ResponseBody      public String getById(Integer id) {          System.out.println("user getById..." + id);          return "{'module':'user getById'}";      }        @RequestMapping("/findAll")      @ResponseBody      public String getAll() {          System.out.println("user getAll...");          return "{'module':'user getAll'}";      }  }
复制代码

修改 REST 风格

现在我们将 UserController 进行改造:

新增

@Controllerpublic class UserController {  //设置当前请求方法为POST,表示REST风格中的添加操作    @RequestMapping(value = "/users",method = RequestMethod.POST)    @ResponseBody    public String save() {        System.out.println("user save...");        return "{'module':'user save'}";    }}
复制代码


  • 将请求路径更改为/users

  • 访问该方法使用 POST: http://localhost/users

  • 使用 method 属性限定该方法的访问方式为POST

  • 如果发送的不是 POST 请求,比如发送 GET 请求,则会报错


删除

@Controllerpublic class UserController {    //设置当前请求方法为DELETE,表示REST风格中的删除操作  @RequestMapping(value = "/users",method = RequestMethod.DELETE)    @ResponseBody    public String delete(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 注解


@Controllerpublic 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'}";    }}
复制代码


思考如下两个问题:


(1)如果方法形参的名称和路径{}中的值不一致,该怎么办?



(2)如果有多个参数需要传递该如何编写?


前端发送请求的时候使用:http://localhost/users/1/tom,路径中的1tom就是我们想要传递的两个参数。


后端获取参数,需要做如下修改:


@Controllerpublic 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'}";    }}
复制代码

修改

@Controllerpublic 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 查询

@Controllerpublic 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

查询所有

@Controllerpublic 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

案例总结

RESTful 入门案例,我们需要学习的内容如下:


(1)设定 Http 请求动作(动词)


@RequestMapping(value="",==method== = RequestMethod.==POST|GET|PUT|DELETE==)


(2)设定请求参数(路径变量)


@RequestMapping(value="/users/=={id}==",method = RequestMethod.DELETE)


@ReponseBody


public String delete(==@PathVariable== Integer ==id==){


}

@PathVariable


关于接收参数,我们学过三个注解@RequestBody@RequestParam@PathVariable,这三个注解之间的区别和应用分别是什么?


  • 区别

  • @RequestParam 用于接收 url 地址传参或表单传参

  • @RequestBody 用于接收 json 数据

  • @PathVariable 用于接收路径参数,使用{参数名称}描述路径参数

  • 应用

  • 后期开发中,发送请求参数超过 1 个时,以 json 格式为主,@RequestBody 应用较广

  • 如果发送非 json 格式数据,选用 @RequestParam 接收请求参数

  • 采用 RESTful 进行开发,当参数数量较少时,例如 1 个,可以采用 @PathVariable 接收请求路径变量,通常用于传递 id 值

RESTful 快速开发

做完了 RESTful 的开发,你会发现==好麻烦==,麻烦在哪?



问题 1:每个方法的 @RequestMapping 注解中都定义了访问路径/books,重复性太高。


问题 2:每个方法的 @RequestMapping 注解中都要使用 method 属性定义请求方式,重复性太高。


问题 3:每个方法响应 json 都需要加上 @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'}"; } }
复制代码


对于刚才的问题,我们都有对应的解决方案:


问题 1:每个方法的 @RequestMapping 注解中都定义了访问路径/books,重复性太高。


将@RequestMapping提到类上面,用来定义所有方法共同的访问路径。
复制代码


问题 2:每个方法的 @RequestMapping 注解中都要使用 method 属性定义请求方式,重复性太高。


使用@GetMapping  @PostMapping  @PutMapping  @DeleteMapping代替
复制代码


问题 3:每个方法响应 json 都需要加上 @ResponseBody 注解,重复性太高。


1.将ResponseBody提到类上面,让所有的方法都有@ResponseBody的功能2.使用@RestController注解替换@Controller与@ResponseBody注解,简化书写
复制代码

快速开发总结

知识点 1:@RestController

知识点 2:@GetMapping @PostMapping @PutMapping @DeleteMapping


发布于: 刚刚阅读数: 5
用户头像

fake smile by

关注

还未添加个人签名 2022.07.31 加入

还未添加个人简介

评论

发布
暂无评论
[SpringMVC]REST入门案例与优化_spring_fake smile by_InfoQ写作社区