• [SpringMVC]REST入门案例与优化


    REST入门案例

    案例需求与思路分析

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

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

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

    修改后: 增删改查: /users

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

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

    环境准备

    • 创建一个Web的Maven项目

    • pom.xml添加Spring依赖

      
      
      <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.0modelVersion>
      
        <groupId>com.nefugroupId>
        <artifactId>springmvc_tryartifactId>
        <version>1.0-SNAPSHOTversion>
        <packaging>warpackaging>
      
        <dependencies>
          <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>javax.servlet-apiartifactId>
            <version>3.1.0version>
            <scope>providedscope>
          dependency>
          <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-webmvcartifactId>
            <version>5.2.10.RELEASEversion>
          dependency>
          <dependency>
            <groupId>com.fasterxml.jackson.coregroupId>
            <artifactId>jackson-databindartifactId>
            <version>2.9.0version>
          dependency>
        dependencies>
      
        <build>
          <plugins>
            <plugin>
              <groupId>org.apache.tomcat.mavengroupId>
              <artifactId>tomcat7-maven-pluginartifactId>
              <version>2.1version>
              <configuration>
                <port>80port>
                <path>/path>
              configuration>
            plugin>
          plugins>
        build>
      project>
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
    • 创建对应的配置类

      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 {
      }
      
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
    • 编写模型类User

      public class User {
          private String name;
          private int age;
          //getter...setter...toString省略
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • 编写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'}";
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38

    修改REST风格

    现在我们将UserController进行改造:

    新增

    @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'}";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 将请求路径更改为/users

      • 访问该方法使用 POST: http://localhost/users
    • 使用method属性限定该方法的访问方式为POST

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

        在这里插入图片描述

    删除

    @Controller
    public 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'}";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 将请求路径更改为/users
      • 访问该方法使用 DELETE: http://localhost/users

    访问成功,但是删除方法没有携带所要删除数据的id,所以针对RESTful的开发,如何携带数据参数?

    传递路径参数

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

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

    • 修改@RequestMapping的value属性,将其中修改为/users/{id},目的是和路径匹配
    • 在方法的形参前添加@PathVariable注解
    @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'}";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    思考如下两个问题:

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

    在这里插入图片描述

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

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

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

    @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'}";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    修改

    @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'}";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 将请求路径更改为/users

      • 访问该方法使用 PUT: http://localhost/users
    • 访问并携带参数:

      在这里插入图片描述

    根据ID查询

    @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'}";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    将请求路径更改为/users

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

    查询所有

    @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'}";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    将请求路径更改为/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

    名称@PathVariable
    类型形参注解
    位置SpringMVC控制器方法形参定义前面
    作用绑定路径参数与处理器方法形参间的关系,要求路径参数名与形参名一一对应

    关于接收参数,我们学过三个注解@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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

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

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

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

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

    使用@GetMapping  @PostMapping  @PutMapping  @DeleteMapping代替
    
    • 1

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

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

    快速开发总结

    知识点1:@RestController

    名称@RestController
    类型类注解
    位置基于SpringMVC的RESTful开发控制器类定义上方
    作用设置当前控制器类为RESTful风格,
    等同于@Controller与@ResponseBody两个注解组合功能

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

    名称@GetMapping @PostMapping @PutMapping @DeleteMapping
    类型方法注解
    位置基于SpringMVC的RESTful开发控制器方法定义上方
    作用设置当前控制器方法请求访问路径与请求动作,每种对应一个请求动作,
    例如@GetMapping对应GET请求
    相关属性value(默认):请求访问路径
  • 相关阅读:
    【附源码】计算机毕业设计SSM网上购物系统
    css文字超出元素省略,单行、多行省略
    MySQL-DML语言-数据库操作语言-
    装饰模式Decorator
    LeetCode【65. 有效数字】
    java设计模式和面向对象编程思想
    4 | Nikto使用
    线上展厅制作成本
    【PAT甲级】1146 Topological Order
    自动驾驶中的坐标系变换
  • 原文地址:https://blog.csdn.net/zyb18507175502/article/details/125887313