RESTFul

RestFul简介

REST:Representational State Transfer,表现层资源状态转移

资源:资源是一种看待服务器的方式

资源的表述:资源的表述是资源在某个特定时刻的状态的描述。可以在客户端-服务器端之间转移、交换。

状态转移:在客户端和服务器端之间转移(transfer)代表资源状态的描述,通过转移和操作资源的表述,来间接实现操作资源的目的。

说人话就是统一资源相同但操作不同的请求的请求路径,如getUserById和DeleteUserByName都设置资源路径为User

即:相同的请求路径、不同的请求方式表示不同的操作

RESTFul的实现

在Http协议中四个表示操作方式的动词:GET、Post、Put、Delete

传统方式 RESTFul方式
查询 findAllUser /user
get
id查询 getUserById?id=1 /user/1
get
添加 saveUser /user
post
修改 updateUser /user
put
删除 deleteUser /user
delete
Get和Post请求模拟
    @RequestMapping(value = "/user", method = RequestMethod.GET)
public String getAllUser() {
System.out.println("查询所有用户信息");
return "success";
}
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public String getUserById(@PathVariable("id") Integer id) {
System.out.println("根据id" + String.valueOf(id) +"查询所有用户信息");
return "success";
}
@RequestMapping(value = "/user", method = RequestMethod.POST)
public String addUser(@RequestParam("username") String username,
@RequestParam("password") String password) {
System.out.println("添加用户信息:" + username + "," + password);
return "success";
}
<a th:href="@{/user}">查询所有用户信息</a><br>
<a th:href="@{/user/1}">查询id为1的用户信息</a><br>
<form th:action="@{/user}" method="post">
UserName:<input type="text"name="username" value="宇多田光"><br>
Password:<input type="password"name="password" value="admin123"><br>
<input type="submit"><br>
</form>
Put和Delete请求模拟:使用HiddenHttpMethodFilter过滤器转换请求方式

form表单中的method方法设置为Post或者Delete是不起作用的,可以通过过滤器替换request请求的方法实现Put和Delete

    <filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

根据源码,实现请求方式转换需要有两个条件:

①请求方式为post

②必须传输一个name为_method值为put或者delete的请求参数

    <form th:action="@{/user}" method="post">
<input type="hidden" name="_method" value="put">
UserName:<input type="text"name="username" value="宇多田光"><br>
Password:<input type="password"name="password" value="admin123"><br>
<input type="submit"><br>

console:

修改用户信息:宇多田光,admin123
※HiddenHttpMethodFilter请求方式转换过滤器和CharacterEncodingFilter编码过滤器的顺序

CharacterEncodingFilter过滤器设置编码的前提条件是在此之前不能获取任何的请求参数,而HiddenHttpMethodFilter获取了name为_method的请求参数,因此CharacterEncodingFilter的< Filter-mapping > 要放在HiddenMethodFilter之前

RESTFull风格案例

通过请求方式实现Employee的增删改查

RESTFul方式
查询 /employee
get
id查询 /employee/1
get
添加 /employee
post
修改 /employee
put
删除 /employee/1
delete
employee_list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head> <body>
<table id="dataTable" border="1" cellspacing="0" cellpadding="0" style="text-align: center">
<tr>
<th colspan="5">Employee Information</th>
</tr>
<tr>
<td>Id</td>
<td>LastName</td>
<td>Email</td>
<td>Gender</td>
<td>Option</td>
</tr>
<tr th:each="employee : ${employeelist}">
<td th:text="${employee.id}"></td>
<td th:text="${employee.lastName}"></td>
<td th:text="${employee.email}"></td>
<td th:text="${employee.gender}"></td>
<td>
<a @click="deleteEmployee" th:href="@{/employee/} + ${employee.id}">delete</a>
<a th:href="@{/employee/} + ${employee.id}">update</a>
</td>
</tr>
</table> <form method="post" id="deleteForm">
<input name="_method" type="hidden" value="delete">
</form> <a th:href="@{/add}">添加</a> <script type="text/javascript" th:src="@{/static/js/vue.js}"></script>
<script type="text/javascript">
var vue = new Vue({
el: "#dataTable",
methods:{
deleteEmployee:function (event) {
console.log("HELLO")
var deleteFrom = document.getElementById("deleteForm");
//将触发点事件的href属性赋值给deleteform表单的action
deleteFrom.action = event.target.href;
//表单提交
deleteFrom.submit();
//取消超链接的默认行为
event.preventDefault();
}
}
});
</script> </body> </html>
显示操作:

/employee(请求) (GET) --> getAllEmploye(控制器方法) --> employee_list(前端页面)

    @RequestMapping(value = "/employee", method = RequestMethod.GET)
public String getAllEmployee(Model model) {
Collection<Employee> employeelist = employeeDao.getAll();
model.addAttribute("employeelist", employeelist);
return "employee_list";
}

