一.开发第一个RESTful应用
本节讲解一个全新的话题,RESTful开发风格。
REST :全称Representational State Transfer(表现层状态转换),资源在网络中,以某种表现形式进行状态转移。听起来很难理解,其实说白了就是在我们web环境下,如果你要获取某个图片,js,网页这些资源的时候,就要以url的形式进行表现。我们访问一个图片的网址,那这个资源返回的就自然是一张图片,如果访问的是一个CSS,那返回的就是一个CSS。好像这种设计理念对于我们的web应用来说是在再基础不过的东西。其实这是rest给我们提出来的一个设计理念,在web环境以URL的方式,来进行资源的传递。那么基于这种REST的理念,注意,是理念,不是具体的实现。
RESTful是基于REST理念的一套开发风格,是具体的开发规则。 下面通过一个图来进行解释:
在这个图的最左侧,我们的客户端已经不再是标准的浏览器了,而是包含了像iPhone和安卓系统里所运行的小程序和app,都是可以作为客户端来使用的。而RESTful开发风格下,我们也并不拘泥于客户端必须是浏览器。那客户端和服务器之间如何交互呢?在这里,我打个比方。比如iPhone中有一个小程序向这个URL发送了一个请求,而这个请求被发送到了web端的服务器,那请求在被处理了以后,关键的区分来了,作为服务器端返回的已经不再是某一个HTML的文本,而是像json或是xml这样的数据。作为RESTful最典型的特征就是,我们服务器端只返回数据 ,这种数据以json或者是xml的方式进行体现。同时返回的数据要求不包含任何与展现相关的内容。当这些数据被送回到客户端以后,再由客户端对这些数据进行渲染和展现。比如我们PC端的浏览器接收到这个JSON以后,可能是以一个表格的形式在浏览器中进行展现,而iPhone或者安卓这种移动端的小屏幕的话,它可能会以滑动列表的形式进行展现。那如何展现呢?这就是客户端的事情了。作为服务器,我不管你客户端使用的是小程序,app还是浏览器,只管专注产生数据就行了,至于数据以什么形式展现出来,那是客户端的事情。这样做最大的好处就是我们开发服务器的后端工程师,只用专注数据,不用关注任何展现。而前端的每一个工程师也不用去关注后台是如何产生数据的。只需要拿到这个字符串进行解析就可以了。在开发的过程中,前端的工程师和后端的工程师可以同步进行,只要我们约定好传递字符串的格式和url就可以了。通过基于RESTful开发风格所编写的程序在行业中还有一个名词叫做前后端分离。前端只负责界面开发,后端只需要专注于业务逻辑就可以了。
RESTful开发规范
1.使用URL作为用户交互入口。
2.明确的语义规范(GET | POST | PUT | DELETE)
这里的语义规范是指在http发送请求的时候,例如get请求或post请求他们自己所实现的含义是有所不同的。在我们日常开发中最常用的http发送的方式有四种GET 、 POST 、PUT 、DELETE。但是后两者我们几乎没有见过,那是为什么呢?是因为在web环境下,只支持get或post请求,不支持put和delete请求。所以我们之前写代码看不到这两种请求。但是看不到,并不代表没有。作为REST在进行语义规范定义的时候,get、post、put、delete其实分别对应了查询操作、新增操作、更新操作、删除操作。也就是说,同一个URL在向服务器发送请求的时候,使用了不同的请求方式,那他在服务器端进行的处理是不一样的。例如你发送一个get请求到服务器端,那程序按照RESTful开发规范,就必须只是一个查询操作,返回请求所对应的数据。那如果是post请求,post对应的是新增操作,那在服务器端的controller中,就要完成对某个数据的新增操作。而put就是数据的更新操作,delete是删除操作。通过遵循RESTful开发规范,当我们看到这个请求的类型的时候,我们就找到要做增删改查的哪一种了。
3.只返回数据(json | xml) ,不包含任何展现。 也就是指在我们服务器产生的数据通常是以json字符串或者xml字符串。日常开发中,优先推荐返回json数据,因为json数据无论是从可读性,还是解析的角度都要比xml简单得多。并且json天然地被JavaScript支持,使用起来更方便。因此主流地web框架,比如说SpringBoot , SpringMVC它都是默认对json提供了良好的支持。
下面举一个例子来举例一下,RESTful怎么写是对的,怎么写是错的。
RESTful命名要求
菜鸟教程也有关于RESTful的相关文章:https://www.runoob.com/w3cnote/restful-architecture.html
开发第一个RESTful应用
创建一个普通的maven项目,按照以前的规范导入web模块后,然后在pom.xml中导入springmvc的依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.13</version> </dependency>
然后配置web.xml。在里面配置DispatcherServlet和CharacterEncodingFilter,代码如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!--配置DispatcherServlet--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--加载applicationContext.xml--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param> <!--在web应用启动时,自动创建Spring IoC容器,并初始化DispatcherServlet--> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!--"/"代表要拦截所有的请求--> <url-pattern>/</url-pattern> </servlet-mapping> <!--将请求的字符集转换为UTF-8,CharacterEncodingFilter比DispatcherServlet优先执行--> <filter> <filter-name>characterFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterFilter</filter-name> <!--对所有的请求进行过滤--> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
配置applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"> <!--自动扫描组件,自动扫描符合条件的bean--> <context:component-scan base-package="com.haiexijun.restful"></context:component-scan> <!--启用Spring MVC的注解开发模式--> <mvc:annotation-driven> <!--配置消息转换器,让响应输出到浏览器以后,以text/html;charset=utf-8输出,解决html里面的中文乱码问题--> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=utf-8</value> <value>application/json;charset=utf-8</value> </list> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> <!--将图片/JS/CSS等静态资源排除在外,可提高执行效率--> <mvc:default-servlet-handler/> </beans>
在com.haiexijun.restful包下创建controller控制器包,并在包下面创建一个全新的java类RestfulController。然后书写如下的代码:
package com.haiexijun.restful.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller @RequestMapping("/restful") public class RestfulController { @GetMapping("request") @ResponseBody public String doGetRequest(){ //注意这里模拟返回一个json字符串 return "{\"message\":\"返回查询结果\"}"; } }
到这里,一个RESTful风格的程序就写好了。你可能会有疑问,这不就是我之前学习过的东西吗?他怎么就是RESTful呢?其实,restful解释一种编码的风格,不是一种新的技术。作为restful我们要求,url所有的部分都是名词,除此以外返回的数据也要求是一个json,或者是一个xml格式的数据。同时get、post、put、delete这四种请求也有不同的涵义。上面定义get请求,我们返回的就是查询的结果。
运行结果如下:
html可以通过ajax技术来使用这个json数据。下面继续来开发restful。来模拟一下客户端页面与restful交互的过程.
二.RESTful基本使用
上一节开发了一个Controller,实现了标准的RESTful风格,本节就来开发html的客户端与服务器端的RESTful进行交互。
返回刚才的工程,在webapp目录下放入jquery.js 文件。等下要用到它来完成Ajax的请求。然后创建一个标准的html页面,这里我叫做index.html。index.html编写如下代码?
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>RESTful</title> <script src="jquery.js"></script> <script> $(function (){ $("#btnGet").click(function (){ $.ajax({ url:"/restful/request", type:"get", dataType:"json", success:function (data){ $("#message").text(data.message) } }) }) }) </script> </head> <body> <input type="button" id="btnGet" value="发送Get请求"> <h1 id="message"></h1> </body> </html>
运行后点击按钮获取数据:
下面在程序中体验一下post等其他请求,在controller中添加如下代码:
这里mapping都为request其实问题不大,因为请求的方式不同。
@PostMapping("/request") @ResponseBody public String doPostRequest(){ return "{\"message\":\"数据新建成功\"}"; } @PutMapping("/request") @ResponseBody public String doPutRequest(){ return "{\"message\":\"数据更新成功\"}"; } @DeleteMapping("/request") @ResponseBody public String doDeleteRequest(){ return "{\"message\":\"数据删除成功\"}"; }
当然,这里只是为了方便学习写成这样的,真正开发肯定不是这样写的。在html中更改ajax的http请求类型就可以了,这里不进行测试了。