封装一个类:不依赖任何框架,通过实现抽象方法,用于快速创建一个restful服务;
后端:
package my;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
import js.web.restful.JsSimpleREST;
/*
* 快速创建rest服务
*/
@WebServlet("/AddBook")
public class AddBookServlet extends JsSimpleREST
{
@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;
}
}
前端:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>模拟</title>
<script type="text/javascript" src="js/jquery.min.js"></script>
<style>
.main
{
width: 500px;
margin: 10px auto;
}
.main input,select{
width: 250px;
padding: 4px;
margin: 2px;
}
/* #bgImg {
height: 100%;
width: 100%;
background: url('img/bg-book.jpg') no-repeat;
background-size: cover;
position: absolute;
overflow: hidden;
} */
body{
background-image: url(img/852.jpg);
background-size:cover;
}
</style>
</head>
<body id="bgImg">
<div class="main">
书号: <br><input type='text' class='id' /> <br> <!-- name: 即参数名 -->
书名: <br><input type='text' class='name' /> <br>
手机: <br><input type='text' class='phone' /> <br>
出版社: <br><input type='text' class='pub' /> <br><br>
<button οnclick="submit()">提交</button>
</div>
</body>
<script>
function submit()
{
var req = {};
req.id = $(".main .id").val().trim();
req.name = $(".main .name").val().trim();
req.phone = $(".main .phone").val().trim();
req.pub = $(".main .pub").val().trim();
/*在发送请求时,把请求转成json对象*/
var jsonStr = JSON.stringify(req);
console.log(jsonStr);
$.ajax({
type:"POST", /*请求类型-POST/GET*/
url:"AddBook", /*服务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);
}
});
}
</script>
</html>
JsSimpleRest:
package js.web.restful;
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 js.web.JsWebException;
/**
* 不依赖任何框架,快速地创建一个RESTful服务
* @author JiuSen
*/
public abstract class JsSimpleREST 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(JsWebException 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("** 出错2: " + 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();
}
/////////////////// 工具方法 //////////////////
// 从 Stream 中读取数据直到读完
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);
}
}
JsWebException:
package js.web;
/**
* 通用的异常类,带 error和reason两个属性
* @author JiuSen
* @since 20190601
*
*/
public class JsWebException extends Exception
{
public int error;
public String reason;
public JsWebException()
{
}
public JsWebException(int error, String reason)
{
this.error = error;
this.reason = reason;
}
@Override
public String getMessage()
{
return reason + "(" + error + ")";
}
}