SpringBoot使用RESTful风格开发Web项目

1. RESTful风格介绍

RESTful架构风格是目前最流行的一种架构风格,它机构清晰、符合标准、易于理解、扩展方便,所以在Web开发中经常被使用。
REST,全称是Representational State Transfer,译作“表现层状态转化”,在 2000 年 Roy Fielding 的博士论文中首次被提出。面向资源是REST明显的特征,对于同一个资源的一组不同的操作。资源是服务器 上一个可命名的抽象概念,资源是以名词为核心来组织的,首先关注的是名词。REST要求必须通过统一的接口来对资源执行各种操作。对于每个资源只能执行一组有限的操作。

详细介绍参照RESTful百度百科

2. RESTful常用接口规范

简单介绍一下安全性和幂等,下面会提及:

  1. 安全性 :不会改变资源状态,可以理解为只读的;
  2. 幂等性 :执行1次和执行N次,对资源状态改变的效果是等价的。

2.1 GET

安全且幂等
获取表示
变更时获取表示(缓存)

状态码表示的状态
200(OK)已在响应中发出
204(无内容)资源有空
301(Moved Permanently)资源的URI已被更新
303(See Other)其他(如,负载均衡)
304(not modified)资源未更改(缓存)
400 (bad request)指代坏请求(如,参数错误)
404 (not found)资源不存在
406 (not acceptable)服务端不支持所需表示
500 (internal server error)通用错误响应
503 (Service Unavailable)服务端当前无法处理请求

2.2POST

不安全且不幂等
使用服务端管理的(自动产生)的实例号创建资源
创建子资源
部分更新资源
如果没有被修改,则不过更新资源(乐观锁)

状态码表示的状态
200(OK)现有资源已被更改
201(created)新资源被创建
202(accepted)已接受处理请求但尚未完成(异步处理)
301(Moved Permanently)资源的URI已被更新
303(See Other)其他(如,负载均衡)
400 (bad request)指代坏请求(如,参数错误)
404 (not found)资源不存在
406 (not acceptable)服务端不支持所需表示
409 (conflict)通用冲突
412(Precondition Failed)前置条件失败(如执行条件更新时的冲突)
415 (unsupported media type)接受到的表示不受支持
500 (internal server error)通用错误响应
503 (Service Unavailable)服务端当前无法处理请求

2.3 PUT

不安全但幂等
用客户端管理的实例号创建一个资源
通过替换的方式更新资源
如果未被修改,则更新资源(乐观锁)

状态码表示的状态
200(OK)现有资源已被更改
201(created)新资源被创建
301(Moved Permanently)资源的URI已被更新
303(See Other)其他(如,负载均衡)
400 (bad request)指代坏请求(如,参数错误)
404 (not found)资源不存在
406 (not acceptable)服务端不支持所需表示
409 (conflict)通用冲突
412(Precondition Failed)前置条件失败(如执行条件更新时的冲突)
415 (unsupported media type)接受到的表示不受支持
500 (internal server error)通用错误响应
503 (Service Unavailable)服务端当前无法处理请求

2.4 DELETE

不安全但幂等
删除资源

状态码表示的状态
200(OK)现有资源已被更改
301(Moved Permanently)资源的URI已被更新
303(See Other)其他(如,负载均衡)
400 (bad request)指代坏请求(如,参数错误)
404 (not found)资源不存在
409 (conflict)通用冲突
500 (internal server error)通用错误响应
503 (Service Unavailable)服务端当前无法处理请求

3.传统风格与RESTful风格简单对比

操作传统风格URLmethod-------------RESTful风格URLmethod
增加/addUser?name=xxxPOST/usersPOST
删除/deleteUser?id=1GET/user/1DELETE
修改/updateUser?id=123&name=testPOST/users/123PUT
查询/listUserGET/usersGET
指定查询/getUser?id=456GET/users/456GET

4.项目实战

4.1 新建数据

创建数据库

create database restful;

创建表

use restful;
CREATE TABLE user (
  id int(11) NOT NULL AUTO_INCREMENT,
  name varchar(30),
  PRIMARY KEY (id)
) DEFAULT CHARSET=UTF8;

