zoukankan      html  css  js  c++  java
  • Java——Restful风格

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

     服务器端只返回数据,以json或者xml的格式。

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

    RESTful命名要求:

    1.第一个RESTful应用

    @Controller
    @RequestMapping("/restful")  //URL中所有的都是名词
    public class RestfulController {
        @GetMapping(value = "/request",produces = "application/json;charset=utf-8")
        @ResponseBody
        public String doGetRequest(){
            return "{"message":"测试"}";  //使用原义输出
        }
    }

    2.实现RESTful实验室

    一般PC和移动端都可以调用API接口,下面模拟PC端调用,使用Ajax:

     通过ajax发送页面请求:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>RESTful</title>
        <script src="jquery-3.4.1.min.js"></script>
        <script>
            $(function () {
                $("#btnGet").click(function () {
                    $.ajax({
                        url : "/restful/request",
                        type : "get",
                        dataType : "json",
                        success : function (json) {
                            $("#message").text(json.message)
                        }
                    })
                })
            })
        </script>
    </head>
    <body>
    <input type="button" id="btnGet" value="发送Get请求">
    <h2 id="message"></h2>
    </body>
    </html>

    因为定义了webapp为静态文件的根目录,所以client.html可以直接访问。

     竟然产生了乱码,查看请求头,发现采用不正确的字符集。

    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>test/html;charset=utf-8</value>
                        <!--通知浏览器以这种格式加载数据-->
                        <value>application/json;charset=utf-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    添加以上配置就可以了。(只能解决ajax乱码问题)

    3.RestController注解与路径变量

    (1)RestController

    @Controller
    @RequestMapping("/restful")  //URL中所有的都是名词
    public class RestfulController {
        @GetMapping(value = "/request",produces = "application/json;charset=utf-8")
        @ResponseBody
        public String doGetRequest(){
            return "{"message":"测试"}";  //使用原义输出
        }
    }

    如果我们希望返回纯文本数据,我们必须要使用@ResponseBody这个注解。
    如果我们使用@RestController这个注解,那么类下面所有方法都是返回纯文本数据。

    @RestController
    @RequestMapping("/restful")  //URL中所有的都是名词
    public class RestfulController {
        @GetMapping(value = "/request",produces = "application/json;charset=utf-8")
        public String doGetRequest(){
            return "{"message":"测试"}";  //使用原义输出
        }
    }

    @RestController可以帮我们简化开发。

    (2)路径变量

    /request/1 对于放在URL中的变量我们可以称之为路径变量。那么如何取值了?

    @RestController
    @RequestMapping("/restful")  //URL中所有的都是名词
    public class RestfulController {
        @GetMapping(value = "/request/{rid}",produces = "application/json;charset=utf-8")
        public String doGetRequest(@PathVariable("rid") Integer requestId){
            System.out.println(requestId);
            return "{"message":"测试"}";  //使用原义输出
        }
    }

    使用@PathVariable路径变量注解进行接收,而后赋值给方法参数。

    4.JSON序列化

    (1)引入步骤

    导入依赖包:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <!--一定要使用2.9.9之后的版本,否则会有安全问题-->
        <version>2.9.9</version>
    </dependency>
    <!--jackson与目标对象交互的根源-->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.9</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.9.9</version>
    </dependency>

     spring非常智能,只要检查有jackson-core和jackson-databind这两个依赖包。
    就会自动启用jackson为我们提供json序列化服务。

    创建实体类:

    public class Person {
        private String name;
        private String address;
    }

    编写控制器:

    @GetMapping("/person/{pid}")
    public Person findByPersonId(@PathVariable("pid") Integer personId){
        Person person = new Person();
        if (personId == 1){
            person.setName("科比");
            person.setAddress("湖北罗田");
        } else if (personId == 2){
            person.setName("星爷");
            person.setAddress("湖北安陆");
        } else {
            person.setName("无名氏");
        }
        return person;
    }

    如果我们返回一个实体对象,并且配置了@RestController或者@ResponseBody,那么jackson就会自动提供序列化服务。

    访问:

    (2)返回多个对象

    如果一次返回多个对象,我们可以List集合:

    @GetMapping("/persons")
    public List<Person> findPersons(){
        List list = new ArrayList();
        Person p1 = new Person();
        p1.setName("科比");
        p1.setAddress("湖北罗田");
        Person p2 = new Person();
        p2.setName("科比");
        p2.setAddress("湖北罗田");
        list.add(p1);
        list.add(p2);
        return list;
    }

    在前端,我们会收到如下数据:

     在页面中,我们可以通过如下方式进行提取:

    $(function () {
        $("#btnPersons").click(function () {
            $.ajax({
                url : "/restful/persons",
                type : "get",
                datatype : "json",
                success : function (json) {
                    console.info(json)
                    for(var i=0;i<json.length;i++){
                        var p = json[i];
                        $("#divPersons").append("<h2>" + p.name + "-" + p.address + "</h2>")
                    }
                }
            })
        })
    })

    (3)时间处理

    需要注意的是,jackson对时间处理并不友好:
    添加事件属性:
    private Date birthday;
    如果不做处理,就是直接返回事件戳的形式。

     我们只需要添加对应时间注解:
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date birthday;
    就可以正常输出了:

     还有需要注意的是默认使用格林时间,需要指定时区:
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date birthday;

    5.浏览器的同源策略

    同源策略:阻止从一个域加载的脚本去获取另一个域上的资源。
    两个不同域名的网站不能通过Ajax访问,这是出于安全的因素考虑。
    比如下面两个地址,虽然本质是一个页面,但是却属于不同源.

    只要协议、域名、端口有任何不同,都被当做是不同的域。
    浏览器Console看到Access-Control-Allow-Origin就代表跨域了。

    HTML中允许跨域的标签:
      <img> 显式远程图片
      <script> 加载远程JS
      <link> 加载远程CSS

    6.SpringMVC解决跨域

    CORS是一种机制,使用额外的HTTP头通知浏览器访问其他域。
    URL响应头中包含Access-Control-*指明请求允许跨域。

    (1)@CrossOrigin - Controller跨域注解

    @RestController
    @RequestMapping("/restful") 
    @CrossOrigin(origins = {"*"}) 
    public class RestfulController {
        @GetMapping(value = "/request/{rid}",produces = "application/json;charset=utf-8")
        public String doGetRequest(@PathVariable("rid") Integer requestId){
            System.out.println(requestId);
            return "{"message":"测试"}"; 
        }
    }

    (2)<mvc:cors> Spring MVC全局跨域配置

    <mvc:cors>
        <!--path哪一个路径允许跨域访问-->
        <!--allowed-origins允许谁进行跨域访问-->
        <!--max-age设置缓存时间-->
        <mvc:mapping path="*" allowed-origins="*"/>
    </mvc:cors>
  • 相关阅读:
    P1744 采购特价商品
    P1359 租用游艇
    P3092 [USACO13NOV]没有找零No Change
    P1272 重建道路
    P2014 选课
    P1026 统计单词个数
    P1776 宝物筛选_NOI导刊2010提高(02)
    自定义异步非阻塞tornado框架
    tornado进阶篇
    tornado基础篇
  • 原文地址:https://www.cnblogs.com/yangmingxianshen/p/12521605.html
Copyright © 2011-2022 走看看