9.Restful Web Service

题记:前段时间经理让写个关于新闻的后台,要求用到Restful风格,且前后端分离。

这里面有三个方面的问题需要记录一下:Restful、跨域、图片或文件的上传。

今天先记录下关于Restful。


关于RESTFul,之前是在淘淘商城中了解的。一直是学习,没有真正用到项目中,现在终于派上了用场。关于RESTful的知识也是部分摘抄于淘淘商城笔记,具体如下:

1.什么是RESTful

在了解RESTful之前先来了解一下,REST

1.1什么是REST

rest不就是放松一下的意思嘛,哈哈,的确用它可以让你放松一下。

  • REST是web服务的一种架构风格(1.3)
  • 使用http、uri等广泛流行的标准和协议
  • 轻量级、跨平台、跨语言的架构设计
  • 是一种设计风格,不是一种标准也不是一种软件,而是一种思想

1.2什么是RESTful

  • RESTful对应的中文是REST式的
  • RESTful web service是一种常见的REST的应用,遵守了REST风格的web服务
  • REST式的web服务式一种ROA(面向资源的架构)

1.3REST架构的风格(原则)

  • 网络上的所有事物都可被抽象为资源(Resource)
  • 每个资源都有一个唯一的资源标识符(Resource Identifier)
  • 同一资源具有多种表现形式(xml、json等)
  • 对资源的各种状态不会改变资源标识符
  • 所有的操作都是无状态的(Stateless)
  • 符合REST原则的架构方式就可以称为RESTful

无状态的解释:无状态性使得客户端与服务器不必保存对方的详细信息,服务器只需处理当前Request,而不必了解Request的历史,从而可以释放资源,让服务器充分利用Pool技术来提高稳定性和性能。


1.4RESTful风格的特色

最大的特色就是使用URI来标识资源

URI:http://example.com/users/

URL:http://example.com/users/{user}{one for each user}

从上面可以看出:uri可以指向多个,而url只能指向一个。

具体情况原始接口与RESTful写法的对比:

原始接口写法:

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/id  --POST/GET 删除数据


RESTful的写法:针对原始接口的写法,RESTful创造者提出:你明知道是get请求,那就是一个查询的请求没有必要写个query;明知道是post请求,那就是新增数据也没有必要写个save,造成数据冗余。便改为如下方式:

Http://127.0.0.1/user/{id}  --  GET请求,查询用户数据

Http://127.0.0.1/user/   -- POST 新增用户数据

Http://127.0.0.1/user/  -- PUT更新数据

Http://127.0.0.1/user/{id}--DELETE删除数据



2.REST接口的定义



3.响应设计

  • Content body仅仅用了传输数据
  • 数据要做到拿来就用原则,不需要“拆箱”的过程
  • 用了描述数据或者请求的元数据放Header中,例如X-Result-Fields
3.1示例:

3.2指定响应的属性字段
无状态服务器应该允许客户端对数据按需提取,在请求头使用X-Result-Fields指定数据返回的字段集合。例如:trade有trade_id,trade_name,created_at三个属性,客户端只需其中的trade_id与trade_name属性,那么就可以做如下的指定:X-Result-Fields:trade_id,trade_name

这样的接口开发更合理些,而不是把所有的属性都返回给用户。

4.http响应状态码

用响应状态码告知用户执行情况。

5.RESTful具体在项目中的应用
下面以上次搭建的TEST项目为例进行RESTful风格的实现。

在项目中创建一个RestUserController类,返回类型为ResponseEntity<User>,因为要返回状态码的操作。