添加数据备用

insert into user values(null,'user 1');
insert into user values(null,'user 2');
insert into user values(null,'user 3');
insert into user values(null,'user 4');
insert into user values(null,'user 5');
insert into user values(null,'user 6');

4.2 构建项目

这次项目用springboot+mybatis+mysql

全工程构造:
在这里插入图片描述
开始新建工程:
在这里插入图片描述
项目信息如下
在这里插入图片描述
勾选Web模板
在这里插入图片描述

4.2.1 修改pom.xml文件,添加如下依赖;

        <!-- servlet依赖. -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
        <!-- tomcat的支持.-->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>
        <!-- mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version><!--我装的是8.0.15版本-->
        </dependency>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.3</version>
        </dependency>
        <!--添加PageHelper的支持,用于分页-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.6</version>
        </dependency>
        

4.2.2 修改application.properties文件

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/restful?useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=666666
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

注意:我用得是Mysql8.0 所以驱动类是 com.mysql.cj.jdbc.Driver如果是其他版本请改用com.mysql.jdbc.Driver

4.2.3 新建一个PageHelperConfig 类用于配置

package com.eknaij.springbootrestful.config;

import com.github.pagehelper.PageHelper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Properties;

@Configuration
public class PageHelperConfig {
    @Bean
    public PageHelper pageHelper() {
        PageHelper pageHelper = new PageHelper();
        Properties p = new Properties();
        p.setProperty("offsetAsPageNum", "true"); //offsetAsPageNum:设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用.
        p.setProperty("rowBoundsWithCount", "true"); //rowBoundsWithCount:设置为true时,使用RowBounds分页会进行count查询.
        p.setProperty("reasonable", "true");//reasonable:启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页。
        pageHelper.setProperties(p);
        return pageHelper;
    }
}

4.2.4 新建一个User,只包含id和name

package com.eknaij.springbootrestful.pojo;

public class User {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

4.2.5 新建一个UserMapper接口

package com.eknaij.springbootrestful.mapper;

import com.eknaij.springbootrestful.pojo.User;
import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface UserMapper {
    @Select("select * from user ")
    List<User> findAll();
    @Insert(" insert into user ( name ) values (#{name}) ")
    public int save(User user);

    @Delete(" delete from user where id= #{id} ")
    public void delete(int id);

    @Select("select * from user where id= #{id} ")
    public User get(int id);

    @Update("update user set name=#{name} where id=#{id} ")
    public int update(User user);
}


4.2.6 新建controller类

package com.eknaij.springbootrestful.controller;

import com.eknaij.springbootrestful.mapper.UserMapper;
import com.eknaij.springbootrestful.pojo.User;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@Controller
public class UserController {
    @Autowired
    UserMapper userMapper;
    @RequestMapping("/listUser")
    //在参数里接受当前是第几页 start ,以及每页显示多少条数据 size。 默认值分别是0和5。
    public String listUser(Model model, @RequestParam(value = "start", defaultValue = "0") int start,
                               @RequestParam(value = "size", defaultValue = "5") int size) throws Exception {
        //根据start,size进行分页
        PageHelper.startPage(start,size);
        List<User> cs=userMapper.findAll();
        PageInfo<User> page = new PageInfo<>(cs);
        model.addAttribute("page", page);
        return "listUser";
    }
    @RequestMapping("/addUser")
    public String addUser(User c) throws Exception {
        userMapper.save(c);
        return "redirect:listUser";
    }
    @RequestMapping("/deleteUser")
    public String deleteUser(User c) throws Exception {
        userMapper.delete(c.getId());
        return "redirect:listUser";
    }
    @RequestMapping("/updateUser")
    public String updateUser(User c) throws Exception {
        userMapper.update(c);
        return "redirect:listUser";
    }
    @RequestMapping("/editUser")
    public String getUser(int id, Model m) throws Exception {
        User c= userMapper.get(id);
        m.addAttribute("c", c);
        return "editUser";
    }
}


4.2.7 新建视图listUser.jsp(采用传统的方法)

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<div align="center">

</div>

<div style="width:500px;margin:20px auto;text-align: center">
    <table align='center' border='1' cellspacing='0'>
        <tr>
            <td>id</td>
            <td>name</td>
            <td>编辑</td>
            <td>删除</td>
        </tr>
        <c:forEach items="${page.list}" var="c" varStatus="st">
            <tr>
                <td>${c.id}</td>
                <td>${c.name}</td>
                <td><a href="editUser?id=${c.id}">编辑</a></td>
                <td><a href="deleteUser?id=${c.id}">删除</a></td>
            </tr>
        </c:forEach>

