嘎里三分熟
  • 首页
  • JMusic
  • TSBay
  • 常用工具
  • About Me
  • 留言板
一行代码一世浮生
  1. 首页
  2. Java web
  3. 正文

SpringMVC 实现 RESTful Web service

2017年03月12日 1799点热度 5人点赞 0条评论

一、Rest 和 RESTful

REST 是 Representational State Transfer 的缩写,简单翻译便是表述性状态转移,是由 Roy Thomas Fielding 博士于2000年提出的概念。

其实,REST是Web服务的一种架构风格,再言之,是一种设计风格,也就是一种思想,而并非一种标准。

通常,REST基于使用 HTTP, URI 和 XML, JSON 以及 HTML 这些现有的广泛流行的协议和标准。

而 RESTful,可以简陋翻译成 REST 式,RESTful Web Service是一种常见的REST的应用,是遵守了 REST 风格的 Web 服务,并且是 ROA (面向资源的架构)。

REST 架构之中有一条很重要的原则就是:网络上的所有事物都可以被抽象为资源,理解这一点很关键。

二、资源操作

当我们欲对一个 User 资源进行 CRUD 操作的时候,最常见的便是直接在 URL 内体现透彻,并且发出的都是 GET 或 POST 请求,如:

  • http://127.0.0.1/user/query/1 GET  查询

  • http://127.0.0.1/user/save POST 新增

  • http://127.0.0.1/user/update POST 修改

  • http://127.0.0.1/user/delete GET/POST 删除

而采用 RESTful 进行编写的时候就会情不自禁采用如下方式:

  • http://127.0.0.1/user/1 GET  查询

  • http://127.0.0.1/user  POST 新增

  • http://127.0.0.1/user  PUT 修改

  • http://127.0.0.1/user  DELETE 删除

转变点在于,我们的 URI 清晰明朗,所有的请求都围绕着我们的 user 资源,而具体的操作则体现在请求方式和参数上面,后面会详细说明。

另外,响应的设计上面也会有所变动,但是围绕不变的原则点是:

  • Content body 仅仅用来传输数据,此举在于保证数据拿来即用的原则,而并不需要进行“拆箱”

  • 描述数据或者请求的元数据放在 Hearder 中,如 X-Restful-Fields

响应示例:
错误:
  {
    "status": 200,
    "data": {
    "user_id": 777,
    "user_name": "Fitz"
    }
  }
正确:
  Response Headers:
    Status: 200
  Response Body:
    {
      "user_id": 777,
      "user_name": "Fitz"
    }

三、http 响应状态码

四、SpringMVC 实现 RESTful Web Service

其实简言之就是,将 URI 和 HTTP 请求方法映射到 Java 处理方法,并将 Java 方法处理结果返回给HTTP请求者。

前面提过只需加以简单注解即可,主要涉及到以下三个注解:

  • @RequestMapping

    最重要的一个注解,用于处理HTTP请求地址映射,可用于类或方法上,用于类上时表示类中的所有响应请求的方法都是以该地址作为父路径,在Spring中,一般一个Controller类处理一种资源,所以每个Controller类都会加@RequestMapping注解。常用属性:value:指定请求的地址method:指定请求的 method 类型, GET、POST、PUT、DELETE 等params:指定 request 中必须包含某些参数,如果有,才让该方法处理

  • @PathVariable

    映射 URL 路径里面的参数

  • @ResponseBody 和 @ResponseBody

    将请求或者响应 body 中的数据(一般常用的为 json)与我们的 Java 对象的互相转换

五、代码体现

  • 保存商品

