[TOC]

RESTful 开发风格

  • REST - 表现层状态转换,资源在网络中以某种表现形式进行状态转移
  • RESTful是基于REST理念的一套开发风格,是具体的开发规则

RESTful 开发规范

  • 使用URL作为用户交互入口
  • 明确的语义规范(GET POST PUT DELETE)
  • 只返回数据(JSON|XML) 不包含任何展现

20200320-192938.jpg
20200320-202706.jpg20200320-203105.jpg

基本的使用

/**
 * @author prim
 */
@Controller
@RequestMapping("/restful")
public class RestfulController {

    //------------------------------ 基本的使用 -----------------------------------------//
    @GetMapping("/t")
    @ResponseBody
    public String test() {
        return "{\"message\":\"This is Message 中文\"}";
    }

    @PostMapping("/t")
    @ResponseBody
    public String doPostRequest(){
        return "{\"message\":\"This is Message POST请求 增加操作\"}";
    }

    @PutMapping("/t")
    @ResponseBody
    public String doPutRequest(){
        return "{\"message\":\"This is Message PUT请求 更新操作\"}";
    }

    @DeleteMapping("/t")
    @ResponseBody
    public String doDeleteRequest(){
        return "{\"message\":\"This is Message DELETE请求 删除操作\"}";
    }
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery.min.js"></script>
    <script>
        $(function () {
            $("#btn").click(function () {
                $.ajax({
                    url: "/restful/t",
                    type: "get",
                    dataType: "json",
                    success: function (json) {
                        $("#result").text(json.message);
                    }
                })
            });
            $("#btnPost").click(function () {
                $.ajax({
                    url: "/restful2/t/100",
                    type: "post",
                    dataType: "json",
                    success: function (json) {
                        $("#result").text(json.message + ":" + json.id);
                    }
                })
            });
            $("#btnPut").click(function () {
                $.ajax({
                    url: "/restful/t",
                    type: "put",
                    dataType: "json",
                    success: function (json) {
                        $("#result").text(json.message);
                    }
                })
            });
            $("#btnDelete").click(function () {
                $.ajax({
                    url: "/restful/t",
                    type: "delete",
                    dataType: "json",
                    success: function (json) {
                        $("#result").text(json.message);
                    }
                })
            });
        });
    </script>
</head>
<body>
<h1>This is Test RESTful</h1>
<input id="btn" name="btn" type="button" value="发送GET请求">
<input id="btnPost" name="btn" type="button" value="发送Post请求">
<input id="btnPut" name="btn" type="button" value="发送Put请求">
<input id="btnDelete" name="btn" type="button" value="发送Delete请求">
<h2 id="result"></h2>
</body>
</html>

RestController注解与路径变量


/**
 * @author prim
 */
@RestController //Restful风格的注解 不用在每个方法上写@ResponseBody了
@RequestMapping("/restful2")
public class RestfulController2 {
    ///restful2/t/{?} 放在uri中的变量成为路径变量 这样使用很普遍的
    //POST /restful2/t/100 如何获取到100呢?
    //通过@XXXMapping(/xx/{id}) 注入路径变量
    //通过@PathVariable 注入给参数
    @PostMapping("/t/{rid}")
    public String doPostRequest(@PathVariable("rid") Integer requestId) {
        return "{\"message\":\"This is Message POST请求 增加操作\",\"id\":" + requestId + "}";
    }
}

简单请求和非简单请求

  • 简单请求是指标准结构的http请求,对应GET/POST请求
  • 非简单请求是复杂要求的HTTP请求,指PUT DELETE、扩展标准(如:自定义请求头等)请求
  • 两者最大区别是非简单请求发送前需要发送预检请求

image.png

put和delete请求获取传递的参数,和get和post请求获取参数是不一样的.

$("#btnPut").click(function () {
                $.ajax({
                    url: "/restful/t",
                    type: "put",
                    data: "name=lily&age=23",
                    dataType: "json",
                    success: function (json) {
                        $("#result").text(json.message);
                    }
                })
            });
    @PutMapping("/t")
    @ResponseBody
    public String doPutRequest(Person person) {
        System.out.println(person.getName() + ":" + person.getAge());
        return "{\"message\":\"This is Message PUT请求 更新操作\"}";
    }j

如果正常的传递参数,会无法获取到参数值,而会直接获取到 null:null

注意:必须要需要在web.xml中进行配置FormContentFilter 对于非简单请求的表单处理

 <!-- 支持put和delete 非简单请求 表单处理 -->
    <filter>
        <filter-name>formContentFilter</filter-name>
        <filter-class>org.springframework.web.filter.FormContentFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>formContentFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

JSON 序列化


<!-- jackson依赖 2.9之前的版本会有很严重的漏洞 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.10.3</version>
            <type>bundle</type>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.10.3</version>
        </dependency>

注意:要将新加入的jackson的jar包添加到WEB-INF/lib 中
然后不用其他配置就可以直接使用. 如下会自动返回JSON List的格式


@GetMapping("persons")
    public List<Person> findPersons() {
        List list = new ArrayList();
        Person p1 = new Person();
        p1.setName("lily");
        p1.setAge(23);
        p1.setBirthday(new Date());
        list.add(p1);
        Person p2 = new Person();
        p2.setName("smith");
        p2.setAge(22);
        p2.setBirthday(new Date());
        list.add(p1);
        return list;
    }

jackson 的坑,在时间处理上,不是很理想.需要如下对时间进行处理

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date birthday;

浏览器跨域访问

  • 浏览器同源策略

    同源策略阻止从一个域加载的脚本去获取另一个域上的资源. 只要协议、域名、端口有任何一个不同,都被当作是不同的域 浏览器Console看到Access-Control-Allow-Origin就代表域了

    /**
     * 交给jackson自动调整
     *
     * @param id
     * @return
     */
    @GetMapping("/person")
    public Person findByPersonId(Integer id) {
        Person person = new Person();
        if (id == 1) {
            person.setName("lily");
            person.setAge(23);
        } else {
            person.setName("smith");
            person.setAge(22);
        }
        return person;
    }

    @GetMapping("persons")
    public List<Person> findPersons() {
        List list = new ArrayList();
        Person p1 = new Person();
        p1.setName("lily");
        p1.setAge(23);
        p1.setBirthday(new Date());
        list.add(p1);
        Person p2 = new Person();
        p2.setName("smith");
        p2.setAge(22);
        p2.setBirthday(new Date());
        list.add(p1);
        return list;
    }

HTML 中允许跨域的标签,其他的标签都不允许跨域

  • RESTful - 图5 - 显示远程图片