REST是什么

  1. REST即Representational State Transfer.(资源)表现层状态转换是目前最流行的一种互联网软件架构,他结构清晰,符合标准,易于理解,扩展方便,所以正得到越来越多的网站的采用。
  1. 资源(resources):网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本,一张图片,一首歌曲,一种服务,总之就是一个具体的存在。可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。获取这个资源,访问它的URI就可以了,因此URI即为每一个资源的独一无二的识别符。
  2. 表现层(Representation):把资源具体呈现出来的形式,叫做他的表现层(Representation)。比如,文本可以用txt格式表现,也可以用HTML格式,XML格式,JSON格式表现,甚至可以采用二进制格式。
  3. 状态转换(State Transfer):每发出一个请求,就代表了客户端和服务器的一次交互过程。HTTP协议,是一个无状态协议,即所有状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生“状态转化”(State Transfer)而这种转化是建立在表现层之上的,所以就是“表现层状态转化”
  4. 具体说,就是HTTP协议里面,四个表示操作方式的动词:GET,POST,PUT,DELETE。他们分别对应四种基本操作:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源。
  1. URL风格:

 ※请求路径相同,根据请求方法确定使用哪个方法来处理请求。

    以前实现CRUD(增删改查):

查询:findAll                 GET

插入:insertUser           POST

更新:getUserById        GET        updateUser            PUT

    删除:deletUser             GET

 

    REST风格实现CRUD(增删改查):

    操作          URL                            请求方式

查询:     /user/1001                          GET

插入:     /user/                                   POST

更新:     查询后再修改 /user/            PUT

删除:    /user/1001                          DELETE

 

♦虽然服务端可以处理PUT和DELETE,但是客户端form表单只有GET和POST两种方式向服务器端发送请求。那么请求方式PUT,DELETE的时候要怎么向服务器端发送请求呢??

 

思路:客户端都以POST的方式发送请求,同时带过去一个参数_method,然后对请求方式和参数进行判断:

POST&&_method=PUT:PUT

POST&&_method=DELETE:DELETE

POST&&_method=null:POST

restful的幂等是什么 rest等于_java

 

 

 

上面的处理要在客户端发送请求后DispatcherServelet前处理,这样的处理可以用监听(listener)或过滤器(filter)

web.xml中个组件的顺序:listener>>filter>>servlet

 

当然spring MVC已经给我们想好了,提供了一个filter:HiddenHttpMethodFilter

源码:

 HiddenHttpMethodFilter.java

1 package org.springframework.web.filter;
 2 
 3 import java.io.IOException;
 4 import java.util.Locale;
 5 import javax.servlet.FilterChain;
 6 import javax.servlet.ServletException;
 7 import javax.servlet.ServletRequest;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletRequestWrapper;
10 import javax.servlet.http.HttpServletResponse;
11 import org.springframework.util.Assert;
12 import org.springframework.util.StringUtils;
13 
14 public class HiddenHttpMethodFilter extends OncePerRequestFilter {
15     public static final String DEFAULT_METHOD_PARAM = "_method";
16     private String methodParam = "_method";
17 
18     public HiddenHttpMethodFilter() {
19     }
20 
21     public void setMethodParam(String methodParam) {
22         Assert.hasText(methodParam, "'methodParam' must not be empty");
23         this.methodParam = methodParam;
24     }
25 
26     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
27         HttpServletRequest requestToUse = request;
28         if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {
29             String paramValue = request.getParameter(this.methodParam);
30             if (StringUtils.hasLength(paramValue)) {
31                 requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, paramValue);
32             }
33         }
34 
35         filterChain.doFilter((ServletRequest)requestToUse, response);
36     }
37 
38     private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
39         private final String method;
40 
41         public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
42             super(request);
43             this.method = method.toUpperCase(Locale.ENGLISH);
44         }
45 
46         public String getMethod() {
47             return this.method;
48         }
49     }
50 }

 

REST CRUD

web.xml

1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
 3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
 5          version="4.0">
 6     <filter>
 7         <filter-name>HiddenHttpMethodFilter</filter-name>
 8         <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
 9     </filter>
