Restful简介
Restful风格的API是一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
在Restful风格中,用户请求的url使用同一个url而用请求方式:get,post,delete,put...等方式对请求的处理方法进行区分,这样可以在前后台分离式的开发中使得前端开发人员不会对请求的资源地址产生混淆和大量的检查方法名的麻烦,形成一个统一的接口。
在Restful风格中,现有规定如下:
- GET(SELECT):从服务器查询,可以在服务器通过请求的参数区分查询的方式。
- POST(CREATE):在服务器新建一个资源,调用insert操作。
- PUT(UPDATE):在服务器更新资源,调用update操作。
- DELETE(DELETE):从服务器删除资源,调用delete语句
了解这个风格定义以后,我们举个例子:
如果当前url是 http://localhost:8080/User
那么用户只要请求这样同一个URL就可以实现不同的增删改查操作,例如
- http://localhost:8080/User?_method=get&id=1001 这样就可以通过get请求获取到数据库 user表里面 id=1001 的用户信息
- http://localhost:8080/User?_method=post&id=1001&name=zhangsan 这样可以向数据库user 表里面插入一条记录
- http://localhost:8080/User?_method=put&id=1001&name=lisi 这样可以将 user表里面 id=1001 的用户名改为lisi
- http://localhost:8080/User?_method=delete&id=1001 这样用于将数据库user 表里面的id=1001 的信息删除
这样定义的规范我们就可以称之为restful风格的API接口,我们可以通过同一个url来实现各种操作
实现
在springMVC中实现restful风格开发
测试
写接口前,先写好单元测试,这样可以理清思路、效验接口正确性,正所谓测试先行。
这里,我通过访问http://127.0.0.1:8080/study_ssmvc/restful接口的method不同来进入不同的controller方法,并打印返回数据。
-
-
-
-
-
- public classRestfulTest {
-
-
-
-
-
- @Test
- public void testGet() throws IOException {
- Stringparam= "id=1&name=2";
- StringurlStr= "http://127.0.0.1:8080/study_ssmvc/restful" + "?"+ param;
- URLurl= newURL(urlStr);
- HttpURLConnectionconn= (HttpURLConnection)url.openConnection();
- conn.setRequestMethod("GET");
- conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
- InputStreamis = conn.getInputStream();
- int count = 0;
- while (count == 0) {
- count = is.available();
- }
- byte[] b = new byte[count];
- is.read(b);
- System.out.println(new String(b, "UTF-8"));
- }
-
-
-
-
-
- @Test
- public void testPost() throws IOException {
- StringurlStr= "http://127.0.0.1:8080/study_ssmvc/restful";
- URLurl= newURL(urlStr);
- HttpURLConnectionconn= (HttpURLConnection)url.openConnection();
- conn.setRequestMethod("POST");
- conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
- conn.setDoOutput(true);
- conn.setDoInput(true);
- Stringparam= "id=1&name=2";
- conn.getOutputStream().write(param.getBytes());
- InputStreamis = conn.getInputStream();
- int count = 0;
- while (count == 0) {
- count = is.available();
- }
- byte[] b = new byte[count];
- is.read(b);
- System.out.println(new String(b, "UTF-8"));
- }
-
-
-
-
-
- @Test
- public void testPut() throws IOException {
- StringurlStr= "http://127.0.0.1:8080/study_ssmvc/restful";
- URLurl= newURL(urlStr);
- HttpURLConnectionconn= (HttpURLConnection)url.openConnection();
- conn.setRequestMethod("PUT");
- conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
- conn.setDoOutput(true);
- conn.setDoInput(true);
- Stringparam= "id=1&name=2";
- conn.getOutputStream().write(param.getBytes());
- InputStreamis = conn.getInputStream();
- int count = 0;
- while (count == 0) {
- count = is.available();
- }
- byte[] b = new byte[count];
- is.read(b);
- System.out.println(new String(b, "UTF-8"));
- }
-
-
-
-
-
- @Test
- public void testDel() throws IOException {
- StringurlStr= "http://127.0.0.1:8080/study_ssmvc/restful/1,2,3,4";
- URLurl= newURL(urlStr);
- HttpURLConnectionconn= (HttpURLConnection)url.openConnection();
- conn.setRequestMethod("DELETE");
- conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
- InputStreamis = conn.getInputStream();
- int count = 0;
- while (count == 0) {
- count = is.available();
- }
- byte[] b = new byte[count];
- is.read(b);
- System.out.println(new String(b, "UTF-8"));
- }
- }
实现接口
根据测试类,写好访问接口
- @Controller
- @RequestMapping("")
- public classTestController {
-
-
-
-
-
-
-
-
- @RequestMapping(value = "/restful",method = RequestMethod.GET)
- public void list(HttpServletRequestrequest,HttpServletResponse response,TestVo vo) throws IOException {
- System.out.println("list被访问,参数:" + vo.toString());
- Map<String,Object> map= newHashMap<String, Object>();
- map.put("params",vo);
- map.put("method",RequestMethod.GET);
- response.getWriter().write(JSON.toJSONString(map));
- }
-
-
-
-
-
-
-
-
- @RequestMapping(value = "/restful",method = RequestMethod.POST)
- public voidupdate(HttpServletRequest request, HttpServletResponse response, TestVo vo) throws IOException {
- System.out.println("update被访问,参数:" + vo.toString());
- Map<String,Object> map= newHashMap<String, Object>();
- map.put("params",vo);
- map.put("method",RequestMethod.POST);
- response.getWriter().write(JSON.toJSONString(map));
- }
-
-
-
-
-
-
-
-
- @RequestMapping(value = "/restful",method = RequestMethod.PUT)
- public void add(HttpServletRequest request, HttpServletResponse response, TestVo vo) throws IOException {
- System.out.println("add被访问,参数:" + vo.toString());
- Map<String,Object> map= newHashMap<String, Object>();
- map.put("params",vo);
- map.put("method",RequestMethod.PUT);
- response.getWriter().write(JSON.toJSONString(map));
- }
-
-
-
-
-
-
-
-
- @RequestMapping(value = "/restful/{id}",method = RequestMethod.DELETE)
- public void del(HttpServletRequest request, HttpServletResponse response, @PathVariable("id") String id) throws IOException {
- System.out.println("delete被访问,参数:" + ", id:"+ id);
- Map<String,Object> map= newHashMap<String, Object>();
- map.put("params",id);
- map.put("method",RequestMethod.DELETE);
- response.getWriter().write(JSON.toJSONString(map));
- }
- }
配置及其他业务代码
这里要注意一下
1.html表单form中,method没有put、delete。
2.springMVC并不能直接接收到通过put、delete方式传过来的参数。
我这里的解决方式是
1.添加过滤器HttpPutFormContentFilter,作用是将put的参数获取并重新放入request中,controller便可以直接拿到这些参数,该过滤器支持put、patch,不支持delete。
配置代码
- <filter>
- <filter-name>httpPutFormFilter</filter-name>
- <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>httpPutFormFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
需要注意的是,只有context-type:application/x-www-form-urlencoded的请求才会被过滤。
2.对于delete,我采用url中的动态参数,即”…/restful/1,2,3,4”,链接最后一项1,2,3,4就是参数。springMVC通过”@PathVariable”获得url动态参数。
参数包装类TestVo
- public classTestVo {
-
- private String id;
- private String name;
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public TestVo() {
- super();
- }
- @Override
- public String toString() {
- return "TestVo [id="+ id + ", name="+ name+ "]";
- }
- }
运行结果
运行测试类,测试全部通过
查看返回打印,确实是预期结果,测试通过
总结
这里要注意的是,delete并没有真正实现参数传输的问题,而是用url动态参数的方式实现。如果要实现delete的参数传输,我们可以使用HiddenHttpMethodFilter过滤器。它实际是将post请求转成delete、put请求使用。
其用法是在post传输参数中加一项”_method:xx”等于传输类型,”@RequestMapping(value = "/XXX", method =RequestMethod.DELETE)”方式去映射对应方法。
这种使用方式用法更加广泛、网上教程也更多,就不在累述了。
ajax中的post/get/delete/put请求方法的写法过于繁琐,所以现在封装成如下简便的形式:
/**
* 获取数据ajax-get请求
* @author laixm
*/
$.sanjiGetJSON = function (url,data,callback){
$.ajax({
url:url,
type:"get",
contentType:"application/json",
dataType:"json",
timeout:10000,
data:data,
success:function(data){
callback(data);
}
});
};
/**
* 提交json数据的post请求
* @author laixm
*/
$.postJSON = function(url,data,callback){
$.ajax({
url:url,
type:"post",
contentType:"application/json",
dataType:"json",
data:data,
timeout:60000,
success:function(msg){
callback(msg);
},
error:function(xhr,textstatus,thrown){
}
});
};
/**
* 修改数据的ajax-put请求
* @author laixm
*/
$.putJSON = function(url,data,callback){
$.ajax({
url:url,
type:"put",
contentType:"application/json",
dataType:"json",
data:data,
timeout:20000,
success:function(msg){
callback(msg);
},
error:function(xhr,textstatus,thrown){
}
});
};
/**
* 删除数据的ajax-delete请求
* @author laixm
*/
$.deleteJSON = function(url,data,callback){
$.ajax({
url:url,
type:"delete",
contentType:"application/json",
dataType:"json",
data:data,
success:function(msg){
callback(msg);
},
error:function(xhr,textstatus,thrown){
}
});
};