目录
一、RESTful调用
二、添加RESTful支持
前端代码:
后端核心代码:
三、列表查询与支持
前端:
后端代码:
四、添加记录
前端添加记录代码:
后端实现添加记录代码:
一、RESTful调用
-创建Web Project
-添加JS/CSS
jquery.js
afquery.js //封装的AJAX操作/JS工具
common.css公共CSS样式
-修改TOMCAT部署,server.xml
前端使用HBuilder进行编辑开发
afRest
// 默认错误处理
Af.restErrHandler = function(error, reason)
{
alert(reason);
};
// serviceUri 服务名, req 请求参象 , okHandler 应答数据处理函数
// errorHandler 处理处理器, 可以为null
Af.rest = function (serviceUri, req, okHandler, errHandler)
{
jQuery.ajax({
url: serviceUri,
method: "POST",
processData: false,
data: JSON.stringify(req),
dataType: 'json',
success: function(ans){
if(ans.error != 0)
{
// 接下来,先用第4个参数(用户自己处理器处理)
if(errHandler != null)
errHandler( ans.error, ans.reason);
else
// 如果未提供第4个参数,则进入默认处理(alert)
Af.restErrHandler (ans.error, ans.reason); // 默认错误处理
}
else
{
okHandler(ans.data);
}
},
error: function( jqXHR, textStatus, errorThrown){
if(errHandler != null)
errHandler( -1, "网络错误: " + textStatus);
else
console.log("网络错误: " + textStatus);
}
});
}
二、添加RESTful支持
1、正常情况:
2、异常情况
前端代码:
<html>
<head>
<meta charset="utf-8">
<title>RESTful调用演示</title>
<script type="text/jscript" src="JS/jquery-3.3.1.min.js"></script>
<script type="text/jscript" src="JS/afquery.js"></script>
</head>
<body>
<div class="container">
<button onclick="M.test()">测试</button>
</div>
</body>
<script>
var M={};
M.test = function()
{
var req = {};
req.id = -2019001;
//
Af.rest("Test01", req, function(data){
console.log( data );
},
function(error, reason)
{
alert( reason );
}
)
}
</script>
</html>
后端核心代码:
后端通过继承设计的AfSimpleREST 类,实现execute方法,来快速创建RESTful支持
package my;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
@WebServlet("/Test01")
public class Test01 extends AfSimpleREST
{
@Override
protected Object execute(HttpServletRequest request, HttpServletResponse response, JSONObject jreq) throws Exception
{
int id = jreq.optInt("id");
if(id<0)
throw new Exception("id必须为正值!");
//处理
//应答数据
JSONObject jresp = new JSONObject();
jresp.put("id", id);
jresp.put("name", "久森");
jresp.put("sex", true);
jresp.put("phone", "15137742640");
return jresp;
}
}
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);
}
}
三、列表查询与支持
熟悉自己设计的AfSimpleREST的使用以及快速创建RESTful服务
前端:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>列表查询与显示</title>
<link rel="stylesheet" href="css/main.css"/>
<script type="text/javascript" src="JS/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="JS/afquery.js"></script>
</head>
<body>
<div class="container">
<div style="background-color: aquamarine; padding: 4px;">
<a href="test01.html">首页</a> >> 列表
</div>
<div class="row">
<button onclick="M.listStudent()">测试</button>
</div>
<div class="row student-list">
<table class="table">
<thead>
<th> 学号 </th>
<th> 姓名</th>
<th> 性别 </th>
<th> 手机号 </th>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</body>
<script>
var M={};
M.test = function()
{
var req = {};
req.id = 2019001;
//带4个参数: uri, req, okHandler, errHandler
Af.rest("Test", req, function(data){
console.log( data );
},
function(error, reason)
{
alert( reason );
}
)
}
/*列表查询*/
M.listStudent = function()
{
var req = {};
Af.rest("ListStudent", req, function(data){
M.addStudent(data);
})
}
/*添加学生记录到表格*/
M.addStudent = function(data)
{
var target = $(".student-list tbody");
target.html(""); //清空
for(var i=0; i<data.length; i++)
{
var it = data[i];
var str = "<tr>"
+ "<td>" + it.id + "</td>"
+ "<td>" + it.name + "</td>"
+ "<td>" + ( it.sex ? '男' : '女') + "</td>"
+ "<td>" + it.cellphone + "</td>"
+ "</tr>";
target.append ( str );
}
}
//初始加载
M.listStudent();
</script>
</html>
后端代码:
package my;
import java.util.List;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONObject;
@WebServlet("/ListStudent")
public class ListStudent extends AfSimpleREST
{
@Override
protected Object execute(HttpServletRequest request, HttpServletResponse response, JSONObject jreq) throws Exception
{
int id = jreq.optInt("id");
if(id<0)
throw new Exception("id必须为正值!");
//处理
//直接把list转化为json,要求list内的元素是pojo类型
List<Student> db = DemoDB.i.list();
JSONArray jresp = new JSONArray(db);
return jresp;
}
}
四、添加记录
前端添加记录代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>添加记录</title>
<link rel="stylesheet" href="css/main.css"/>
<script type="text/javascript" src="JS/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="JS/afquery.js"></script>
<style>
.form .line{
margin: 10px 0;
}
.form label{
display: inline-block;
min-width: 80px;
text-align: right;
}
.form input,select{
width: 200px;
height: 24px;
}
</style>
</head>
<body>
<div class="container">
<div style="background-color: #F8F8FF; padding: 4px;">
<a href="test01.html">首页</a> >> 添加记录
</div>
<div class="row" style="margin-bottom: 30px;">
<button onclick="M.save()">保存</button>
</div>
<div class="row form">
<div class="line">
<label>学号</label>
<input type="text" class="id" />
</div>
<div class="line">
<label>姓名</label>
<input type="text" class="name" />
</div>
<div class="line">
<label>性别</label>
<select class="sex">
<option value="male">男</option>
<option value="female">女</option>
</select>
</div>
<div class='line'>
<label> 手机号 </label>
<input type='text' class='phone' >
</div>
</div>
</div>
</body>
<script>
var M = {};
M.save = function()
{
//取得输入的值
var req = {};
req.id = $(".form .id").val();
req.name = $(".form .name").val();
req.sex = $(".form .sex").val();
req.phone = $(".form .phone").val();
//必要的转换
req.id = Number(req.id);
req.sex = (req.sex == "male"); //sex转化为Boolean
//调用后台接口
Af.rest("AddaStudent", req, function(data){
alert("成功!");
location.href = "test01.html"; //跳转到首页
},
function(error, reason){
alert(reason);
})
}
</script>
</html>
后端实现添加记录代码:
package my;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
@WebServlet("/AddaStudent")
public class StudentAddSevice extends AfSimpleREST
{
@Override
protected Object execute(HttpServletRequest request,
HttpServletResponse response,
JSONObject jreq) throws Exception
{
// 取得请求参数
int id = jreq.getInt("id");
String name = jreq.optString("name", "");
boolean sex = jreq.optBoolean("sex", true);
String phone = jreq.optString("phone", "");
// 参数检查
if(id <= 0)
throw new Exception("ID必须为正值!");
if(name.length() == 0)
throw new Exception("姓名不得为空!");
// 保存数据
Student stu = new Student(id, name, sex, phone);
DemoDB.i.add(stu);
// 注意:返回 null是正常情形,不表示错误!
// 返回null 仅仅表示客户端浏览器不需要返回什么特别的数据 。
// 只有 throw了Exception ,才表示在处理过程中发生了错误。
return null;
}
}