springmvc 实现restful接口

REST表示 Representational State Transfer(表示性状态转换).它是可以用来设计web services的框架,可以被不同的客户端调用。REST本身只是为分布式超媒体系统设计的一种架构风格,而不是标准。

核心思想是:使用简单的HTTP协议来实现调用,而不是CORBA, RPC 或者 SOAP等负责的机制。


在Rest 基础设计中,资源使用以下动词进行操作。

  • 创建资源 : 使用 HTTP POST
  • 获取资源 : 使用 HTTP GET
  • 更新资源 : 使用 HTTP PUT
  • 删除资源 : 使用 HTTP DELETE

也意味着,你作为Rest 服务开发者或者客户,应该遵循以上的标准。

尽管没有限制必须返回的类型,但是一般基于Web services的Rest返回JSON或者XML作为响应。

客户端可以指定(使用HTTP Accept header)他们想要的资源类型吗,服务器返回需要的资源。
指明资源的Content-Type。

基于Rest的Controller(控制器)

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;

import com.cmcc.model.SysUser;
import com.cmcc.model.User;
import com.cmcc.service.SysUserService;

@RestController  
public class HelloWorldRestController {  

    @Autowired  
    SysUserService userService;  //Service which will do all data retrieval/manipulation work  


    //-------------------Retrieve All Users--------------------------------------------------------  

    @RequestMapping(value = "/user/", method = RequestMethod.GET)  
    public ResponseEntity<List<SysUser>> listAllUsers() {  
        List<SysUser> sysUser = userService.selectSysUserByCondition(new SysUser());
        if(sysUser.isEmpty()){  
            return new ResponseEntity<List<SysUser>>(HttpStatus.NO_CONTENT);//You many decide to return HttpStatus.NOT_FOUND  
        }  
        return new ResponseEntity<List<SysUser>>(sysUser, HttpStatus.OK);  
    }  

    //-------------------Retrieve Single User--------------------------------------------------------  

    @RequestMapping(value = "/user/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)  
    public ResponseEntity<SysUser> getUser(@PathVariable("id") String id) {  
        System.out.println("Fetching User with id " + id);
        SysUser sysUser = new SysUser();
        sysUser.setUserId(id);
        List<SysUser> sysUsers = userService.selectSysUserByCondition(sysUser);  
        if (sysUsers.size() == 0) {  
            System.out.println("User with id " + id + " not found");  
            return new ResponseEntity<SysUser>(HttpStatus.NOT_FOUND);  
        }  
        return new ResponseEntity<SysUser>(sysUsers.get(0), HttpStatus.OK);  
    }  

    //-------------------Create a User--------------------------------------------------------  

    @RequestMapping(value = "/user/", method = RequestMethod.POST)  
    public ResponseEntity<String> createUser(@RequestBody SysUser user,    UriComponentsBuilder ucBuilder) {  
//        System.out.println("Creating User " + user.getName());  

        if (userService.selectByLoginAccount(user.getUserAccount()) != null) {  
            System.out.println("A User with name " + user.getUserAccount() + " already exist");  
            return new ResponseEntity<String>("A User with name " + user.getUserAccount() + " already exist" ,HttpStatus.CONFLICT);  
        }  

        userService.insertUser(user);  

        HttpHeaders headers = new HttpHeaders();  
        headers.setLocation(ucBuilder.path("/user/{id}").buildAndExpand(user.getUserId()).toUri());  
        return new ResponseEntity<String>(headers, HttpStatus.CREATED);  
    }  

    //------------------- Update a User --------------------------------------------------------  

    @RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)  
    public ResponseEntity<SysUser> updateUser(@PathVariable("id") String id, @RequestBody SysUser user) {  
        System.out.println("Updating User " + id);  

        SysUser sysUser = new SysUser();
        sysUser.setUserId(id);
        List<SysUser> sysUsers = userService.selectSysUserByCondition(sysUser);  
        sysUser = null;
        if(sysUsers.size() != 0){
            sysUser = sysUsers.get(0);
        }
        if (sysUser==null) {  
            System.out.println("User with id " + id + " not found"); 
            return new ResponseEntity<SysUser>(HttpStatus.NOT_FOUND);
        }  

        sysUser.setUserName(user.getUserName());  
        sysUser.setUserAddress(user.getUserAddress());

        userService.updateSysUser(sysUser);
        return new ResponseEntity<SysUser>(sysUser, HttpStatus.OK);  
    }  

    //------------------- Delete a User --------------------------------------------------------  

