restful post请求_猿蜕变9——一文搞定SpringMVC的RESTFul套路
看过之前的蜕变系列文章,相信你对springMVC有了一定的认识。对springMVC的Interceptor拦截器,也有了一定的认识。今天我们来开启新讨论,讲一讲springMVC对那一种休闲风的支付——RestFul。
每月底工厂君会根据后台记录筛选转发文章前三位的朋友,给与奖励,第一名100元,第二名50元,第三名30元的现金奖励。行动力超强的你,关注公号,转发文章,赶紧动起来吧!目前来看排名如下,胖子是我本人,不算的,大家多多努力噢。在路上同学,一直感谢你的默默关注,赶紧加我的微信,月底了,保持住,奖励就是你的。
猿蜕变同样是一个原创系列文章,帮助你从一个普通的小白,开始掌握一些行业内通用的框架技术知识以及锻炼你对系统设计能力的提升,完成属于你的蜕变,更多精彩内容,敬请大家关注公主号猿人工厂,点击猿人养成获取!
都0202年了,再不会RestFul的URL风格的东西,你都不好意思出门了。Roy Fielding提出论文都20年了,这种清爽的,含有意义的URL几乎所有的有点逼格的站点都在跟风靠拢。
REST的英文全称是——Representational StateTransfer,中文含义是表现层状态传输,目前主流的Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,无论是对URL的处理还是对Payload的编码,REST都倾向于用更加简单轻量的方法设计和实现。
值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。RESTful是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义(就目前而言基本上是JSON的天下了)。rest是一种架构风格,跟编程语言无关,跟平台无关,RESTFUL特点包括:
1、每一个URI代表1种资源;
2、客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;
3、通过操作资源的表现形式来操作资源;
4、资源的表现形式是XML或者HTML;
5、客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息
RESTful对url要求非常严格,要求每一个URI都表示一个资源。我们看看下面两个URL:
127.0.0.1/xxx.do?id=1
127.0.0.1/xxx/1
127.0.0.1/xxx/1是属于RESTful风格的,而127.0.0.1/xxx.do?id=1就不是RESTful风格了。
使用RESTful架构,你的应用结构就变成了下图所描述的一样:
注意噢,你的应用更多的是使用JSON数据格式返回数据共其他应用使用,你就是其他应用的数据源!
项目开发引入RESTful架构,利于团队并行开发。在RESTful架构中,将多数HTTP请求转移到前端服务器上,降低服务器的负荷,使视图获取后端模型失败也能呈现。但RESTful架构却不适用于所有的项目,当项目比较小时无需使用RESTful架构,项目变得更加复杂。
接下来我们就开始学习怎样再Spring MVC中使用RESTFul的架构风格。在这之前我们先了了解下Spring MVC中和RESTFul相关的一个Annotation:
@RequestBody
restful风格的请求数据是使用json格式,此时我们在要接收请求参数的javabean前面添加@RequestBody就可以将请求的数据赋值到相应的bean属性中。
@GetMapping该注解用来替代RequestMapping,特点是@GetMapping只处理get方式的请求。
@PostMapping该注解用来替代RequestMapping,特点是@PostMapping只处理post方式的请求。
@PutMapping该注解用来替代RequestMapping,特点是@PutMapping只处理put方式的请求。
@DeleteMapping该注解用来替代RequestMapping,特点是@DeleteMapping只处理delete方式的请求。
以上注解就是在restful架构风格中spring mvc常用的注解,下面我们来完成一个restful风格的例子。
前端和后端的数据传输都使用json格式了,所以需要引入json相关的依赖之前已经讲过了,这里就不多讲了。要实现restful风格,还需要修改web.xml文件里面的中央控制器的url匹配方式,不能是*.do之类的了,需要要改成/。
<?xml version="1.0" encoding="UTF-8"?><web-appxmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <filter> <filter-name>characterEncodingFilterfilter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class> <init-param> <param-name>encodingparam-name> <param-value>utf-8param-value> init-param> <init-param> <param-name>forceEncodingparam-name> <param-value>trueparam-value> init-param>filter><filter-mapping> <filter-name>characterEncodingFilterfilter-name> <url-pattern>/*url-pattern>filter-mapping> <servlet> <servlet-name>springMVCservlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class> <init-param> <param-name>contextConfigLocationparam-name> <param-value>classpath:springmvc.xmlparam-value> init-param> <load-on-startup>1load-on-startup>servlet><servlet-mapping> <servlet-name>springMVCservlet-name> <url-pattern>/url-pattern>servlet-mapping> web-app>
我们之前将前端控制器的路径设置为”/”,所有的请求都会通过前端控制器转发,这样静态资源的访问也会被当作controller的请求,所以我们同样需要做一些处理。
除了需要在springmvc的配置文件中添加静态资源,我们还需要设置json格式的字符编码,否则可能会在响应时出现乱码。
springMVC使用的StringHttpMessageConverter默认字符编码是ISO_8859_1,这样就会导致响应头中出现Content-Type: text/plain;charset=ISO-8859-1,即使你使用了spring mvc中自带的编码过滤器也会出现乱码问题,因为在字符编码过滤器中没有设置响应的Content-Type,所以最好在配置文件中设置json格式的字符编码为UTF-8。
<?xmlversion ="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"> <beanid="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter"> <propertyname="supportedMediaTypes"> <list> <value>text/plain;charset=UTF-8value> <value>application/json;charset=UTF-8value> list> property> bean> <mvc:annotation-driven> <mvc:message-convertersregister-defaults="true"> <bean> <propertyname="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8value> <value>application/jsonvalue> <value>application/xml;charset=UTF-8value> list> property> <propertyname="features"> <list> <value>WriteMapNullValuevalue> <value>WriteNullNumberAsZerovalue> <value>WriteNullListAsEmptyvalue> <value>WriteNullStringAsEmptyvalue> <value>WriteNullBooleanAsFalsevalue> <value>WriteDateUseDateFormatvalue> list> property> bean> mvc:message-converters> mvc:annotation-driven> <mvc:resourcesmapping="/images/**" location="/images/" /> <mvc:resourcesmapping="/js/**" location="/js/" /> <mvc:resourcesmapping="/css/**" location="/css/" /> <mvc:resourcesmapping="/html/**" location="/html/" /> <context:component-scanbase-package="com.pz.web.study.springmvc.*"/> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/> <bean> <property name="prefix"value="/jsp/"/> <property name="suffix"value=".jsp"/> bean> beans>
本文针对SpringMVC的讲解,暂时不需要数据库方面的操作,因此我们编写一个DataUtil.java工具类来提供数据支持。下面是rest风格的controller的写法,一个rest风格的url中是不能包含动词的(当然你写动词了也不会出问题),因为在rest风格眼中,互联网中的任何一个资源都是一个事物。
package com.pz.web.study.springmvc; import java.time.LocalDate;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set; public class DataUtil { private staticHashMap dataMap = new HashMap<>(); //mock data初始化 static{ User user1 = newUser("pangzi", "13188888888", "北京",LocalDate.of(2010, 10, 10)); User user2 = newUser("matou", "13866666666", "上海",LocalDate.of(2014, 11, 11)); User user3 = newUser("xxxxxx", "13799999999", "广州",LocalDate.of(2012, 12, 12)); dataMap.put("1", user1); dataMap.put("2", user2); dataMap.put("3", user3); } /** * 查找全部数据 * @return */ public staticHashMapfindAll(){ return dataMap; } /** * 根据id查找用户 * @param id * @return */ public static UserfindById(String id){ returndataMap.get(id); } /** * 创建用户 * @param user * @throws Exception */ public static voidcreate(User user) throws Exception{ //遍历map找到key的最大值 Set> entries = dataMap.entrySet(); Iterator> iterator =entries.iterator(); int max = 3; while(iterator.hasNext()) { Map.Entry next = iterator.next(); int i =Integer.parseInt(next.getKey()); if (i >max) { max = i; } } //将最大值做自增运算,然后作为key放入map中 dataMap.put(++max+"", user); } /** * 更新用户 * @param id * @param user */ public static voidupdate(String id, User user) throws Exception { dataMap.put(id,user); } /** * 根据id删除用户 * @param id * @throws Exception */ public static voiddelete(String id) throws Exception { dataMap.remove(id); }}
package com.pz.web.study.springmvc; import com.alibaba.fastjson.JSON;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; @RestControllerpublic class RestFulController { /** * 查找所有用户 * * @return * @throws Exception */ @GetMapping("/users") public String findAll()throws Exception { HashMap allUser = DataUtil.findAll(); returnJSON.toJSONString(allUser); } /** * 根据id查找 * * @param id * @return * @throws Exception */ @GetMapping("/users/{id}") public StringfindById(@PathVariable String id) throws Exception { User user =DataUtil.findById(id); returnJSON.toJSONString(user); } /** * 新增 * * @param user * @return */ @PostMapping("/users") public Stringcreate(@RequestBody User user) { try { DataUtil.create(user); System.out.println(user.getName()); } catch (Exceptione) { e.printStackTrace(); returnJSON.toJSONString("fail"); } returnJSON.toJSONString("success"); } /** * 更新 * * @param id * @param user * @return */ @PutMapping("/users/{id}") public Stringupdate(@PathVariable String id, @RequestBody User user) { try { DataUtil.update(id, user); } catch (Exceptione) { e.printStackTrace(); returnJSON.toJSONString("fail"); } returnJSON.toJSONString("success"); } /** * 删除 * * @param id * @return */ @DeleteMapping("/users/{id}") public Stringdelete(@PathVariable String id) { try { DataUtil.delete(id); } catch (Exception e) { e.printStackTrace(); returnJSON.toJSONString("fail"); } returnJSON.toJSONString("success"); }}
其实rest风格的前端可以完全不用使用jsp了,关于这一点,在之前的猿进化系列17——实战之一文学会前后端分离套路中已经讨论得淋漓尽致了。
接下来在webapp目录下创建html文件夹:
user_list.html:
<html><head> <metacharset="utf-8"> <metahttp-equiv="X-UA-Compatible" content="IE=edge"> <metaname="viewport" content="width=device-width,initial-scale=1"> <title>用户列表title> <linkhref="../css/bootstrap.css" rel="stylesheet">head><body><div class="container theme-showcase"role="main"> <divid="msg">div> <div> <inputtype="text" id="user-id" name="id"placeholder="请输入id"> <buttonid="query" type="button" class="btn btn-smbtn-primary">查询button> <buttonid="add" type="button" class="btn btn-smbtn-success">添加button> div> <div> <div> <tableclass="table table-striped"> <thead> <tr> <th>编号th> <th>姓名th> <th>手机th> <th>生日th> <th>地址th> <th>操作th> tr> thead> <tbodyid="tbody"> <tr> <td> td> tr> tbody> table> div> div>div><scriptsrc="../js/jquery-3.3.1.min.js">script><script src="../js/bootstrap.js">script><script> $(function () { //查找 getAll(); //绑定删除按钮的点击事件 $("#tbody").on("click", ".btn-info",function () { var flag =confirm("是否删除?"); if(flag){ deleteUser(this); } }); //绑定修改按钮的点击事件 $("#tbody").on("click", ".btn-warning",function () { var userId =this.parentNode.parentNode.firstChild.innerHTML; $(location).attr('href', '/html/user_update.html?id='+userId); }); //绑定添加按钮的点击事件 $("#add").click(function () { $(location).attr('href', '/html/user_add.html'); }); $("#query").click(function () { var userId =$("#user-id").val(); if(userId !=""){ getUserById(userId); }else{ getAll(); } }); }); functiongetUserById(userId) { $.ajax({ url:"/users/"+userId, type:"get", dataType:"json", success:function (result) { var dataTR = "" +
"" + userId + "" +"" + result.name + "" +
"" + result.phone + "" +
"" +result.birthday + "" +
"" + result.address + "" +
"" +
"删除"+"修改"+
"
" +"
"; $("#tbody").html(dataTR); } }); } //查找 function getAll() { $.ajax({ url:"/users", type:"get", dataType:"json", success:function (result) { var dataTR= ""; $.each(result, function (index, value) { dataTR+= "" +"" + index + "" +
"" + value.name + "" +
"" + value.phone + "" +
"" + value.birthday + "" +
"" + value.address + "" +
"" +
"删除"+"修改"+
"
" +"
"; }); $("#tbody").html(dataTR); } }); } //删除 functiondeleteUser(obj) { var userId =obj.parentNode.parentNode.firstChild.innerHTML; $.ajax({ url:"/users/"+userId, type:"delete", dataType:"json", success:function (result) { getAll(); console.log(result) if(result== "success"){ //提示信息 varmsg = '
删除成功!
'; $('#msg').html(msg); setTimeout(function(){ $('#msg').empty(); },2000); }else{ //提示信息 varmsg = '
删除失败!
'; $('#msg').html(msg); setTimeout(function(){ $('#msg').empty(); },2000); } } }); }script>body>html>
user_add.html:
<html><head> <metacharset="utf-8"> <metahttp-equiv="X-UA-Compatible" content="IE=edge"> <metaname="viewport" content="width=device-width,initial-scale=1"> <title>新增用户title> <linkhref="../css/bootstrap.css" rel="stylesheet">head><body><div>div><div> <divid="msg">div> <formid="user-form" style="max-width: 330px;padding: 15px;margin: 0auto;"> <div> <labelfor="name">姓名:label> <inputtype="text" id="name"name="name"> div> <div> <labelfor="phone">手机:label> <inputtype="text" id="phone"name="phone"> div> <div> <labelfor="birthday">生日:label> <inputtype="date" id="birthday"name="birthday"> div> <div> <labelfor="address">地址:label> <input type="text"class="form-control" id="address"name="address"> div> <buttontype="button" class="btn btn-sm btn-primary">添加button> form>div>body><scriptsrc="../js/jquery-3.3.1.min.js">script><script src="../js/bootstrap.js">script><script> $(function () { $(".btn-primary").click(function () { var jsonForm=$('#user-form').serializeArray(); var jsonData ={}; $.each(jsonForm,function (i,v) { jsonData[v.name] = v.value; }); var params =JSON.stringify(jsonData); $.ajax({ url:"/users", type:"post", data:params, dataType:"json", contentType:"application/json", success:function (result) { if(result == "success"){ $(location).attr('href', '/html/user_list.html'); }else{ //提示信息 varmsg = '
添加失败!
'; $('#msg').html(msg); setTimeout(function(){ $('#msg').empty(); },2000); } } }); }); });script>html>
user_update.html:
<html><head> <metacharset="utf-8"> <metahttp-equiv="X-UA-Compatible" content="IE=edge"> <metaname="viewport" content="width=device-width,initial-scale=1"> <title>修改用户title> <linkhref="../css/bootstrap.css" rel="stylesheet">head><body><div>div><div> <formid="user-form" style="max-width: 330px;padding: 15px;margin: 0auto;"> <inputtype="hidden" id="id"> <div> <labelfor="name">姓名:label> <inputtype="text" id="name"name="name"> div> <div> <labelfor="phone">手机:label> <inputtype="text" id="phone"name="phone"> div> <div> <labelfor="birthday">生日:label> <input type="date"class="form-control" id="birthday"name="birthday"> div> <div> <labelfor="address">地址:label> <inputtype="text" id="address"name="address"> div> <buttontype="button" class="btn btn-sm btn-primary">修改button> form>div>body><scriptsrc="../js/jquery-3.3.1.min.js">script><script src="../js/bootstrap.js">script><script> $(function () { //从url中获取携带的参数 var userId =location.search.split("="); $("#userId").val(userId[1]); //查询要修改的数据 $.ajax({ url:"/users/"+userId[1], type:"get", dataType:"json", success:function (result) { $("#name").val(result.name); $("#phone").val(result.phone); $("#address").val(result.address); $("#birthday").val(result.birthday); } }); $(".btn-primary").click(function () { var jsonForm=$('#user-form').serializeArray(); var jsonData ={}; $.each(jsonForm,function (i,v) { jsonData[v.name] = v.value; }); var params = JSON.stringify(jsonData); $.ajax({ url:"/users/"+userId[1], type:"put", data:params, dataType:"json", contentType:"application/json", success:function(result) { if(result == "success"){ $(location).attr('href', '/html/user_list.html'); }else{ //提示信息 varmsg = '
添加失败!
'; $('#msg').html(msg); setTimeout(function(){ $('#msg').empty(); },2000); } } }); }); });script>html>
以上示例就是基于spring mvc的restful架构风格。
我建了一个群,群里有很多高手,欢迎大家入群探讨。
restful post请求_猿蜕变9——一文搞定SpringMVC的RESTFul套路相关推荐
- 普通类创建获取session 方式_猿蜕变11——一文搞懂mybatis花式使用方式
看过之前的蜕变系列文章,相信你对mybatis有了初步的认识.但是这些还不够,我们今天进一步来了解下mybatis的一些用法. 猿蜕变同样是一个原创系列文章,帮助你从一个普通的小白,开始掌握一些行业内 ...
- python爬虫结果是字节_入门爬虫?一文搞定!
为了感谢大家对"Python客栈"的关注与支持,我们每天会在留言中随机抽取三位粉丝发放6.6元小红包.快来参与吧! 文章分三个个部分 两个爬虫库requests和selenium如 ...
- Spring Boot 异步请求和异步调用,一文搞定!
一.Spring Boot中异步请求的使用 1.异步请求与同步请求 特点: 可以先释放容器分配给请求的线程与相关资源,减轻系统负担,释放了容器所分配线程的请求,其响应将被延后,可以在耗时处理完成(例如 ...
- springboot服务调用超时_Spring Boot 异步请求和异步调用,一文搞定
一.Spring Boot中异步请求的使用 1.异步请求与同步请求 特点: 可以先释放容器分配给请求的线程与相关资源,减轻系统负担,释放了容器所分配线程的请求,其响应将被延后,可以在耗时处理完成(例如 ...
- php带参数单元测试_一文搞定单元测试核心概念
基础概念 单元测试(unittesting),是指对软件中的最小可测试单元进行检查和验证,这里的最小可测试单元通常是指函数或者类.单元测试是即所谓的白盒测试,一般由开发人员负责测试,因为开发人员知道被 ...
- jsp中的url拼接的参数传递到controller乱码_猿蜕变系列5——一文搞懂Controller的花式编写...
看过之前的执行流程,相信你对springMVC有了一定的认识.今天我们继续来学习springMVC相关的核心知识,帮助你快速起飞,完成蜕变. 每月底工厂君会根据后台记录筛选转发文章前三位的朋友,给与奖 ...
- jsp文件上传_猿蜕变系列7——也说说springMVC上传姿势
看过之前的蜕变系列文章,相信你对springMVC有了一定的认识.对springMVC的异常处理,也有了一定的认识.今天我们来开启新讨论,讲一讲web开发中会经常遇到的一个功能,文件上传. 猿蜕变同样 ...
- rest api是什么_一文搞懂什么是RESTful API
RESTful接口实战 首发公众号:bigsai 转载请附上本文链接 文章收藏在回车课堂 前言 在学习RESTful 风格接口之前,即使你不知道它是什么,但你肯定会好奇它能解决什么问题?有什么应用场景 ...
- python网页爬虫循环获取_手把手教你用 Python 搞定网页爬虫
原标题:手把手教你用 Python 搞定网页爬虫 编译:欧剃 作为数据科学家的第一个任务,就是做网页爬取.那时候,我对使用代码从网站上获取数据这项技术完全一无所知,它偏偏又是最有逻辑性并且最容易获得的 ...
最新文章
- 全新的Spring Authorization Server快速入门
- win7-X64下用VM安装linux系统CentOS
- cocos2d-x plist使用
- VTK:参数样条用法实战
- OS- -操作系统常见问题总结
- ubuntu的mysql教程 pdf_Ubuntu上的MySQL字符集设置技巧
- 挖掘建模-分类与预测-回归分析-逻辑回归
- unity android 在后台运行_Unity问答 | 盘点2019年社区优秀问答
- Log4J基础详解及示例大全
- html——inline、block与block-inline区别
- linux中id命令的功能,Linux id命令参数及用法详解
- 雷军自述:我十年的程序员生涯
- 与人和代码打交道,有何不同?
- 线性同余法产生(0,1)均匀分布的随机数
- Springboot配置log4j2配置文件和log4j2.xml详解
- win10共享打印机搜索不到计算机,大师告诉您Win10搜不到共享打印机的操作方案...
- 数组分割 java_分割java数组
- 笑着学Spring - (3) - Spring事务管理
- C语言编程——输入某年某月某日,判断这一天是这一年的第几天?
- Fires Dynamics Simulator(FDS)软件运行代码说明
热门文章
- java 加法表编程_java编程——数据的加法
- java中pi_Java-Pi的几种实现
- 显示封装_怎么显示与隐藏原理图库的PCB封装名称?
- python怎么检查数据库实例能否链接_python pymysql链接数据库查询结果转为Dataframe实例...
- Java字符串格式化
- 记录华为P40Pro+系列相机参数总结
- c语言编程获取当前系统时间包含年,月,日,时,分,秒.,C语言获取系统时间的几种方式...
- java离群值,监视-衡量Java中单线程复杂算法的最佳宏基准测试工具/框架是什么?...
- linux打开没有图形界面,linux无法打开图形界面
- php error 2,一起搞懂PHP的错误和异常(二)