乐趣区

关于mvc:基于MVC的RESTFul风格API实战

基于 MVCRESTful格调的实现

1.RESTful格调论述

REST服务是一种 ROA(Resource-Oriented Architecture, 面向资源的架构) 利用。次要特点是办法信息存在于 HTTP 协定的办法中(GET,POST,PUT,DELETE),作用域存在于 URL 中。例如,在一个获取设施资源列表的 GET 申请中,办法信息是GET,作用域信息是 URI 种蕴含的对设施资源的过滤、分页和排序等条件

== 良好的 REST API 不须要任何文档 ==

1.1REST格调资源门路

REST格调的资源门路设计是面向资源的,== 资源的名称 == 应该是精确形容该资源的 == 名词 ==。

资源门路概览:sheme://host:port/path?queryString

例:http://localhost:8080/bywlstudio/users/user?username=xiuer

1.2HTTP办法

GET用于 == 读取 ==、== 检索 ==、== 查问 ==、== 过滤 == 资源

PSOT用于 == 创立 == 一个资源

PUT用于 == 批改 ==、== 更新 == 资源、== 创立客户端保护主键信息的资源 ==

DELETE用于 == 删除 == 资源

资源地址和 HTTP 办法联合在一起就能够实现对资源的残缺定位

1.3RESTful格调 API 设计

上文讲述了通过 HTTP 办法和资源门路对服务器的一个资源进行定位的过程

接下来看一个 REST 格调 API 的设计

性能 形容
增加 / 创立 POST/users
PUT/users{id}1
删除 DELETE/users/{id}
批改 / 更新 PUT/users/{id}
查问全副 GET/users
主键查问 GET/users/{id}
GET/users?id=26
分页作用域查问 GET/users?start=0&size=10
GET/users?07,2019-07,2020

能够看到通过这个 RESTAPI 都是通过对 == 同一个资源 == 的操作,所不同的就是通过不同的 ==HTTP 办法 == 来实现对资源不同的解决。

2.MVCREST 的反对

1.1 次要通过注解来实现
  • @Controller声名一个解决申请的控制器
  • @RequestMapping申请映射地址,它存在几个子注解对于实现 REST 格调来说更加具备 == 语义性 ==

    • @GETMapping ==GET 申请 ==
    • @PUTMapping ==PUT 申请 ==
    • @POSTMapping ==POST 申请 ==
    • @DELETEMapping ==DELETE 申请 ==
  • @ResponseBody 将响应内容转换为 JSON 格局
  • @RequestBody 申请内容转换为 JSON 格局
  • @PathVariable("id")用于绑定一个参数
  • @RESTController 等同于 @Controller+@ResponseBody 在类上写了这个注解,标识这个类的所有办法只 == 返回数据 ==,而不进行 == 视图跳转 ==
1.2 返回 HTTP 状态码

REST格调 API 一个最显明的特点通过返回对应的 HTTPStatus 来判断客户端的操作是否实现

== 上面是 spring 中对于 Http 状态码形容的枚举类,本文列举了常见的状态码 ==(读者若对此感兴趣能够查看 HttpStatus 源码)

public enum HttpStatus{OK(200, "OK"),// 用于服务器有实体响应
    CREATED(201, "Created"),// 创立了新实体,响应该实体
    NO_CONTENT(204, "No Content"),// 服务器失常响应,但无实体响应
    BAD_REQUEST(400, "Bad Request"),// 客户端申请语法错误
    NOT_FOUND(404, "Not Found"),// 指标资源不存在
    INTERNAL_SERVER_ERROR(500, "Internal Server Error"),// 服务器外部谬误
    NOT_IMPLEMENTED(501, "Not Implemented"),// 服务器不反对以后申请
}

Spring 返回状态码是通过 @ResponseStatus 注解或者 ResponseEntity<?> 类实现的。

==@ResponseStatus形式 ==

@GetMapping(path = "/user/{id}" , produces = "application/json;charset=utf-8")
@ResponseStatus(HttpStatus.OK)
public User findUserById(@PathVariable("id")Integer id){User user = userService.findUserById(id);
    return user ;
}

==ResponseEntity<?>== 形式

@GetMapping(produces = "application/json;charset=utf-8")
public ResponseEntity<List<User>> findAll(){List<User> users = userService.findAll();
    return new ResponseEntity<List<User>>(users , HttpStatus.OK);
}
1.3 因为 MVC 默认不反对 PUTDELETE办法,所以须要手动开启

tomcat 服务器的 web.xml 文件中开启一下配置

<servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
        <param-name>readonly</param-name>
        <param-value>true</param-value><!-- 开启这个 -->
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

在我的项目的 web.xml 中配置

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

  <filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <servlet-name>dispathcherServlet</servlet-name>
  </filter-mapping>

3.MVC实现 REST 代码实现

3.1 实例环境
  • JDK1.8
  • maven3.60
  • tomcat9
3.2API设计
URI Description Response HTTPStatus
==GET==/users 获取全副用户 JSON 200
==GET==/users/{id} 获取指定主键的用户 JSON 200
==PUT==/users/{id} 批改指定的主键的用户信息 JSON 200/201
==POST==/users 减少一个用户 JSON 201
==DELETE==/users/{id} 删除一个用户 void 204
3.3 管制层代码
@RestController
@RequestMapping("/users")
public class UserControler {

    @Autowired
    private IUserService userService ;

    //REST 格调实现办法

    /**
     * 查问所有
     * @return
     */
    @GetMapping(produces = "application/json;charset=utf-8")
    public ResponseEntity<List<User>> findAll(){List<User> users = userService.findAll();
        return new ResponseEntity<List<User>>(users , HttpStatus.OK);
    }

    /**、* 依据 ID 查问
     * @param id
     * @return
     */

    @GetMapping(path = "/{id}" , produces = "application/json;charset=utf-8")
    @ResponseStatus(HttpStatus.OK)
    public User findUserById(@PathVariable("id")Integer id){User user = userService.findUserById(id);
        return user ;
    }
    /**
     * 减少一个用户
     * 返回该用户
     */
    @PostMapping(produces = "application/json;charset=utf-8")
    @ResponseStatus(HttpStatus.CREATED)
    public User addUser(@RequestBody User user){User newUser = userService.addUser(user);
        return newUser ;
    }

    /**
     * 更新
     * @param user
     */
    @PutMapping(path = "/{id}" ,produces = "application/json;charset=utf-8")
    public ResponseEntity<User> updateUser(@PathVariable("id") Integer id , @RequestBody User user){user.setUid(id);
        // 资源是否批改
        boolean flag = userService.updateUser(user);
        User deUser = userService.findUserById(id);
        if(flag)
            return new ResponseEntity<User>(deUser,HttpStatus.CREATED);
        return new ResponseEntity<User>(deUser,HttpStatus.OK);
    }

    @DeleteMapping(path = "/{id}"  , produces = "application/json;charset=utf-8")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void delUser(@PathVariable("id") Integer id){User user = userService.findUserById(id);
        userService.delUser(id);
    }
}

更多原创文章和 Java 学习材料 @公众号 MakerStack


  1. 创立客户端保护主键信息的资源 ↩
退出移动版