SpringMVC 实现 RESTful Web service

贴心的 SpringMVC 原生态地支持 RESTful的设计风格,我们只需稍加简单的注解,就可以轻松搞定 RESTful Web Service。

一、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 架构之中有一条很重要的原则就是:网络上的所有事物都可以被抽象为资源,理解这一点很关键。</p>

二、资源操作

当我们欲对一个 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 资源,而具体的操作则体现在请求方式和参数上面,后面会详细说明。

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
响应示例:
错误:
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;"status":&nbsp;200,
&nbsp;&nbsp;&nbsp;&nbsp;"data":&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;"user_id":&nbsp;777,
&nbsp;&nbsp;&nbsp;&nbsp;"user_name":&nbsp;"Fitz"
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}
正确:
&nbsp;&nbsp;Response&nbsp;Headers:
&nbsp;&nbsp;&nbsp;&nbsp;Status:&nbsp;200
&nbsp;&nbsp;Response&nbsp;Body:
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"user_id":&nbsp;777,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"user_name":&nbsp;"Fitz"
&nbsp;&nbsp;&nbsp;&nbsp;}```<p><br/></p><h2>三、http 响应状态码</h2><p><img class="alignnone wp-image-126 size-full" src="http://blogsource.chenkaikai.com/uploads/2017/03/http-status-code.png" alt="" height="706" width="872"/></p><h2>四、SpringMVC 实现 RESTful Web Service</h2><p>其实简言之就是,将 URI 和 HTTP 请求方法映射到 Java&nbsp;处理方法,并将 Java&nbsp;方法处理结果返回给HTTP请求者。

前面提过只需加以简单注解即可,主要涉及到以下三个注解:</p><ul class=" list-paddingleft-2"><li><h4>@RequestMapping</h4><p>最重要的一个注解,用于处理HTTP请求地址映射,可用于类或方法上,用于类上时表示类中的所有响应请求的方法都是以该地址作为父路径,在Spring中,一般一个Controller类处理一种资源,所以每个Controller类都会加@RequestMapping注解。常用属性:<strong>value</strong>:指定请求的地址<strong>method</strong>:指定请求的 method 类型, GET、POST、PUT、DELETE 等<strong>params</strong>:指定 request 中必须包含某些参数,如果有,才让该方法处理</p></li><li><h4>@PathVariable</h4><p>映射 URL 路径里面的参数</p></li><li><h4>@ResponseBody 和&nbsp;@ResponseBody</h4><p>将请求或者响应 body 中的数据(一般常用的为 json)与我们的 Java 对象的互相转换</p></li></ul><h2>五、代码体现</h2><ul class=" list-paddingleft-2"><li><p><strong>保存商品</strong></p></li></ul>

/
  说明:商品操作相关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 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();
  }
}

class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
&nbsp;*&nbsp;说明:修改商品
&nbsp;*&nbsp;@param&nbsp;item
&nbsp;*&nbsp;@param&nbsp;desc
&nbsp;*&nbsp;@return
&nbsp;*&nbsp;@author&nbsp;CKK
&nbsp;*/
&nbsp;@RequestMapping(method&nbsp;=&nbsp;RequestMethod.PUT)
&nbsp;public&nbsp;ResponseEntity<Void>&nbsp;updateItem(Item&nbsp;item,&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@RequestParam(value&nbsp;=&nbsp;"desc")&nbsp;String&nbsp;desc,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@RequestParam(value&nbsp;=&nbsp;"itemParams")&nbsp;String&nbsp;itemParams)&nbsp;{
&nbsp;&nbsp;&nbsp;try&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(StringUtils.isBlank(item.getTitle()))&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;400&nbsp;参数不符
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;ResponseEntity.badRequest().build();&nbsp;//&nbsp;TODO&nbsp;参数校验待完善
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Boolean&nbsp;saveResult&nbsp;=&nbsp;itemService.updateItem(item,&nbsp;desc,&nbsp;itemParams);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(saveResult)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;204&nbsp;添加成功
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;ResponseEntity.status(HttpStatus.NO_CONTENT).build();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;500&nbsp;发送异常
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(Exception&nbsp;e)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();
&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;//&nbsp;500&nbsp;发送异常
&nbsp;&nbsp;&nbsp;return&nbsp;ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}```<p>但是默认情况下,PUT 请求是无法提交表单数据的,所以我们需要在 web.xml 中添加过滤器来解决,配置如下<code>:<br/></code></p>


   HttpMethodFilter</filter-name>
   org.springframework.web.filter.HttpPutFormContentFilter</filter-class>


   HttpMethodFilter</filter-name>
   /*</url-pattern>
</filter-mapping>

class
1
2

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


   HiddenHttpMethodFilter</filter-name>
   org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>


   HiddenHttpMethodFilter</filter-name>
   /*</url-pattern>
</filter-mapping>```

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

 

 
</p>

------ 本文结束 感谢阅读 ------
0%