5.1查询接口开发
/**
     * 查询用户
     * @param id
     * @return
     */
    @RequestMapping(value="{id}", method=RequestMethod.GET)
    public ResponseEntity<User> queryUser(@PathVariable("id")Integer id){
       try {
           User user = this.userService.getUserById(id);
               if (null==user) {
//                   资源不存在响应404
               return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
            }
//               资源存在,响应200
           return ResponseEntity.ok(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
//       出错响应500
       return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
    }
测试:(测试工具的安装与使用

5.2增加用户接口开发
/**
     * 新增用户
     * @param user
     * @return
     */
    @RequestMapping(method=RequestMethod.POST)
    public ResponseEntity<Void> saveUser(User user){
           try {
            int count = this.userService.saveUser(user);
            if(count!=0){
                return ResponseEntity.status(HttpStatus.CREATED).build();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
           return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }

测试:


由于我在数据中这是了not null,所以在插入的时候要保证所有的字段不能为空才可以。

5.3更新用户信息
/**
     * 更新用户
     * @param user
     * @return
     */
    @RequestMapping(method=RequestMethod.PUT)
    public ResponseEntity<Void> updateUser(User user){
        try {
           int count = this.userService.updateUser(user);
           if(count==0){
               //说明更新的资源不存在
               return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
           }
           return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }



测试:

测试报错,查看后台错误提示:说明后台没有获得前台传递的id等信息,所以无法进行更新。
### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where id = null' at line 3
### The error may involve com.test.dao.UserMapper.updateByPrimaryKeySelective-Inline
### The error occurred while setting parameters
### SQL: update user            where id = ?
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where id = null' at line 3
; bad SQL grammar []; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where id = null' at line 3
	at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231)

原因是因为put方法无法提交表单数据,解决办法(点击此处)

5.4删除用户
/**
     * 删除用户
     * @param id
     * @return
     */
    @RequestMapping(value="{id}",method=RequestMethod.DELETE)
    public ResponseEntity<Void> deleteUser(@PathVariable("id") Integer id){
       try {
        int count= this.userService.deleteUser(id);
           if(count==0){
//           删除的资源不存在
              return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
           }
           return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
       
    }

测试:


至此,关于RESTful的基本使用就是这些了。
下面贴出controller和service的完整代码:
RestUserController.java
package com.test.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.test.pojo.User;
import com.test.service.UserService;

@Controller
@RequestMapping("/user")
public class RestUserController {
    @Autowired
    private UserService userService;
    
    /**
     * 查询用户
     * @param id
     * @return
     */
    @RequestMapping(value="{id}", method=RequestMethod.GET)
    public ResponseEntity<User> queryUser(@PathVariable("id")Integer id){
       try {
           User user = this.userService.getUserById(id);
               if (null==user) {
//                   资源不存在响应404
               return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
            }
//               资源存在,响应200
           return ResponseEntity.ok(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
//       出错响应500
       return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
    }
    /**
     * 新增用户
     * @param user
     * @return
     */
    @RequestMapping(method=RequestMethod.POST)
    public ResponseEntity<Void> saveUser(User user){
           try {
            int count = this.userService.saveUser(user);
            if(count!=0){
                return ResponseEntity.status(HttpStatus.CREATED).build();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
           return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }
    
    /**
     * 更新用户
     * @param user
     * @return
     */
    @RequestMapping(method=RequestMethod.PUT)
    public ResponseEntity<Void> updateUser(User user){
        try {
           int count = this.userService.updateUser(user);
           if(count==0){
               //说明更新的资源不存在
               return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
           }
           return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }
    /**
     * 删除用户
     * @param id
     * @return
     */
    @RequestMapping(value="{id}",method=RequestMethod.DELETE)
    public ResponseEntity<Void> deleteUser(@PathVariable("id") Integer id){
       try {
        int count= this.userService.deleteUser(id);
           if(count==0){
//           删除的资源不存在
              return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
           }
           return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
       
    }
    
}


UserService.java接口
package com.test.service;

import com.test.pojo.User;

public interface UserService {
    public User getUserById(int id);
    
    public int saveUser(User user);
    
    public int updateUser(User user);
    
    public int deleteUser(int id);
}



UserServiceImpl.java实现
package com.test.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.test.dao.UserMapper;
import com.test.pojo.User;
import com.test.service.UserService;

@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserMapper userMapper;

    public User getUserById(int id) {
        return this.userMapper.selectByPrimaryKey(id);
    }

    public int saveUser(User user) {
       int count = this.userMapper.insertSelective(user); 
       return count;
    }

    public int updateUser(User user) {
        int count=this.userMapper.updateByPrimaryKeySelective(user);
        return count;
    }

    public int deleteUser(int id) {
      int count = this.userMapper.deleteByPrimaryKey(id);
      return count;
    }

}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值