    </table>
    <br>
    <div>
        <a href="?start=1">[首  页]</a>
        <a href="?start=${page.pageNum-1}">[上一页]</a>
        <a href="?start=${page.pageNum+1}">[下一页]</a>
        <a href="?start=${page.pages}">[末  页]</a>
    </div>
    <br>
    <form action="addUser" method="post">

        name: <input name="name"> <br>
        <button type="submit">提交</button>

    </form>
</div>

4.2.8 新建一个editUser.jsp用于修改信息:

<%@ page language=“java” contentType=“text/html; charset=UTF-8”
pageEncoding=“UTF-8” isELIgnored=“false”%>

<form action="updateUser" method="post">

    name: <input name="name" value="${c.name}"> <br>

    <input name="id" type="hidden" value="${c.id}">
    <button type="submit">提交</button>

</form>

4.2.9 浏览器启动测试

运行项目,浏览器输入http://localhost:8080/listUser,可以看到如下信息:
在这里插入图片描述
CRUD操作可以用,接下来我们修改成RESTful风格

5. 修改成RESTful风格

5.1 修改listUser.jsp

  1. 增加:把form表单的 action修改为"users"

修改action为users
将Usercontroller中addUser方法的@RequestMapping("/addUser")改成@PostMapping("/users"),跟前面表单的action对应

  1. 删除:由于一个页面中只能用一个submit按钮提交一个form表单,所以这里我们采用JS进行提交,原理上是一样的,相当于把action改成了users/${c.id},把method改成了DELETE
    修改删除的超链接:
    在这里插入图片描述
    在后面添加一个用于提交删除的表单:
    在这里插入图片描述

然后新建JS文件夹,导入JS:
在这里插入图片描述
在JSP中导入文件<script type="text/javascript" src="js/jquery.min.js"></script>
编写JS,如下

<script type="text/javascript" src="js/jquery.min.js"></script>
 
    <script type="text/javascript">
       /*将post method 改变为delete*/
      $(function(){                    
           $(".delete").click(function(){
               var href=$(this).attr("href");
               $("#formdelete").attr("action",href).submit();
               return false;
           })
       })
   </script>  

注意:一般实际开发中删除要进行二次确认,在此为了方便便省略了

将Usercontroller中deleteUser方法的@RequestMapping("/deleteUser")改成 @DeleteMapping("/users/{id}")

  1. 指定查询:url修改为users/id
    在这里插入图片描述
    将Usercontroller中getUser方法的@RequestMapping("/editUser")改成@GetMapping("/users/{id}")

  2. 修改:
    将editUser.jsp页面form表单页面的action改成users/id的形式,方法为PUT:
    由于form表单的method没有PUT方法 所以我们用一个隐藏的input修改method方法为PUT
    在这里插入图片描述

将Usercontroller中updateUser方法的@RequestMapping("/updateUser")改成@PutMapping("/users/{id}")

最终Usercontroller类如图:

在这里插入图片描述

红框中的为已修改后的内容

6. 测试RESTful风格

由于之前我们进行了修改,所以重新启动项目后,浏览器输入的url为http://localhost:8080/users,运行正确就可以看到和之前一样的界面:
在这里插入图片描述
如果CRUD操作都没有问题就OK了

7.总结

RESTful风格与传统风格大同小异,关键的地方要注意

  1. 前端视图表单提交的action要与后端相对应
  2. 不同的操作使用的注解不一样,下面汇总为一个表格方便对比:
操作使用的注解
增加@PostMapping("")
删除@DeleteMapping("")
修改@PutMapping("")
查询@GetMapping("")

本文源码:点击前往

  • 2
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值