①首先通过在SpringMVC.xml配置文件设置视图控制器实现/employee请求和getAllEmploye控制器方法的映射

②通过DAO获取employeelist并将其添加到request域中

③通过ThymeLeaf视图转发到前端页面employee_list.html

④在前端页面通过ThymeLeaf获取request域中的employeelist并渲染显示

删除操作:

/employee/{id} (DELETE) --> DeleteEmployeeById --> "redirect:/employee"

    @RequestMapping(value = "/employee/{id}", method = RequestMethod.DELETE)
public String DeleteEmployeeById(@PathVariable("id") Integer id) {
employeeDao.delete(id);
return "redirect:/employee";
}

①这里前端页面的删除是一个超链接,其内容经过Thymeleaf渲染后为 /employyee/1的形式而超链接默认只能通过get发送请求,因此直接点击会被当成“根据ID进行查询”的操作

<a @click="deleteEmployee" th:href="@{/employee/} + ${employee.id}">delete</a>

解决办法是使用Vue,通过给超链接添加一个点击事件,当用户点击时将点击事件的请求地址(/employyee/1)赋值给一个带有隐藏域的form表单的action,提交表单并且禁用点击事件的默认行为,最终服务器的过滤器组件HiddenHttpMethodFilter会将表单的post请求更改为delete请求。

转换请求方式用的deleteForm表单

    <form method="post" id="deleteForm">
<input name="_method" type="hidden" value="delete">
</form>

Vue实现转移事件

<script type="text/javascript" th:src="@{/static/js/vue.js}"></script>
<script type="text/javascript">
var vue = new Vue({
el: "#dataTable",
methods:{
deleteEmployee:function (event) {
console.log("HELLO")
var deleteFrom = document.getElementById("deleteForm");
//将触发点事件的href属性赋值给deleteform表单的action
deleteFrom.action = event.target.href;
//表单提交
deleteFrom.submit();
//取消超链接的默认行为
event.preventDefault();
}
}
});
</script>

如此一来就得到了一个请求路径为"/employee/1",请求方式为"Delete"的request

③通过DAO实现根据id删除

重定向到/employee请求,这里使用转发"employee_list"到前端页面的话,request是没有页面需要的内容的,因此需要重定向到请求/employee,经控制器方法向请求域添加employeelist才能使前端获取到数据

根据Id查询+修改操作

/employee/{id} (GET) --> toUpdateEmployee --> "employee_update"

/employee (POST-->PUT) --> UpdateEmployee --> "redirect:/employee"

①通过前端超链接点击的GET方式的请求,经ThymeLeaf渲染的请求路径为 /employee/id,然后经控制器方法toUpdateEmployee通过DAO根据id获取到Employee对象,然后向request域中添加此对象转发至前端页面employee_update

<a th:href="@{/employee/} + ${employee.id}">update</a>
    @RequestMapping(value = "/employee/{id}", method = RequestMethod.GET)
public String toUpdateEmployee(Model model,
@PathVariable("id") Integer id) {
Employee employee = employeeDao.get(id);
model.addAttribute("employee", employee);
return "employee_update";
}

②前端页面employee_update根据request域中的内容通过ThymeLeaf进行渲染回显

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div style="border: cornflowerblue 1px solid">
<form th:action="@{/employee}" method="post">
<input type="hidden" name="_method" value="put">
编号:<input type="text" name="id" th:value="${employee.id}"><br>
姓名:<input type="text" name="lastName" th:value="${employee.lastName}"><br>
邮箱:<input type="text" name="email" th:value="${employee.email}"><br>
性别:<input type="text" name="gender" th:value="${employee.gender}"><br>
<input type="submit" value="修改">
</form>
</div> </body>
</html>

③employee_update表单提交请求地址为 /employee请求方式为POST的request请求,因表单含有"_mothod"隐藏域,因此会服务器过滤器修改请求方式为PUT

④该请求会被被控制器方法UpdateEmployee匹配,经DAO修改后重定向到/employee请求

    @RequestMapping(value = "/employee", method = RequestMethod.PUT)
public String UpdateEmployee(Employee employee) {
employeeDao.save(employee);
return "redirect:/employee";
}
添加操作(略)

employee_list.html

<a th:href="@{/add}">添加</a>

springMVC.xml

<mvc:view-controller path="/add" view-name="employee_add"></mvc:view-controller>

employee_add.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div style="border: cornflowerblue 1px solid">
<form th:action="@{/employee}" method="post">
编号:<input type="text" name="id"><br>
姓名:<input type="text" name="lastName" value="宇多田光"><br>
邮箱:<input type="text" name="email" value="hikaru@163.com"><br>
性别:<input type="text" name="gender" value="1"><br>
<input type="submit" value="添加">
</form>
</div>
</body>
</html>

AddEmployee()

    @RequestMapping(value = "/employee", method = RequestMethod.POST)
public String AddEmployee(Employee employee) {
employeeDao.save(employee);
return "redirect:/employee";
}

