什么是REST
REST(Representational State Transfer)中文含义是是表现层状态转化。全程应该是Resource Representational State Transfer,省略了Resource (资源)。它允许客户端发出以统一资源标识符(URI)访问和操作网络资源的请求。换句话说,前端(表现层)使用同样的URL地址,完成资源的增加、删除、修改、查询,具体是增加、删除、修改、查询那种操作是由表现层控制的。要深入的了解这个概念,要有以下几个概念去理解
资源和URI :网络上的任何一个具体信息,如:文本、图片、视频等,每种资源对应一个特定的URI(注意这是uri,不是url),URI就成了每一个资源的地址或独一无二的识别符。要想操作该资源访问它的URI就可以。URI只代表资源的实体,不代表它的形式。
表现层(Representation):资源具体呈现出来的形式,叫做它的"表现层",如文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;资源的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对"表现层"的描述
状态转化(State Transfer):服务器端的资源发生变化,如发生:修改、增加、删除等操作,会涉资源的状态的变化。
表现层状态转化:前后端交互技术手段是HTTP协议,前端使用四个操作方式的动词:GET、POST、PUT、DELETE分别对应四种基本操作,完成查询、增加、删除、修改服务器端的资源发生状态变化,这些动作是由前端发出的就叫"表现层状态转化"。
简单小结:每一个URI代表一种资源;客户端和服务器之间,传递这种资源的某种表现层;客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。符合REST规范的软件架构就是restful编程风格。
什么是RESTful风格编程
RESTful是一种编程风格,确切说是一种按照rest要求的编程规范。这种规范主要有两条:
- 资源(数据)的增删改查使用统一资源定位符(URI),前端使用post、delete、put、get传递对资源的增删改查。
传统查询id=1的用户写法:http://…/users/getUserById?id=1;
restful风格要求写法: http://…/users/1
这里http://…/users/1 只标识了服务器上有一个id=1的用户数据,它可以代表查询id为1的用户,同时也代表了删除id为1的用户,查询还是删除,需要根据前段传递的是get、还是delete。 - URI是资源定位符,因此所有路径名必须是名词,不能是动词。如:http://…/getAllUser是不符合规范的。
SpringMVC对RESTful编程风格支持
使用RESTful编程风格时,springmvc需要修改以下配置。
- web.xml中的DispatcherServlet的/;“/”后不带任何的后缀,表示拦截所有没有受理的请求。同时,由于from表单并不支持put、delete,因此需要增加一个过滤器org.springframework.web.filter.HiddenHttpMethodFilter,将前段传递过来post请求细分为put、delete或post请求。完整的web.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--处理中文乱码问题-->
<filter>
<filter-name>encodingFilter</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
- 修改springmvc配置文件,添加<mvc:resources location=“/js/” mapping=“/js/**” />配置静态资源的访问映射,此配置中的文件将不被前端控制器拦截,
所有的配置文件完成后,就可以做简单的restful风格的编码的测试
@RestController
@RequestMapping("/product")
public class ProductController {
private static List<Productvo> products = new ArrayList<>();
static {
Productvo product = new Productvo();
product.setId(1);
product.setProductName("联想笔记本");
product.setProductDesc("thinkpad T 系列");
products.add(product);
Productvo product2 = new Productvo();
product2.setId(2);
product2.setProductName("Dell笔记本");
product2.setProductDesc("移动工作站 系列");
products.add(product2);
}
@GetMapping("/{id}")
public Map getDataById(@PathVariable("id") Integer id){
System.out.println(id);
Map<String,Object> map = new HashMap<>();
Iterator<Productvo> it = products.iterator();
while(it.hasNext()){
Productvo vo = it.next();
if(id==vo.getId()){
map.put("vo",vo);
}
}
if(map.size()==0){
map.put("msg","没有找到id="+id+"数据");
}
return map;
}
@DeleteMapping("/{id}")
public Map delete(@PathVariable("id") Integer id){
System.out.println(id);
Map<String,String> map = new HashMap<>();
map.put("msg","删除成功");
return map;
}
@PostMapping
public Map insert(@RequestBody Productvo product){
/* Productvo product = JSONObject.parseObject(dddd,Productvo.class);*/
System.out.println(product.toString());
Map<String,String> map = new HashMap<>();
map.put("msg","添加成功");
return map;
}
@PutMapping
public String update(@RequestBody Productvo dddd){
System.out.println(dddd.toString());
return "{msg:'修改成功'}";
}
}
测试结果:
查询:
新增
修改
删除
前后端完全分离和restful编程风格
RESTful编程风格对于简单的增删改查简单明了,但对复杂的操作就很不友好,实际的开发中在URL地址中包含动词,更通俗易懂。RESTful编程风格和前后端分离的概念并不一样,当我们把服务器提供的信息都看成一种资源,前后端传递的数据使用JSON格式(当然多媒体文件传递不是json格式),后端只提供数据及根据前段的请求完成对数据的操作,页面的跳转使用前端路由时,使用ajax进行异步通讯时,才形成真正意义的前后端完全分离。具有rest编程风格的SpringMVC成为当前Java web开发主流技术。