    @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)  
    public ResponseEntity<User> deleteUser(@PathVariable("id") String id) {  
        System.out.println("Fetching & Deleting User with id " + id);  

        SysUser sysUser = new SysUser();
        sysUser.setUserId(id);
        SysUser user = (SysUser) userService.selectSysUserByCondition(sysUser);  
        if (user == null) {  
            System.out.println("Unable to delete. User with id " + id + " not found");  
            return new ResponseEntity<User>(HttpStatus.NOT_FOUND);  
        }  

        userService.deleteUserById(id);  
        return new ResponseEntity<User>(HttpStatus.NO_CONTENT);  
    }  

    //------------------- Delete All Users --------------------------------------------------------  

    @RequestMapping(value = "/user/", method = RequestMethod.DELETE)  
    public ResponseEntity<User> deleteAllUsers() {  
        System.out.println("Deleting All Users");  

//        userService.deleteAllUsers();  
        return new ResponseEntity<User>(HttpStatus.NO_CONTENT);  
    }  

}  
  • @RestController :首先我们使用的是Spring 4的新注解@RestController注解.
    此注解避免了每个方法都要加上@ResponseBody注解。也就是说@RestController 自己戴上了 @ResponseBody注解,看以看作是
    @Controller 和 @ResponseBody的结合体。
  • @RequestBody : 如果方法参数被@RequestBody注解,Spring将绑定HTTP请求体到那个参数上。如果那样做,Spring将根据请求中的ACCEPT或者 Content-Type header(私下)使用 HTTP Message converters 来将http请求体转化为domain对象。
  • @ResponseBody : 如果方法加上了@ResponseBody注解,Spring返回值到响应体。如果这样做的话,Spring将根据请求中的 Content-Type header(私下)使用 HTTP Message converters 来将domain对象转换为响应体。
  • ResponseEntity 是一个真实数据.它代表了整个 HTTP 响应(response). 它的好处是你可以控制任何对象放到它内部。
    你可以指定状态码、头信息和响应体。它包含你想要构建HTTP Response 的信息。
  • @PathVariable 此注解意味着一个方法参数应该绑定到一个url模板变量[在’{}’里的一个]中一般来说你,要实现REST API in Spring 4 需要了解@RestController , @RequestBody, ResponseEntity 和 @PathVariable 这些注解 .另外, spring 也提供了一些支持类帮助你实现一些可定制化的东西。
  • MediaType : 带着 @RequestMapping注解,通过特殊的控制器方法你可以额外指定,MediaType来生产或者消耗。
    *

一个良好的Rest架构的应用中,所有的异常都应该有对应的Http Status Code来表示具体的异常类型,这样可以客户端可以基于对应的Status Code做出最有利于自己的处理。

最近,一些新产品的开发甚至已经几乎完全抛弃了传统的类似 JSP 的技术, 转而大量使用 REST 风格的构架设计, 即在服务器端所有商业逻辑都以 REST API 的方式暴露给客户端, 所有浏览器用户界面使用 widget,Ajax,HTML5 等技术,用 HTTP 的方式与后台直接交互。

REST规范

  1. 客户-服务器
    这种规范的提出,改善了用户接口跨多个平台的可移植性,并且通过简化服务器组件,改善了系统的可伸缩性。最为关键的是通过分离用户接口和数据存储这两个关注点,使得不同用户终端享受相同数据成为了可能。

  2. 无状态性
    无状态性是在客户-服务器约束的基础上添加的又一层规范。他要求通信必须在本质上是无状态的,即从客户到服务器的每个request都必须包含理解该 request所必须的所有信息。这个规范改善了系统的可见性(无状态性使得客户端和服务器端不必保存对方的详细信息,服务器只需要处理当前request,而不必了解所有的request历史),可靠性(无状态性减少了服务器从局部错误中恢复的任务量),可伸缩性(无状态性使得服务器端可以 很容易的释放资源,因为服务器端不必在多个request中保存状态)。同时,这种规范的缺点也是显而易见得,由于不能将状态数据保存在服务器上的共享上 下文中,因此增加了在一系列request中发送重复数据的开销,严重的降低了效率。

  3. 缓存
    为了改善无状态性带来的网络的低效性,我们填加了缓存约束。缓存约束允许隐式或显式地标记一个response中的数据,这样就赋予了客户端缓存 response数据的功能,这样就可以为以后的request共用缓存的数据,部分或全部的消除一部分交互,增加了网络的效率。但是用于客户端缓存了信 息,也就同时增加了客户端与服务器数据不一致的可能,从而降低了可靠性。
    B/S架构的优点是其部署非常方便,但在用户体验方面却不是很理想。为了改善这种情况,我们引入了REST。
    REST在原有的架构上增加了三个新规范:统一接口,分层系统和按需代码。

  4. 统一接口
    REST 架构风格的核心特征就是强调组件之间有一个统一的接口,这表现在REST世界里,网络上所有的事物都被抽象为资源,而REST就是通过通用的链接器接口对 资源进行操作。这样设计的好处是保证系统提供的服务都是解耦的,极大的简化了系统,从而改善了系统的交互性和可重用性。并且REST针对Web的常见情况 做了优化,使得REST接口被设计为可以高效的转移大粒度的超媒体数据,这也就导致了REST接口对其它的架构并不是最优的。

  5. 分层系统
    分层系统规则的加入提高了各种层次之间的独立性,为整个系统的复杂性设置了边界,通过封装遗留的服务,使新的服务器免受遗留客户端的影响,这也就提高了系统的可伸缩性。

  6. 按需代码
    REST允许对客户端功能进行扩展。比如,通过下载并执行applet或脚本形式的代码,来扩展客户端功能。但这在改善系统可扩展性的同时,也降低了可见性。所以它只是REST的一个可选的约束。

REST提出了如下设计准则:

网络上的所有事物都被抽象为资源(resource); 
每个资源对应一个唯一的资源标识符(resource identifier); 
通过通用的连接器接口(generic connector interface)对资源进行操作; 
对资源的各种操作不会改变资源标识符; 
所有的操作都是无状态的(stateless)。

REST是基于Http协议的,任何对资源的操作行为都是通过Http协议来实现

REST新的思维方式是把所有用户需求抽象为资源,这在实际开发中是比较难做到的,因为并不是所有的用户需求都能被抽象为资源,这样也就是说不是整个系统的结构都能 通过REST的来表现。所以在开发中,我们需要根据以上2点来在REST和MVC中做出选择。我们认为比较好的办法是混用REST和MVC,因为这适合绝 大多数的Web应用开发,开发人员只需要对比较容易能够抽象为资源的用户需求采取REST的开发模式,而对其它需求采取MVC开发即可。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值