/**
 * 说明:商品操作相关controller
 * /
@Controller
@RequestMapping("item")
public class ItemController {
    // 注入service
    @Autowired
   private ItemService itemService;
   /**
     * 说明:保存商品
    * 
    * @param item
    * @param desc
    * @return
    * @author CKK
    */
  @RequestMapping(method = RequestMethod.POST)
  public ResponseEntity<Void> saveItem(Item item, 
       @RequestParam(value = "desc") String desc,
       @RequestParam(value = "itemParams") String itemParams) {
    try {
       if (StringUtils.isBlank(item.getTitle())) {
         // 400 参数不符
        return ResponseEntity.badRequest().build(); // TODO 参数校验待完善
      }
      Boolean saveResult = itemService.saveItem(item, desc, itemParams);
      if (saveResult) {
        // 201 添加成功
        return ResponseEntity.status(HttpStatus.CREATED).build();
      } else {
        // 500 发送异常
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    // 500 发送异常
    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
  }
}

  • 修改商品

/**
 * 说明:修改商品
 * @param item
 * @param desc
 * @return
 * @author CKK
 */
 @RequestMapping(method = RequestMethod.PUT)
 public ResponseEntity<Void> updateItem(Item item, 
      @RequestParam(value = "desc") String desc,
      @RequestParam(value = "itemParams") String itemParams) {
   try {
     if (StringUtils.isBlank(item.getTitle())) {
       // 400 参数不符
       return ResponseEntity.badRequest().build(); // TODO 参数校验待完善
     }
     Boolean saveResult = itemService.updateItem(item, desc, itemParams);
     if (saveResult) {
       // 204 添加成功
       return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
     } else {
       // 500 发送异常
       return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
     }
   } catch (Exception e) {
     e.printStackTrace();
   }
   // 500 发送异常
   return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}

但是默认情况下,PUT 请求是无法提交表单数据的,所以我们需要在 web.xml 中添加过滤器来解决,配置如下:

<!-- 解决PUT请求无法提交表单数据的问题 -->
<filter>
   <filter-name>HttpMethodFilter</filter-name>
   <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>HttpMethodFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

  • 删除资源

删除资源操作其实大同小异,需要使用 @RequestMapping(method = RequestMethod.DELETE)

但是还有一点需要注意,DELETE 请求同样是无法提交表单数据的,所以需要在 web.xml 中添加过滤器解决,配置如下:

<!--
  将POST请求转化为DELETE或者是PUT
  要用_method指定真正的请求参数
-->
<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>

当然,测试的时候也有小技巧:

 

 

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: RESTful SpringMVC
最后更新:2017年03月21日

GoldenJet

爱折腾技术的90后漫威小死忠程序员一枚

点赞
下一篇 >

文章评论

取消回复

通过电子邮件订阅博客

分类目录
  • BootStrap (2)
  • Bug集中营 (6)
  • Java web (3)
  • JavaScript (7)
  • Java基础 (17)
  • Java工具 (5)
  • Linux (3)
  • Python (3)
  • SpringBoot (14)
  • Spring基础 (8)
  • thymeleaf (1)
  • 娱乐 (3)
  • 小谈 (2)
  • 常用工具 (7)
  • 技术分析集 (5)
  • 技能 (10)
  • 源码 (4)
  • 科普类 (1)
  • 算法 (9)
  • 踩坑记 (5)
文章归档
  • 2020年11月 (1)
  • 2020年7月 (1)
  • 2020年4月 (2)
  • 2020年3月 (1)
  • 2020年1月 (1)
  • 2019年11月 (1)
  • 2019年10月 (1)
  • 2019年9月 (1)
  • 2019年8月 (1)
  • 2019年7月 (2)
  • 2019年5月 (2)
  • 2019年4月 (2)
  • 2019年3月 (3)
  • 2019年2月 (2)
  • 2019年1月 (2)
  • 2018年12月 (2)
  • 2018年11月 (3)
  • 2018年10月 (3)
  • 2018年9月 (2)
  • 2018年8月 (3)
  • 2018年7月 (2)
  • 2018年5月 (1)
  • 2018年4月 (3)
  • 2018年3月 (2)
  • 2018年2月 (3)
  • 2018年1月 (5)
  • 2017年12月 (2)
  • 2017年11月 (3)
  • 2017年10月 (1)
  • 2017年9月 (1)
  • 2017年8月 (1)
  • 2017年7月 (7)
  • 2017年6月 (5)
  • 2017年5月 (1)
  • 2017年4月 (2)
  • 2017年3月 (4)
  • 2017年2月 (2)
小伙伴友链
  • 前端驿站

COPYRIGHT © 2017-2020 嘎里三分熟. ALL RIGHTS RESERVED.

浙ICP备17005575号-1

浙公网安备 33010802009043号