学号:
姓名:
手机:
性别:
RESTful,一种通用的前后台交互方式
RESTful一般是指这种格式:
(1)使用HTTP POST(或GET)进行数据交互
(2)请求数据和应答数据均为JSON格式(或XML)
RESTful的前端实现
前端:在发送请求时,把请求转成JSON字符串
$.ajax({
type:"POST", /*请求类型-POST/GET*/
url:"AddStudent?mode=admin&token=12930289", /*服务URI,用相对地址*/
data:jsonStr, /*附加请求参数*/
dataType:"json", /*期望服务器返回的数据类型*/
success: function(resp) /*已经将服务器返回的数据转成JS 对象*/
{
if(resp.error==0)
alert("提交成功");
else
alert("出错:"+resp.reason);
},
error: function(jqXHR, textstatus, errorThrown)
{
alert("错误:" +jqXHR.status);
}
});
后端:手工读取请求数据,转成JSONObject,然后再做处理
//读取请求数据,转化为字符串
String reqText = readAsText(request.getInputStream(), "utf-8");
//转化为json
JSONObject jreq = new JSONObject(reqText);
一般来说,使用RESTful接口时,所有的请求参数放在JSON中即可。但有的时候,还有少许参数放在URL里面。
演示代码:
前端:
AJAX POST
学号:
姓名:
手机:
性别:
后端核心代码:
package my;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
/**
* Servlet implementation class AddStudent
*/
@WebServlet("/AddStudent")
public class AddStudent extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public AddStudent() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String reqText = readAsText(request.getInputStream(), "UTF-8");
System.out.println(reqText);
//转化为JSON
JSONObject jreq = new JSONObject(reqText);
//URL末尾,由问号引导的字符串(在restful中也有部分参数在URL中
//例如:url:"AddStudent?mode=admin&token=12930289", /*服务URI,用相对地址*/
String query = request.getQueryString();
System.out.println(query);
HashMapppp = parseQuery(query);
System.out.println(ppp);
int id = jreq.getInt("id");
String name = jreq.getString("name");
String phone = jreq.getString("phone");
boolean sex = "male".equals(jreq.getString("sex"));
// 添加到数据库
Student s = new Student(id, name, sex, phone);
DemoDB.i.add( s );
// 返回应答数据
JSONObject jresp = new JSONObject();
jresp.put("error", 0); // 错误码,0表示成功
jresp.put("reason", "OK"); // 错误原因描述, 如果没有错误则提示OK
response.setCharacterEncoding("UTF-8");
response.setContentType("text/plain");
Writer writer = response.getWriter();
writer.write( jresp.toString(2));
writer.close();
}
//从Stream中读取数据直到读取完毕
public String readAsText(InputStream StreamIn, String charset) throws IOException
{
ByteArrayOutputStream cache = new ByteArrayOutputStream(1024*16);
byte[] data = new byte[1024];
while(true)
{
int n =StreamIn.read(data);
if(n<0)break;
if(n==0)continue;
//缓存起来
cache.write(data, 0 ,n);
if(cache.size()>1024*512)
break;
}
return cache.toString(charset);
}
//转为HashMap
public HashMapparseQuery(String query)
{
HashMapparms = new HashMap();
String[] ppp = query.split("&");
for(String p : ppp)
{
String[] kv = p.split("=");
String key = kv[0];
String value = "";
if(kv.length>1)value = kv[1];
parms.put(key, value);
}
return parms;
}
}
-首先自定义设计一个抽象类AfSimpleREST继承与HttpServlet
-里面定义一个抽象方法,用于子类对前端传回的JSON格式字符串的数据进行分析
package my;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
import af.AfWebException;
public abstract class AfSimpleREST extends HttpServlet
{
protected boolean enableErrorLog = false; // 是否打印异常输出
protected boolean niceJSONFormat = true; // 输出的JSON是否综进 (缩进影响运行效率)
protected int MAX_REQUEST_SIZE = 1024 * 512; // 允许上传的JSON最大长度
protected String charset = "UTF-8";
// 子类须重写这个方法,进行业务处理
// 处理返回后,可以返回 JSONObject, JSONArray, 或int long String 等基本类型
protected abstract Object execute(HttpServletRequest request,
HttpServletResponse response,
JSONObject jreq)throws Exception;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
// 无论是 GET/POST, 均统一处理
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String requestURI = request.getRequestURI();
// 处理请求数据
JSONObject jresp = new JSONObject();
try{
// 读取请求数据, 转成字符串, 转成 JSON
String reqText = readAsText(request.getInputStream(), charset, MAX_REQUEST_SIZE);
JSONObject jreq = null;
if(reqText.length()>0) jreq = new JSONObject(reqText);
// 子类应重写 execute() 方法
Object data = execute(request, response, jreq);
jresp.put("error", 0); // 错误码,0表示成功
jresp.put("reason", "OK"); // 错误原因描述, 如果没有错误则提示OK
if(data != null)
jresp.put("data", data); //
}
catch(AfWebException e)
{
String reason = e.getMessage();
System.out.println("** 出错: " + requestURI + ", 原因: " + reason);
if(enableErrorLog) e.printStackTrace();
// 应签数据
jresp.put("error", e.error); // 错误码,0表示成功
jresp.put("reason", reason); // 错误原因描述, 如果没有错误则提示OK
}
catch(Exception e)
{
String reason = e.getMessage();
if(reason == null) reason = e.getClass().getName();
System.out.println("** 出错: " + requestURI + ", 原因: " + reason);
if(enableErrorLog) e.printStackTrace();
// 应签数据
jresp.put("error", -1); // 错误码,0表示成功
jresp.put("reason", e.getMessage()); // 错误原因描述, 如果没有错误则提示OK
}
// 是否按可读风格生成JSON ( 缩进格式 or 紧凑格式 )
String jsonstr = niceJSONFormat ? jresp.toString(2) : jresp.toString();
// 发送应答给客户端
response.setCharacterEncoding(charset);
response.setContentType("text/plain");
//response.setHeader("Connection", "close");
Writer writer = response.getWriter();
writer.write( jsonstr );
writer.close();
}
public static String readAsText(InputStream streamIn, String charset, int maxSize)
throws IOException
{
ByteArrayOutputStream cache = new ByteArrayOutputStream(1024*16);
byte[] data = new byte[1024];
int numOfWait = 0;
while (true)
{
int n = streamIn.read(data); // n: 实际读取的字节数
if(n < 0) break; // 连接已经断开
if(n == 0)
{
if( numOfWait ++ >= 3) break; // 此种情况不得连续3次
try{ Thread.sleep(5);}catch(Exception e){}
continue;// 数据未完 //
}
numOfWait = 0;
// 缓存起来
cache.write(data, 0, n);
if(cache.size() > maxSize) // 上限, 最多读取512K
break;
}
return cache.toString(charset);
}
}
子类继承:
package my;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
@WebServlet("/AddBook")
public class AddBook extends AfSimpleREST
{
@Override
protected Object execute(HttpServletRequest request,
HttpServletResponse response,
JSONObject jreq) throws Exception
{
String id = jreq.getString("id");
String name = jreq.getString("name");
String phone = jreq.getString("phone");
String pub = jreq.getString("pub");
System.out.println("编号:"+id+"作者:"+name+"手机号:"+phone+"出版社:"+pub);
return null;
}
}
前端代码:
AJAX POST
书号:
书名:
手机:
出版社: