SpringMVC与REST相结合实现RESTful风格

简介: SpringMVC与REST相结合实现RESTful风格

【1】REST简介

以下来源于百度百科:


REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。

在三种主流的Web服务实现方案中,因为REST模式的Web服务与复杂的SOAP和XML-RPC对比来讲明显的更加简洁,越来越多的web服务开始采用REST风格设计和实现。

REST : 即 RepresentationalStateTransfer ,(资源)表现层状态转化(表现层资源状态转移)。

资源


网络上的一个实体或者说是网络上的一个具体信息。 每种资源对应一个特定的URI,因此URI为每一个资源的独一无二的识别符。资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源组成。每个资源是服务器上一个可命名的抽象概念。因为资源是一个抽象的概念,所以它不仅仅能代表服务器文件系统中的一个文件、数据库中的一张表等等具体的东西,可以将资源设计的要多抽象有多抽象,只要想象力允许而且客户端应用开发者能够理解。


与面向对象设计类似,资源是以名词为核心来组织的,首先关注的是名词。一个资源可以由一个或多个URI来标识。URI既是资源的名称,也是资源在Web上的地址。对某个资源感兴趣的客户端应用,可以通过资源的URI与其进行交互。

资源的表述

资源的表述是一段对于资源在某个特定时刻的状态的描述。可以在客户端-服务器端之间转移(交

换)。资源的表述可以有多种格式,例如HTML/XML/JSON/纯文本/图片/视频/音频等等。资源的表述格

式可以通过协商机制来确定。请求-响应方向的表述通常使用不同的格式。


状态转化/转移


态转移说的是:在客户端和服务器端之间转移(transfer)代表资源状态的表述。通过转移和操作资

源的表述,来间接实现操作资源的目的。每发出一个请求,就代表了客户端和服务器端的一次交互过程。HTTP协议是一个无状态协议,即所有的状态都保存在服务器上。


因此用户想要操作服务器,必须通过某种手段,让服务器发生状态变化。而这种状态变化是建立在表现层之上的,所以就是“表现层状态变化”。


REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方

式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性。


具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE用来删除资源。

【2】SpringMVC 与 REST相结合

浏览器form表单只支持GET与POST请求,Spring3.0增加了一个过滤器,可以将这些HTTP请求转换为标准的HTTP方法,使得支持GET、POST、PUT与DELETE请求。


由于浏览器只支持发送get和post方式的请求,那么该如何发送put和delete请求呢?SpringMVC 提供了 HiddenHttpMethodFilter 帮助我们将 POST 请求转换为 DELETE 或 PUT 请求


HiddenHttpMethodFilter 处理put和delete请求的条件:


当前请求的请求方式必须为post

当前请求必须传输请求参数_method

满足以上条件,HiddenHttpMethodFilter 过滤器就会将当前请求的请求方式转换为请求参数_method的值,因此请求参数_method的值才是最终的请求方式

① HiddenHttpMethodFilter

源码如下:

public class HiddenHttpMethodFilter extends OncePerRequestFilter {
 //PUT DELETE PATCH
  private static final List<String> ALLOWED_METHODS =
      Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(),
          HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
  /**默认方法参数  _method */
  public static final String DEFAULT_METHOD_PARAM = "_method";
  private String methodParam = DEFAULT_METHOD_PARAM;
  public void setMethodParam(String methodParam) {
    Assert.hasText(methodParam, "'methodParam' must not be empty");
    this.methodParam = methodParam;
  }
  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
      throws ServletException, IOException {
    HttpServletRequest requestToUse = request;
    if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
      String paramValue = request.getParameter(this.methodParam);
      if (StringUtils.hasLength(paramValue)) {
        String method = paramValue.toUpperCase(Locale.ENGLISH);
        if (ALLOWED_METHODS.contains(method)) {
          requestToUse = new HttpMethodRequestWrapper(request, method);
        }
      }
    }
    filterChain.doFilter(requestToUse, response);
  }
   //简单request包装器,有参数method标明转换后的参数
  private static class HttpMethodRequestWrapper extends HttpServletRequestWrapper {
    private final String method;
    public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
      super(request);
      this.method = method;
    }
    @Override
    public String getMethod() {
      return this.method;
    }
  }
}


源码解释如下:


① 判断当前方法是否为POST且request属性中WebUtils.ERROR_EXCEPTION_ATTRIBUTE是否为空。

② 获取_method参数对应的值,判断是否在ALLOWED_METHODS内。如果在,则包装request

③ 继续流转filterChain

② web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0">
  <listener>
    <listener-class>com.web.hh.utils.SpringIocContextListener</listener-class>
  </listener>
  <filter>
    <filter-name>encoding</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>encoding</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-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>
  <servlet>
    <servlet-name>hh-mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>namespace</param-name>
      <param-value>hh-mvc</param-value>
    </init-param>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:applicationContext.xml</param-value>
    </init-param>
    <init-param>
      <param-name>publishContext</param-name>
      <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>hh-mvc</servlet-name>
    <!--  注意这里 -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

【3】方法测试

① GET

JSP页面,获取资源 且 GET方法默认支持,不需要使用隐藏域。

<a href="springmvc/testRest/1">Test Rest Get</a>

后台code

@RequestMapping(value = "/testRest/{id}", method = RequestMethod.GET)
public String testRest(@PathVariable Integer id) {
  System.out.println("testRest GET: " + id);
  return SUCCESS;
}


可见,与普通的方法并无差异。

② POST

JSP页面:

<form action="springmvc/testRest" method="post">
  <input type="submit" value="TestRest POST"/>
</form>


后台code:

@RequestMapping(value = "/testRest", method = RequestMethod.POST)
public String testRest() {
  System.out.println("testRest POST");
  return SUCCESS;
}

