С выходом новой версии Intersystems Caché появилась возможность использовать технологию REST и строить приложения, с помощью различных Javascript UI библиотек, в то время как сервер Caché выступает в роли сервера данных. В данной статье будет рассмотрен очень простой пример доступа к хранимым классам Caché с помощью технологии REST.
Если упростить, то схема такого приложения выглядит следующим образом:
Как видно из схемы, обмен данными производится с помощью REST брокера, используя формат JSON. Таким образом, Caché используется только для получения данных в формате json, которые обрабатываются любой Javascript UI библиотекой. Это позволяет полностью разделить серверную бизнес-логику и пользовательский интерфейс. При желании интерфейс пользователя можно расположить в статических html страницах, что повысит производительность приложения. Также данный подход дает большое преимущество при проектировании интерфейсов, разработчику интерфейса нет необходимости знать Caché, ему достаточно JSON данных, которые приходят с сервера.
Перейдем к простейшей реализации данного подхода. Для этого необходимо создать простейший REST брокер. Создаем новый класс и наследуем его от %CSP.REST:
Class User.DataGateway Extends %CSP.REST
{
XData UrlMap
{
<Routes>
<Route Url="/get" Method="GET" Call="GetData"/>
</Routes>
}
ClassMethod GetData() As %Status
{
w "hello"
quit $$$OK
}
}
Для того чтобы брокер заработал, необходимо выполнить настройку веб приложения. В портале управления необходимо зайти в «Администрирование системы > Безопасность > Приложения > Веб приложения», после чего изменить приложение (в данном примере это «/csp/user»). В поле класс-обработчик указываем только что созданный класс User.DataGateway.
Если все настроено правильно, то перейдя по адресу http://localhost:57772/csp/user/get мы должны увидеть текст «hello». Теперь модифицируем метод таким образом, чтобы можно было обратиться к любому статическому методу класса. Для этого воспользуемся функцией $CLASSMETHOD.
ClassMethod GetData() As %Status
{
// Необходимо для примера, чтобы работали кросс-доменные запросы
d %response.SetHeader("Access-Control-Allow-Origin", "*")
// Получаем имя класса и имя метода
s class = %request.Get("class", "")
if (class '= "") {
set method = %request.Get("method", "")
if (method '= "") {
try {
// Выполняем метод класса
d $CLASSMETHOD(class, method)
} catch err {
w err.AsSystemError()
}
}
}
quit $$$OK
}
Чтобы протестировать работу REST брокера, создадим простой класс описывающий организацию.
Class User.GridDemo Extends %Persistent
{
Property Code As %String;
Property NameFull As %String;
Property NameShort As %String;
ClassMethod InitDemoData()
{
s o = ##class(User.GridDemo).%New()
s o.Code = "001"
s o.NameFull = "Organization One"
s o.NameShort = "Org 1"
d o.%Save()
s o = ##class(User.GridDemo).%New()
s o.Code = "002"
s o.NameFull = "Organization Two"
s o.NameShort = "Org 2"
d o.%Save()
w "Done"
}
}
Перейдя по ссылке http://localhost:57772/csp/user/get?class=GridDemo&method=InitDemoData, увидим «Done». Таким образом, мы вызвали метод InitDemoData класса GridDemo. Теперь добавим метод, который будет формировать json для грида(в данном случае рассмотрен формат, который использует dhtmlx grid).
ClassMethod GetGridData()
{
// Выбираем все данные
s sql = ##class(%SQL.Statement).%New()
s st = sql.%Prepare("select * from GridDemo")
if (st '= 1) {
w "%Prepare failed",$System.Status.DisplayError(st)
q
}
s rset = sql.%Execute()
if (rset.%SQLCODE '= 0) {
w "query error: ", rset.%SQLCODE, " ", rset.%Message
q
}
// Строим json
s json = "{ ""rows"": [ "
while rset.%Next() {
s json = json _ "{ ""id"": " _ rset.Id _ ", ""data"": [ "
s json = json _ """" _ rset.Code _ """,""" _ rset.NameFull _ """"
s json = json _ " ] },"
}
// Убираем запятую в конце, если она есть
s len = $l(json)
if ($e(json, len, len) = ",") s json = $E(json, 1, len - 1)
s json = json _ " ] }"
w json
}
После чего, по адресу localhost:57772/csp/user/get?class=GridDemo&method=GetGridData должны отображаться данные в формате JSON.
{ "rows": [ { "id": 1, "data": [ "001","Organization One" ] },{ "id": 2, "data": [ "002","Organization Two" ] } ] }
Стоит обратить внимание, что в данной статье не рассматривается вопрос безопасности, а также корректного формирования JSON. Данные методы приведены как иллюстрация подхода к проектированию приложения и построения интерфейсов пользователя. Если кратко, то необходимо ограничить доступ к методам классов, чтобы можно было вызвать только методы, которые ориентированы на обработку данных, а также проверять права пользователя в каждом методе отдельно.
Получив JSON с данными, остается только написать страничку с пользовательским интерфейсом. Для этого воспользуемся библиотекой dhtmlx (или Sencha Ext JS, JQuery UI и т.п., просто изменив формат исходящего JSON).
<!DOCTYPE html>
<html>
<head>
<title>Grid Demo</title>
<link href="js/dhtmlxw/dhtmlx.css" rel="stylesheet">
<script src="js/dhtmlxw/dhtmlx.js"></script>
<script src="js/jquery-1.10.2.min.js"></script>
<script language='javascript'>
var g = null;
var l = null;
$(document).ready(function (){
l = new dhtmlXLayoutObject(document.body, '1C');
g = l.cells("a").attachGrid();
l.cells("a").setText("Grid Demo");
g.setImagePath("/js/dhtmlxw/imgs/");
g.setHeader("Code,Full Name,Short name");
g.setColumnIds("Code,NameFull,NameShort");
g.attachHeader("#text_filter,#text_filter,#text_filter,#text_filter");
g.setInitWidths("120,*,200");
g.setColAlign("center,left,left,left");
g.setColTypes("ro,ro,ro,ro");
g.setColSorting('str,str,str,str');
g.init();
$.getJSON( "http://localhost:57772/csp/user/get?class=GridDemo&method=GetGridData&table=GridDemo", onDataLoaded);
});
function onDataLoaded(data) {
g.clearAll();
g.parse(data,'json');
}
</script>
</head>
<body style="height:600px">
</body>
</html>
Для запросов к серверу в данном примере используется метод JQuery — getJSON, после чего в колбеке onDataLoaded, данные передаются в грид. Если все сделано правильно, должен появится грид с данными.
Заключение
В статье был рассмотрен один из методов взаимодействия с сервером Caché посредством технологии REST. Создан универсальный механизм доступа к любым статическим методам. Используя его, формируется JSON с данными, который обрабатывается на клиенте с помощью UI библиотеки.
В данной статье не было рассмотрено:
- Безопасность при обращении к классам, используя REST(права пользователей, именование веб методов).
- Формирование корректного JSON(zconvert, %ZEN.Auxiliary.jsonSQLProvider и т. п.).
- Формирование расширенного пользовательского интерфейса (layout, tabs, treeview и т. п.).
Пример, используемый в статье, можно скачать тут
Автор: dsoul