【SpringMVC】(二)RESTFul的更多相关文章

  1. 基于springMVC的RESTful服务实现

    一,什么是RESTful RESTful(RESTful Web Services)一种架构风格,表述性状态转移,它不是一个软件,也不是一个标准,而是一种思想,不依赖于任何通信协议,但是开发时要成功映 ...

  2. SpringMVC实现RESTful服务

    SpringMVC实现RESTful服务 这里只说service,controller层的代码.Mapper层则直接继承Mapper<T>则可以,记住mybatis-config.xml一 ...

  3. springmvc的RESTful风格

    springmvc对RESTful得支持RESTful架构,就是目前最流行得一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以挣得到越来越多网站的采用. RESTful(即Repres ...

  4. 基于 springMVC 的 RESTful HTTP API 实践(服务端)

    理解 REST REST(Representational State Transfer),中文翻译叫"表述性状态转移".是 Roy Thomas Fielding 在他2000年 ...

  5. Spring+SpringMVC+MyBatis+easyUI整合进阶篇(二)RESTful API实战笔记(接口设计及Java后端实现)

    写在前面的话 原计划这部分代码的更新也是上传到ssm-demo仓库中,因为如下原因并没有这么做: 有些使用了该项目的朋友建议重新创建一个仓库,因为原来仓库中的项目太多,结构多少有些乱糟糟的. 而且这次 ...

  6. 004 使用SpringMVC开发restful API二--编写用户详情

    一:编写用户详情服务 1.任务 @PathVariable隐射url片段到java方法的参数 在url声明中使用正则表达式 @JsonView控制json输出内容 二:@PathVariable 1. ...

  7. 前后端分离开发,基于SpringMVC符合Restful API风格Maven项目实战(附完整Demo)!

    摘要: 本人在前辈<从MVC到前后端分离(REST-个人也认为是目前比较流行和比较好的方式)>一文的基础上,实现了一个基于Spring的符合REST风格的完整Demo,具有MVC分层结构并 ...

  8. 【SpringMVC】RESTful支持

    一.概述 1.1 什么是RESTful 1.2 URL的RESTful实现 二.演示 2.1 需求 2.2 第一步更改DispatcherServlet配置 2.3 第二步参数通过url传递 2.4 ...

  9. 优雅的SpringMVC和Restful

    一.前言 1.前段时间一直在写微信小程序的请求,终于把客户端的请求弄好了,可是服务端呢,该怎么写,纠结了半天,用servlet暂时写好了一个:http://www.cnblogs.com/JJDJJ/ ...

  10. spring 3.0 应用springmvc 构造RESTful URL 详细讲解

    在线springmvc_rest demo 由于下一版本的rapid-framwork需要集成spring RESTful URL,所以研究了一下怎么搭建. 并碰到了一下问题. springmvc 3 ...

随机推荐

  1. 常用功能系列---【JWT生成Token实现接口登录认证方案思路】

    JWT生成Token实现接口登录认证方案思路 方案一(双token实现无感刷新) 在token中,refreshToken的作用主要是避免token过期时,前端用户突然退出登录,跳转至登录页面. 但是 ...

  2. C语言初级阶段4——数组2————二维数组

    C语言初级阶段4--数组2----二维数组 二维数组的定义:类型说明符 数组名[数组大小] [数组大小] 第一个大小是行的大小,第二个大小是列的大小. 二维数组的初始化:{} #include< ...

  3. MySQL数据库封锁机制和事务隔离级别

    参考: 数据库技术:MySql学习笔记之事务隔离级别详解 详解MySQL 数据库隔离级别与MVCC MySQL 事务&&锁机制&&MVCC 数据库系统原理 - MySQ ...

  4. C++常见报错信息和原因的对应关系

    1. 无法找到 xxx.dll 没有把动态链接库和exe放在一个文件夹下 2. 不允许使用不完整的类型 指的是忘了加头文件 3. link err .无法解析的外部符号 指的是 lib 库没有配置对 ...

  5. JavaScript 包装类

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. Vue 解决先渲染 暂无数据

    // 组件 data(){ return { data:null // 设置默认值为null } } // template <div v-show="data != null&quo ...

  7. [Unity基础]碰撞和触发

    参考链接: https://www.cnblogs.com/hont/p/4472326.html 碰撞关系表: https://docs.unity3d.com/Manual/CollidersOv ...

  8. MySQLdb安装

    yum seach MySQL-Python sudo yum install MySQL-python.x86_64 import MySQLdb

  9. Ubuntu 14.04环境编译android源码android-5.0.2_r1.7z

    环境: Win7:8G内存 vmware:vm给ubuntu分配4G内存80G空间 参考视频: https://www.bilibili.com/video/BV15t411R78o ubuntu14 ...

  10. windows 安装mysql57

    1. 配置my.ini文件 在根目录下新建 "my.ini" 文件: 添加配置: [mysql] # 设置mysql客户端默认字符集 default-character-set=u ...