同样默认支持,与普通的方法并无差异。

③ PUT

更新资源,默认不支持该方法,需要在JSP页面设隐藏域。

JSP页面:

//form里面method是POST,_method的value为PUT
<form action="springmvc/testRest/1" method="post">
  <input type="hidden" name="_method" value="PUT"/>
  //设置隐藏域 注意 name 与value
  <input type="submit" value="TestRest PUT"/>
</form>

后台code

// method为PUT
@RequestMapping(value = "/testRest/{id}", method = RequestMethod.PUT)
public String testRestPut(@PathVariable("id") Integer id) {
  System.out.println("testRest Put: " + id);
  return SUCCESS;
}


④ DELETE

删除资源,默认不支持该方法,需要在JSP页面设隐藏域。

JSP页面:

<form action="springmvc/testRest/1" method="post">
  <input type="hidden" name="_method" value="DELETE"/>
  //设置隐藏域 注意 name 与value
  <input type="submit" value="TestRest DELETE"/>
</form>


JSP页面:

<form action="springmvc/testRest/1" method="post">
  <input type="hidden" name="_method" value="DELETE"/>
  //设置隐藏域 注意 name 与value
  <input type="submit" value="TestRest DELETE"/>
</form>

后台code:

//method为DELETE
@RequestMapping(value = "/testRest/{id}", method = RequestMethod.DELETE)
public String testRestDelete(@PathVariable(value="id") Integer id) {
  System.out.println("testRest Delete: " + id);
  return SUCCESS;
}


关于PUT和DELETE,均是在表单中设置隐藏域,name='_method',value设置为对应值。然后form表单发送POST请求,由HiddenHttpMethodFilter根据_method的值将POST请求转换为PUT请求或者DELETE请求。

目录
相关文章
|
3月前
|
JSON 前端开发 Java
spring mvc Rest风格
spring mvc Rest风格
29 0
|
10天前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
15天前
|
XML JSON 数据库
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
这篇文章详细介绍了RESTful的概念、实现方式,以及如何在SpringMVC中使用HiddenHttpMethodFilter来处理PUT和DELETE请求,并通过具体代码案例分析了RESTful的使用。
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
|
12天前
|
前端开发 应用服务中间件 数据库
SpringMVC入门到实战------八、RESTful案例。SpringMVC+thymeleaf+BootStrap+RestFul实现员工信息的增删改查
这篇文章通过一个具体的项目案例,详细讲解了如何使用SpringMVC、Thymeleaf、Bootstrap以及RESTful风格接口来实现员工信息的增删改查功能。文章提供了项目结构、配置文件、控制器、数据访问对象、实体类和前端页面的完整源码,并展示了实现效果的截图。项目的目的是锻炼使用RESTful风格的接口开发,虽然数据是假数据并未连接数据库,但提供了一个很好的实践机会。文章最后强调了这一章节主要是为了练习RESTful,其他方面暂不考虑。
SpringMVC入门到实战------八、RESTful案例。SpringMVC+thymeleaf+BootStrap+RestFul实现员工信息的增删改查
|
29天前
|
JSON 前端开发 Java
Spring MVC返回JSON数据
综上所述,Spring MVC提供了灵活、强大的方式来支持返回JSON数据,从直接使用 `@ResponseBody`及 `@RestController`注解,到通过配置消息转换器和异常处理器,开发人员可以根据具体需求选择合适的实现方式。
57 4
|
29天前
|
XML 前端开发 Java
Spring MVC接收param参数(直接接收、注解接收、集合接收、实体接收)
Spring MVC提供了灵活多样的参数接收方式,可以满足各种不同场景下的需求。了解并熟练运用这些基本的参数接收技巧,可以使得Web应用的开发更加方便、高效。同时,也是提高代码的可读性和维护性的关键所在。在实际开发过程中,根据具体需求选择最合适的参数接收方式,能够有效提升开发效率和应用性能。
55 3
|
30天前
|
XML 前端开发 Java
Spring MVC接收param参数(直接接收、注解接收、集合接收、实体接收)
Spring MVC提供了灵活多样的参数接收方式,可以满足各种不同场景下的需求。了解并熟练运用这些基本的参数接收技巧,可以使得Web应用的开发更加方便、高效。同时,也是提高代码的可读性和维护性的关键所在。在实际开发过程中,根据具体需求选择最合适的参数接收方式,能够有效提升开发效率和应用性能。
54 2
|
2月前
|
前端开发 Java 应用服务中间件
我以为我对Spring MVC很了解,直到我遇到了...
所有人都知道Spring MVC是是开发的,却鲜有人知道Spring MVC的理论基础来自于1978 年提出MVC模式的一个老头子,他就是Trygve Mikkjel Heyerdahl Reenskaug,挪威计算机科学家,名誉教授。Trygve Reenskaug的MVC架构思想早期用于图形用户界面(GUI) 的软件设计,他对MVC是这样解释的。MVC 被认为是解决用户控制大型复杂数据集问题的通用解决方案。最困难的部分是为不同的架构组件想出好的名字。模型-视图-编辑器是第一个。
我以为我对Spring MVC很了解,直到我遇到了...
|
2月前
|
前端开发 Java API
Spring Boot 中的 MVC 支持
### Spring Boot 注解摘要 - **@RestController** - **@RequestMapping** - **@PathVariable** - **@RequestParam** - **@RequestBody**
22 2
|
18天前
|
前端开发 Java Spring
Java 新手入门:Spring Boot 轻松整合 Spring 和 Spring MVC!
Java 新手入门:Spring Boot 轻松整合 Spring 和 Spring MVC!
37 0
下一篇
云函数