10     <filter-mapping>
11         <filter-name>HiddenHttpMethodFilter</filter-name>
12         <url-pattern>/*</url-pattern>
13     </filter-mapping>
14     <servlet>
15         <servlet-name>springMVC</servlet-name>
16         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
17     </servlet>
18     <servlet-mapping>
19         <servlet-name>springMVC</servlet-name>
20         <url-pattern>/</url-pattern>
21     </servlet-mapping>
22 </web-app>

 

springMVC-servlet.xml

1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xmlns:context="http://www.springframework.org/schema/context"
 5        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 6 
 7     <context:component-scan base-package="com.iwakan.controller"/>
 8     <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
 9         <!--
10         /WEB-INF下的东西不能直接访问,只能通过转发进行访问。
11         转发和重定向的区别在于,地址发布发生变化,重定向地址发生变化,
12         如果用重定向访问的化话,又相当于直接访问WEB-INF下的页面了
13         -->
14         <property name="prefix" value="/WEB-INF/view/"/>
15         <property name="suffix" value=".jsp"></property>
16     </bean>
17 </beans>

 

rest.jsp

1 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
 2 <html>
 3 <head>
 4     <title>Rest</title>
 5 </head>
 6 <body>
 7     <a href="/testREST/1001">测试GET</a>
 8     <br>
 9     <br>
10     <form action="/testREST" method="post">
11         <input type="submit" value="测试POST">
12     </form>
13     <br>
14     <form action="/testREST" method="post">
15         <input  type="hidden" name="_method" value="PUT">
16         <input type="submit" value="测试PUT">
17     </form>
18     <br>
19     <form action="/testREST/1001" method="post">
20         <input  type="hidden" name="_method" value="DELETE">
21         <input type="submit" value="测试DELETE">
22     </form>
23 </body>
24 </html>

 

RestController.java
1 package com.iwakan.controller;
 2 
 3 import org.springframework.stereotype.Controller;
 4 import org.springframework.web.bind.annotation.PathVariable;
 5 import org.springframework.web.bind.annotation.RequestMapping;
 6 import org.springframework.web.bind.annotation.RequestMethod;
 7 
 8 @Controller
 9 public class RestController {
10 
11     @RequestMapping(value = "/testREST/{id}", method = RequestMethod.GET)
12     public String getUserById(@PathVariable("id") Integer id) {
13         System.out.println("GET:id==" + id);
14         return "success";
15     }
16 
17     @RequestMapping(value = "/testREST" ,method = RequestMethod.POST)
18     public String insertUser() {
19         System.out.println("POST");
20         return "success";
21     }
22 
23     @RequestMapping(value = "/testREST",method = RequestMethod.PUT)
24     public String UpdateUser(){
25         System.out.println("PUT");
26         return "success";
27     }
28 
29     @RequestMapping(value = "/testREST/{id}",method = RequestMethod.DELETE)
30     public String deleteUser(@PathVariable("id") Integer id){
31         System.out.println("DELETE:id=="+id);
32         return "success";
33     }
34 }

success.jsp

1 <%@ page contentType="text/html;charset=UTF-8"  language="java" %>
2 <html>
3 <head>
4     <title>成功</title>
5 </head>
6 <body>
7     <h2>成功</h2>
8 </body>
9 </html>

restful的幂等是什么 rest等于_xml_02

 

 当点击上面连个按钮时报错:

restful的幂等是什么 rest等于_restful的幂等是什么_03

 

 解决办法:

三种简单处理的办法!
第一:tomcat换到7.0以及以下版本
第二:请求先转给一个Controller,再返回jsp页面
第三种:在你的success页面头部文件将
<%@ page language=”java” contentType=”text/html; charset=UTF-8”
pageEncoding=”UTF-8” isErrorPage=”true”%>

success.jsp

1 <%@ page contentType="text/html;charset=UTF-8" pageEncoding="utf-8" isErrorPage="true" language="java" %>
2 <html>
3 <head>
4     <title>成功</title>
5 </head>
6 <body>
7     <h2>成功</h2>
8 </body>
9 </html>

 

修改完成后,在点击就成功了。

 

 

用Ajax也可以实现REST风格。

※ form表单只有GET和POST两种请求,只能通过HiddenHttpMethodFilter来实现。然而,AJax有八种请求方式,所以可以在不通过HiddenHttpMethodFilter直接实现