Restful风格的编程

  • 1、 Restful简介
  • 2、查询用户以及用户详情
    • 2.1常用注解
    • 2.2查询用户详情
  • 3、处理创建请求
    • 3.1@RequestBody注解
      • 3.1.1用途
      • 3.1.2语法规范
    • 3.2日期类型的处理
    • 3.3BindingResult
  • 4、用户信息修改与删除
    • 4.1用户信息修改
    • 4.2案例
      • 前端界面
      • 后端控制器

1、 Restful简介

Restful比较热门,,Spring的微服务是基于Restful风格搭建的框架。
Restful有一下几个特点:

  1. 使用URL描述资源。
  2. 使用HTTP方法描述行为,使用HTTP状态码来表示不同的结果。
  3. 使用JSON交互数据。
  4. Restful只是一种风格,不是强制标准。

2、查询用户以及用户详情

最简单的,最常用的GET请求,用于查询全部数据或者其中一条数据的详情。

2.1常用注解

常用注解作用
@RestController表明此tController 提供的是Restful服务
@RequestMapping将URL映射到Java
@RequestParam映射请求参数到Java上的参数
@PageableDefault指定分页参数的默认值

2.2查询用户详情

@RequestMapping(value="/manage", method= {RequestMethod.GET})public String list(String userId,Map<String,Object> map) {if(userId==""||userId==null) {map.put("userList", userService.getUserList());}else {map.put("userList",userService.getUserById(Integer.parseInt(userId)));}return "user/list";}

3、处理创建请求

3.1@RequestBody注解

3.1.1用途

用于接收前端传递给后端的json字符串中的数据。(处理json格式的数据)
@RequestBody用来接收前端传递给后端的json字符串中的数据,GET方式的请求一般通过URL中携带key-value参数,而@RequestBody接收的是请求体中的数据(json格式的数据,只有请求体中能保存json),所以使用@RequestBody接收数据的时候必须是POST方式等方式。
@RequestBody与@RequestParam()可以同时使用,但@RequestBody最多只能有一个,而@RequestParam()可以多个。

3.1.2语法规范

(@RequestBody Map map)(@RequestBody Object object)

(@RequestBody Map map)先对简单,将json解析成Map形式的key-value对,直接通过map.get(“KeyName”)就能拿到值了
(@RequestBody Object object) 通过json字符串中的key来匹配对应实体类的属性如果匹配一致且json中的该key对应的值符合实体类的对应属性的类型要求时,会调用实体类的setter方法将值注入到该属性。
例如

public Result deleteBookById(@RequestBody HashMap<String, String> map) {        this.bookService.deleteBookById(Long.parseLong(map.get("id")));        return Result.createWithSuccessMessage();    }public Result updateBookById(@RequestBody Book book){        Book record = this.bookService.updateBookById(book);        return Result.createWithModel(record);    }

注意:

在(@RequestBody Object object)中,前端POST过来的数据会通过反序列数据到实体类中,并且在反序列的过程中会进行类型的转换。
在json中应该用null来代表空值,如果是”“(空字符串)会判断为空串,如果实体类属性是String类型的,那么接受到的就是””,如果实现类属性类型是Integer、Double等类型,那么接收到的就是null。

{name:"",age:null}

(@RequestBody Object object)内部是通过传递过来的数据中的Key寻找setter方法,有则调用,无则不作任何操作(其实可以设计)。
如果通过Key匹配到setter方法,但是Value无法转换为对应的实例类属性的类型时,抛出异常。

3.2日期类型的处理

前端传入日期格式: yyyy-MM-dd HH:mm:ss,例如:2018-07-09 12:55:12(不使用时间戳,前后双方联调时查看起来更加友好)

后端返回日期格式: yyyy-MM-dd HH:mm:ss,例如:2018-07-09 12:55:12(不使用时间戳,前后双方联调时查看起来更加友好)

后端json序列化、反序列化框架: 定义任何一种高效的json工具都行,例如:Fastjson、Gson、Jackson lib

序列化、反序列化日期格式规范: pattern=”yyyy-MM-dd HH:mm:ss”,timezone = “GMT+8”,除特出场景可以使用pattern=”yyyy-MM-dd”,timezone = “GMT+8”

不要随意自定义convert处理日期格式以及其他特殊格式转换,应该交由基础框架组或架构组统一在框架层面解决,对业务开发透明,或者在有些小公司由Leader或高开来担当。

3.3BindingResult

/*     * 添加用户,使用@RequestBody将请求体映射到Action方法参数中     * 使用@Valid注解验证请求参数的合法性     * 使用BindingResult处理校验结果     * @param user     * @param result     * @return     */      @PostMapping("/user")      public User create(@Valid @RequestBody User user, BindingResult result){         if(result.hasErrors()){             result.getAllErrors().stream().forEach(error -> {                 FieldError fieldError = (FieldError)error;                 String message = fieldError.getField() + " " + error.getDefaultMessage();                 System.out.println(message);             });             return null;         }         System.out.println(user.toString());         user.setId(5l);         return user;     }

4、用户信息修改与删除

PUT和DELETE并不复杂,大家也熟悉,用于对后台数据的更新和删除。

4.1用户信息修改

对资源更新的请求方法通常是是PUT,但有时候也可能是POST。那么问题来了,都是更新资源区别在哪里?

PUTPOST
在HTTP中PUT被定义为幂等的请求方法而POST则不是
操作是作用于一个具体资源之上作用于一个集合资源之上
URL在客户端确定使用PUTURL在服务端确定使用POST

比较直观的是资源URL的不同
——

4.2案例

前端界面

        Title                $(function () {            // 查询所有            $('#btn1').click(function () {                $.get('/employees', function (data) {                    console.log(data);                });            });            // 查询一个            $('#btn2').click(function () {                $.get('/employees/10', function (data) {                    console.log(data);                });            });            // 添加            $('#btn3').click(function () {                $.post('/employees', "id=11", function (data) {                    console.log(data);                });            });            // 修改            $('#btn4').click(function () {                $.ajax({                    url: "/employees",                    type: "PUT",                    data: {id: 1, name: "小肥羊", age: 10},                    success: function (data) {                        console.log(data);                    }                });            });            // 删除            $('#btn5').click(function () {                $.ajax({                    url: "/employees/13",                    type: "DELETE",                    data: {id: 1},                    success: function (data) {                        console.log(data);                    }                });            });        });    

后端控制器

package com.yy.web.controller;import com.yy.domain.Employee;import com.yy.util.JsonResult;import org.springframework.stereotype.Controller;import org.springframework.stereotype.Repository;import org.springframework.web.bind.annotation.*;import java.util.Arrays;import java.util.List;/** * @program: restful-demo * @ClassName: EmployeeController * @description: * @author: YanYang * @create: 2021-06-23 15:04 **/@RestController@RequestMapping("employees")public class EmployeeController {    /**     * 2个接口设计都是用相同资源,相同请求方法,此时 SpringMVC 无法识别,     * 认为是同一方法,报错:Ambiguous mapping. [模糊映射]     *     * RESTful 解决方案:使用 参数路径 方式     *      具体实现:将参数作为请求映射路径一部分,[参与映射路径区分]     *      比如:查询指定 id 的员工信息接口设计     *      @RequestMapping(value = "/employees/{id}", method = RequestMethod.GET)     *      其中 "/employees/{id}" 参数路径,{id} 就是路径参数     *     *      访问该接口时:http:localhost:8080/employees/1  其中 1 是 id 参数     *      接口接收路径参数:使用 @PathVariable,表示将参数路径上的参数解析,并赋值给指定变量     *      如果路径参数与变量名不一致,使用 @PathVariable("eid")明确指定     *     */    // 查询所有(数据是模拟的)//    @RequestMapping(value = "/employees", method = RequestMethod.GET)    @GetMapping    public List list() {        return Arrays.asList(new Employee(1L,"小肥羊", 10), new Employee(2L, "熊大", 11));    }    // 查询单个(数据是模拟的)//    @RequestMapping(value = "/employees/{id}", method = RequestMethod.GET)    @GetMapping("/{eid}")    public Employee queryById(@PathVariable("eid") Long id) {        System.out.println("查询单个 = " + id);        return new Employee(3L, "熊二", 8);    }    // 添加(数据是模拟的)//    @RequestMapping(value = "/employees", method = RequestMethod.POST)    @PostMapping    public Employee add(@ModelAttribute("employee") Employee employee) {        System.out.println("添加 = " + employee.getId());        return employee;    }    // 修改(数据是模拟的)//    @RequestMapping(value = "/employees", method = RequestMethod.PUT)    @PutMapping    public Employee update(@ModelAttribute("employee") Employee employee) {        System.out.println("修改 = " + employee.getId());        employee.setId(employee.getId());        employee.setName(employee.getName());        employee.setAge(employee.getAge());        return employee;    }    // 删除(数据是模拟的)//    @RequestMapping(value = "/employees/{id}", method = RequestMethod.DELETE)    @DeleteMapping("/{id}")    public String delete(@PathVariable Long id) {        System.out.println("删除 = " + id);        if (id != null && 1 == id) {            return "删除成功";        }        return "删除失败";    }}


求三连!!!!!