После добавления приведённой конфигурации можно использовать следующую ссылку для доступа к примеру объекта.
http://[your_server_host]:[your_server_port]/[your_servlet_context]/yieldMyName?name=John
В предыдущей главе было объяснено правило маршрутизации этого фреймворка, которое используется для поиска файла JavaScript, обрабатывающего запрос. Однако размещение всей логики в одном файле не является наилучшей практикой, поэтому в большинстве случаев нам необходимо импортировать другие файлы в один файл в реальных сценариях использования.
Nashorn предоставляет метод load(файл полный путь) для этой цели, но мы не рекомендуем его использовать. Вместо этого мы предлагаем использовать метод import(файл относительный путь), предоставляемый фреймворком.
Вот причины, по которым следует использовать метод imports():
Метод import импортирует файл один раз в рамках области видимости (global.js выполняется в глобальной области видимости, каждый запрос выполняется в отдельной области). Поэтому для некоторых общих методов использование import более эффективно и не вызовет проблем из-за повторного импорта.
В методе import используется относительный путь, что обеспечивает лучшую переносимость и не приведёт к ошибкам импорта при изменении пути. Обратите внимание, что в случае импорта файла в область контроллера корнем относительного пути является значение свойства fileHome объекта $webapp в global.js (по умолчанию это classpath), а в глобальной области корнем относительного пути всегда является classpath.
Используя метод import, вы можете заменить символ / на символ ., что более привычно для программистов, знакомых с Java. Поэтому обратите внимание, что вы не должны использовать символ . в пути к файлу, и что расширение файла не должно быть включено при импорте. Вы можете настроить расширение файла через свойство fileExtension объекта $webapp в global.js в области контроллера, а расширение всех импортируемых файлов в глобальной области должно быть .js.
Как и при написании собственных классов сервлетов, функции/методы контроллера получают два параметра: первый — запрос, второй — ответ. Эти два параметра представляют собой объекты JavaScript, инкапсулирующие HttpServletRequest и HttpServletResponse. Теоретически, вы должны получить данные, отправленные пользователем из запроса, и записать результат в ответ. Однако в разделе «Быстрое начало» вы видите только один параметр запроса. Это будет объяснено позже.
Пример метода контроллера:
function dosth(req, res){
var someParamVal = req.parameters["name-defined-in-form-input"]; // Если ваш параметр достаточно прост, вы даже можете использовать только ., например, если имя вашего параметра — "simpleName", вы можете использовать: req.parameters.simpleName
var serviceResult = someServiceObject.doService(someParamVal);
res.write(serviceResult);
}
Если вы предпочитаете использовать методы обратного вызова, вы можете написать:
function dosth(req, res){
var someParamVal = req.parameters["name-defined-in-form-input"];
someServiceObject.doService(someParamVal, function (serviceCallbackResult) {
res.write(serviceCallbackResult);
});
}
Полный список свойств и методов объектов запроса и ответа:
Объект запроса (названный req)
req.oriRequest: исходный объект HttpServletRequest Java.
req.session: объект HttpSession Java, полученный через исходный request.getSession().
req.authType: строка, полученная через исходный request.getAuthType().
req.method: строка, полученная через оригинальный request.getMethod().
req.contentLength: длинное число, полученное через исходный request.getContentLength(), представляющее количество байтов содержимого запроса.
req.contentType: строковый объект, полученный через оригинальный request.getContentType(), представляющий тип содержимого запроса.
req.queryString: строковый объект, полученный через оригинальный request.getQueryString(), представляющий содержимое после ? в адресе доступа.
req.protocol: строковый объект, полученный через оригинальный request.getProtocol(), представляющий протокол текущего доступа.
req.schema: строковый объект, полученный через оригинальный request.getSchema(), представляющий схему текущего протокола доступа, которая может быть «http» или «https».
req.serverName: строковый объект, представляющий имя сервера, полученный через оригинальный request.getServerName().
req.serverPort: числовой объект, представляющий порт сервера, полученный через оригинальный request.getServerPort().
req.contextPath: контекст, строковый объект, полученный через оригинальный request.getContextPath().
req.requestURI: адрес ресурса запроса без протокола, адреса, порта, параметров доступа и т. д., включая текущий контекстный адрес. Строковый объект, полученный через оригинальный request's getRequestURI().
req.requestUri: псевдоним req.requestURI.
req.uri: псевдоним req.requestURI.
req.ctxUri: адрес запроса ресурса без контекстного адреса.
req.servletPath: текущий путь сервлета, строковый объект, полученный через оригинальный request's getServletPaht().
req.requestURL: адрес запроса, включающий всю информацию до ?. Строковый объект, полученный через оригинальный request's getRequestURL() и преобразованный в строку с помощью toString().
req.requestUrl: псевдоним req.requestURL.
req.url: псевдоним req.requestURL.
req.headers: заголовки запроса, объект JSON, созданный с использованием оригинального request's getHeader(name). Например, req.headers["user-agent"] может получить данные заголовка user-agen.
req.header: псевдоним req.headers.
req.parameterValues: параметры запроса, содержащие часть строки запроса после ? и часть тела запроса, когда content-type равен application/x-www-form-urlencoded или multipart/form-data. Этот параметр всегда возвращает массив (даже если массив содержит только один элемент). Если это запрос multipart/form-data, который включает загрузку файла, то параметр файла будет проанализирован как следующий объект JSON:
{
"filename": "somePicture.jpg", // имя файла
"contentType": "image/jpg", // тип содержимого
"content": "xxxxxx" // строка, полученная из содержимого multipart, вы можете использовать метод getBytes() для получения массива байтов и записи его в файл.
}
req.parameterValue: псевдоним req.parameterValues.
req.paramVals: псевдоним req.parameterValues.
req.parameters: аналогично req.parameterValues, но возвращает только одно значение, возвращая первое, если есть несколько одноимённых параметров запроса. req.parameter, req.parameters
— псевдоним.
req.params, req.parameters
— псевдоним.
req.param, req.parameters
— псевдоним.
req.pathValues — путь параметра, подробнее см. в разделе «Путь параметра».
req.pathValue, req.pathValues
— псевдоним.
req.setAttribute(name, val) — упаковка метода setAttribute(name, value) исходного запроса.
req.setAttr(name, val), req.setAttribute(name, val)
— псевдоним.
req.getAttribute(name, defaultValue) — упаковка исходного метода getAttribute(name), который отличается добавлением значения по умолчанию: если исходный метод возвращает значение null, этот метод вернёт указанное значение по умолчанию.
req.getAttr(name, defaultValue), req.getAttribute(name, defaultValue)
— псевдоним.
req.removeAttribute(name) — упаковка исходного метода removeAttribute(name).
req.removeAttr(name), req.removeAttribute(name)
— псевдоним.
req.rmAttr(name), req.removeAttribute(name)
— псевдоним.
req.readRequestBody() — возвращает тело запроса, например, если тип содержимого — application/x-www-form-urlencoded, то этот метод возвращает null.
req.data — если тип содержимого запроса — application/json, то параметр является объектом JSON, преобразованным из req.readRequestBody с помощью JSON.parse().
res.headers
— псевдоним.res.addHeader(name, value)
— псевдоним.В этом разделе описывается другой способ реагирования, при котором вам не нужно использовать объект response, а достаточно вернуть значение, чтобы запрос получил правильный ответ.
По сути, если метод возвращает структурированный JSON-объект, соответствующий формату, фреймворк автоматически обрабатывает ответ. В процессе кодирования нам не нужно знать конкретную структуру JSON-объекта, достаточно использовать глобальный объект $renderer для обработки наших данных.
Методы объекта $renderer следующие:
Вот пример использования объекта $renderer, который демонстрирует стиль кода, используемый при явном написании этого объекта:
function dosth(req){
var param = req.parameters;
var serviceResult = someServiceObject.doService(param);
return $renderer.json(serviceResult);
}
Фактически, в большинстве случаев нет необходимости явно писать объект $renderer; вы можете просто вернуть свой бизнес-объект, и фреймворк автоматически адаптирует эти объекты:
function dosth(req){
var param = req.parameters;
var serviceResult = someServiceObject.doService(param);
return serviceResult; // Возвращаемое значение представляет собой объект JSON
}
Вы также можете возвращать данные, подобные следующей структуре:
return "<!DOCTYPE html><html>....</html>"; // Ответ будет иметь тип содержимого "text/html".
return "<?xml version="1.0" encoding="UTF-8"?><tag>...</tag>"; // Ответ будет иметь тип содержимого "text/xml".
return "redirect:/url"; // Будет перенаправлен на /url
return "forward:/url"; // Запрос будет переадресован на /url
return "some text"; // Ответ будет типа "text/plain"
``` Это очень распространённый паттерн проектирования, основной принцип которого заключается в разделении на слои: логический слой (Model), управляющий слой (Controller) и слой представления (View).
Разделение кода на слои имеет следующие преимущества: развязка, что делает код более читаемым и удобным в обслуживании. Разработчики веб-сайтов любят использовать MVC, особенно разработчики Java Web, поэтому существует множество шаблонов, предоставляемых языком Java. Благодаря этому использование MVC в нашем фреймворке становится очень простым.
KJServlet поддерживает JSP, Freemarker и Velocity в качестве шаблонов для слоя View.
Как было видно в предыдущей главе, вам нужно использовать метод $renderer.view для использования MVC. Пример:
```javascript
function dosth(req){
var param = req.parameters;
var serviceResult = someServiceObject.doService(param);
return $renderer.view("/WEB-INF/pages/view.jsp", serviceResult); // serviceResult — это объект JSON
}
По умолчанию фреймворк использует JSP в качестве механизма шаблонов. Вы можете настроить свой собственный механизм шаблонов в объекте $webapp в файле global.js. Пример:
$webapp = {
controller : {
fileHome : "classpath:/org/keijack/kjservlet/demo/controller", // путь к вашему методу контроллера, по умолчанию "classpath:"
fileSuffix : ".js", // суффикс вашего файла контроллера, по умолчанию ".js"
suffix : "", // суффикс запроса вашего контроллера, по умолчанию ""
},
resources : [ "*.html", "/images/*" ],
view : {
resolver : "jsp", // тип механизма шаблонов, может быть "jsp", "freemarker" или "velocity"
prefix : "/WEB-INF/pages/", // префикс пути к файлу представления.
suffix : ".jsp", // суффикс пути к файлу представления.
},
}
Если вы настроили указанные выше параметры в global.js, ваш метод контроллера будет упрощён до:
function dosth(req){
var param = req.parameters;
var serviceResult = someServiceObject.doService(param);
return $renderer.view("view", serviceResult); // файл шаблона будет /WEB-INF/pages/view.jsp
}
Примечание! Если вы используете freemarker или velocity в качестве механизмов шаблонов, вам необходимо самостоятельно добавить зависимости этих механизмов.
В $renderer.view(templateFileLocation, data, header) второй параметр данных должен быть объектом JSON. Фреймворк преобразует этот объект JSON в объект Java Map, который затем передаётся в ваш механизм шаблонов. Поэтому в вашем механизме шаблонов вы можете использовать объект Map.
Предположим, что ваш объект данных выглядит следующим образом:
function dosth(req){
var data = {"userName": "Jhon",
"sex": "male",
"age": 28,
"department": { "name": "HR",
"phone": "+01xxxxxx",
},
"subordinates": ["Mike", "Lily"]
};
return $renderer.view("view", data);
}
В вашем файле шаблона (например, с использованием freemarker) вы можете сделать следующее:
<!DOCTYPE html>
<html>
<head>
<title>Personal Details</title>
</head>
<body>
<h1>Personal Details of ${userName}</h1>
<p>sex: ${sex}</p>
<p>age: ${age}</p>
<p>department: ${department.name}</p>
<p>subordinates: <#list subordinates as sbn>${sbn}, </#list>
</body>
</html>
Вы также можете использовать методы объектов в данных, а затем использовать эти методы в механизме шаблонов с помощью call или apply.
Примечание! Метод call может принимать не более 10 параметров. Метод apply всегда принимает один объект данных в качестве параметра.
Предполагая, что ваш объект данных следующий:
var data = {"userName": "Jhon",
"sex": "male",
"isAdult": function(){
// обратите внимание: в этом методе не следует использовать this, потому что в конечном итоге эти методы будут инкапсулированы как Java-объект JSFunctionWrapper, поэтому this не указывает на текущий объект JSON.
return data.age >= 18;
},
"age": 28,
"department": { "name": "HR",
"phone": "+01xxxxxx",
},
"subordinates": ["Mike", "Lily"]
};
Тогда в вашем файле шаблона вы можете вызвать этот метод следующим образом:
<!DOCTYPE html>
<html>
<head>
<title>Personal Details</title>
</head>
<body>
<h1>Personal Details of ${userName}</h1>
<p>sex: ${sex}</p>
<p>is adult: ${isAult.call()}</p>
<p>age: ${age}</p>
<p>department: ${department.name}</p>
<p>subordinates: <#list subordinates as sbn>${sbn}, </#list>
</body>
</html>
Если вы считаете, что все три механизма шаблонов не подходят, вы даже можете создать свой собственный механизм шаблонов:
$webapp = {
controller : {
fileHome : "classpath:/org/keijack/kjservlet/demo/controller",
fileSuffix : ".js",
suffix : "",
},
resources : [ "*.html", "/images/*" ],
view : {
resolver : function(viewFileLocation, data, headers){
// viewFileLocation уже содержит префикс и суффикс из конфигурации выше.
// генерирует окончательную строку HTML, которая визуализируется слоем View
var html = ...;
// наконец, через $renderer
... **Возврат структурированного объекта**
return $renderer.html(html, headers);
},
prefix: "/WEB-INF/pages/",
suffix: ".jsp",
}
Маркировка и аспектно-ориентированное программирование (AOP)
В JavaScript нет встроенной системы аннотаций, как в Java. Кроме того, способ создания объектов в JavaScript сильно отличается от Java, и вы можете создавать объекты без использования ключевого слова new. Поэтому в JavaScript сложно реализовать аспектно-ориентированное программирование, как это делается в Java. Однако с помощью некоторых уловок мы всё же смогли реализовать некоторые аспекты.
Если вы знакомы с JavaScript, вы наверняка слышали об использовании strict mode. Если вы хотите, чтобы метод выполнялся в строгом режиме, вам нужно добавить строку «use strict» в начало вашего метода. Наша идея AOP также возникла из этого. Пожалуйста, обратитесь к следующему коду:
function dosth(req){
"use strict";
"@post"; // KJSeverlet встроенная аннотация, этот метод принимает только запросы POST.
"@myOwnAnno"; // Пользовательская аннотация.
// Ваш логический код
...
"@Anno2"; // Если ваша аннотация находится в теле логики, она не будет прочитана фреймворком.
...
}
В этом примере вы получите аннотации ["@post", "@myOwnAnno"].
Обратите внимание! Аннотации действуют только в методах контроллера!
Мы уже знаем, как делать аннотации, но как их использовать? Вернёмся к объекту $webapp в файле global.js:
$webapp = {
controller : {
fileHome : "classpath:/org/keijack/kjservlet/demo/controller",
fileSuffix : ".js",
suffix : "",
},
resources : [ "*.html", "/images/*" ],
view : {
resolver : "jsp",
prefix : "/WEB-INF/pages/",
suffix : ".jsp",
},
interceptors : {
intercept : "@myOwnAnno", // Если вы хотите применить один и тот же аспект к нескольким стандартным методам, вы можете передать массив в этот параметр
// intercept: ["@myOwnAnno1", "@MyOwnAnno2"],
before : function(req, res, ctx) {
// Код, который выполняется перед методом контроллера
return true; // Если вы хотите продолжить выполнение метода, вы должны вернуть true, если вы вернёте false, метод контроллера будет остановлен и не будет выполнен.
},
after : function(req, res, result, ctx) {
// Код, выполняемый после выполнения метода контроллера.
},
onError : function(req, res, error, ctx) {
// Код, выполняемый при возникновении исключения в методе контроллера.
}
}, // Если у вас несколько аспектов, передайте массив
// interceptors: [ {intercept: "@myOwnAnno1" , before: function(req, res){}} , {intercept: "myAnno2", after: function(req, res){}}],
}
Здесь вы увидите объект ctx, который в конечном итоге будет добавлен в область запроса, и в вашем методе контроллера вы можете получить доступ к тому же объекту через глобальный объект $context.
Например, с помощью этого метода вы можете легко реализовать использование одного и того же соединения с базой данных в одном запросе, и только после успешного выполнения бизнес-логики соединение будет зафиксировано. Если возникает исключение, вы можете откатить все операции. (О базе данных $db мы подробно расскажем в следующем разделе.)
// В global.js вы можете определить его следующим образом
$webapp = {
...
interceptors : {
intercept : "@transaction",
before : function(req, res, ctx) {
ctx.conn = $db.connect(); // Использовать источник данных с именем "default"
ctx.conn.autoCommit = false;
return true;
},
after : function(req, res, result, ctx) {
ctx.conn.commit();
},
onError : function(req, res, error, ctx) {
ctx.conn.rollback();
}
}
};
// In your controller script and the script files it imports.
function ctrlFun(req){
"@transaction";
$context.conn.insert("TableName", {...});
}
Фреймворк имеет встроенные аннотации для "@get", "@head", "@post", "@put", "@delete", "@connect", "@options", "@trace", "@patch". Как видите, эти аннотации фактически являются методами HTTP-запросов, и если вы используете одну или несколько из этих аннотаций и метод запроса не соответствует выбранным вами аннотациям, фреймворк напрямую вернёт ошибку 404.
События
Программисты на JavaScript часто используют событийно-ориентированный подход, но эта среда выполнения основана на J2EE, где поддержка событий очень слабая.
Однако мы также попытались поддержать некоторые событийно-ориентированные методы кодирования. Мы предоставляем глобальный объект $event в области запроса. Для получения подробной информации см.:
/**
* Зарегистрировать слушателя для прослушивания события с именем «eventName».
**/
var listener = $event.on("eventName", function(data) {
// Этот код будет выполняться при получении события «eventName».
});
/**
* Этот слушатель больше не слушает событие.
**/
listener.off();
/**
* Вы также можете использовать этот метод для отмены прослушивания, эффект такой же, как и у предыдущего метода.
**/
$event.remove(listener);
/**
* Отменить все события и удалить всех слушателей событий.
**/
$event.off("eventName");
/**
* Опубликовать событие, после публикации события все слушатели событий получат событие и выполнят соответствующий код.
**/
$event.publish("eventName", data);
Примечание! События поддерживаются только в области запросов, что означает, что вы не можете использовать их в global.js и файлах, которые он импортирует.
WebSocket
Чтобы использовать WebSocket, вам необходимо добавить переменную $websocket в ваш файл global.js:
$websocket = {
fileHome: "classpath:", // Путь к файлу JavaScript для обработки WebSocket, по умолчанию — "classpath:".
fileExtension: ".js", // Расширение файла JavaScript для обработки WebSocket, по умолчанию — ".js".
endpoints: [
{
endpoint: "/ws/echo/{pathValue0}/{pathValue1}", // Адрес вашего подключения к WebSocket.
handler: "/ws/echo/echo.upper", // Путь и обработчик файла. В этом примере обработчиком файла WebSocket является объект echo в classpath:/ws/echo.js, а upper — его дочерний объект.
onHandShake: function(conf, request, response) { // Этот метод является необязательным.
// Ваш код, который будет выполняться во время рукопожатия, обратите внимание: в этом методе conf, request и response все являются
Я не совсем понимаю, что именно вы хотели бы перевести. Пожалуйста, уточните запрос, если я неправильно понял исходный текст. **Объекты Java**
} }, "/ws/chatRoom/checkin", // Простой способ, не обрабатывающий рукопожатие, путь endpoint совпадает с путём класса обработки. Объект обработки находится в classpath:/ws/chatRoom.js и называется checkin. ] }
В приведённом примере конфигурация обработки websocket-соединений находится в пути classpath в Java, обычно это `/WEB-INF/classes`. Файлы имеют расширение `.js`.
В этом примере зарегистрировано два endpoint. Первый endpoint при обращении к нему через websocket-клиент имеет адрес: `ws://[имя сервера]:[порт сервера]/[контекст webapp]/ws/echo/pv0/pv1`, а файл обработки расположен в `classpaht:/ws` и называется `echo.js`. В этом файле должен быть следующий объект:
```javascript
var echo = {
upper : {
onOpen : function(session, conf) {
// Код, выполняемый при открытии websocket
},
onMessage : function(session, message) {
// Код для получения сообщения
},
onClose : function(session, closeReason) {
// Код, который выполняется при закрытии websocket
},
onError : function(session, throwable) {
// Код, который выполняется в случае ошибки
}
}
}
Второй endpoint при обращении к нему через websocket-клиент имеет адрес ws://[имя сервера]:[порт сервера]/[контекст webapp]/ws/chatRoom/checkin
, а файл обработки расположен в classpaht:/ws
и называется chatRoom.js
. В этом файле должен быть объект checkin
, структура которого аналогична структуре объекта echo.upper
из примера.
Объект обработки должен содержать как минимум один из следующих четырёх методов:
session
— это упакованный JSON-объект, а conf
— неупакованный Java-объект, совпадающий с объектом conf
в методе onHandShake
.session
и message
аналогичны объектам в методе onOpen
.closeReason
— объект Java CloseReason, неупакованный.throwable
— Java-объект исключения.Эти методы являются опциональными, вы можете выбрать те, которые вам нужны. Если ни один метод не реализован, то websocket не будет иметь смысла.
session.id
.session.id
.isLast
является необязательным параметром. Если передать isLast
, и его значение будет false
, то сессия не отправит текст сразу, а дождётся, пока isLast
станет true
.bytes
не является массивом byte[]
, метод ничего не делает.binary
должен быть объектом java.nio.ByteBuffer
в Java, иначе метод ничего не сделает.sendJSON
.session.uri
.{}
.session.pathValues
.session.pathValues
.session.pathValues
.?
в URI.session.parameterValues
.session.parameterValues
.session.parameterValues
.session.parameterValues
, но значение всегда одно. Если есть несколько параметров, возвращается только первый.Возможно, потребуется сохранить этот объект session в глобальной области видимости, чтобы использовать его для отправки сообщений клиенту в других запросах. Однако, поскольку Narson не является потокобезопасным, для обеспечения безопасности потоков можно обратиться к разделу «Потоки».
В KJServlet-фреймворке есть две области: глобальная и область запроса. Первая инициализируется при загрузке сервлета, и в ней, помимо некоторых встроенных скриптов, выполняется наиболее важный файл global.js
.
Область запроса создаётся при поступлении запроса на сервер. Сервлет распределяет запрос в KJServletRuntime, который является синглтоном. Runtime определяет маршрут запроса, находит правильный контроллер и метод, и создаёт новую область для выполнения кода контроллера.
Как переменные в глобальной области доступны в области запроса и наоборот? Здесь мы немного схитрили. Хотя файл, содержащий метод управления, выполняется в области запроса, сам метод управления выполняется в глобальной области. Поэтому метод управления может обращаться к переменным как в области запроса, так и в глобальной области. Кроме того, только метод управления и вызываемые им методы могут обращаться к глобальным переменным.
При реализации websocket каждый сеанс работает в своей собственной области, которая создаётся до вызова метода onOpen
и уничтожается после выполнения метода onClose
. conn.update(tableName, object || object-array[, whereQuery[, queryPrameters]]), обновление данных в указанной таблице базы данных. Если условие запроса не указано, метод попытается обновить поля объекта с идентификатором и соответствующие поля в базе данных.
var conn = $db.connect(); // Использование источника данных по умолчанию.
// Следующий метод обновит данные в строке, где id равен 2. Поскольку значение столбца sex не передано, оно не будет обновлено. Возвращаемое значение updateCount показывает, сколько строк было обновлено.
var updateCount = conn.update("User", {
"id": 2,
"userName": "Michael",
"userEmail": "mike@bcd.com"
});
// Обновление нескольких строк данных, убедитесь, что все объекты имеют одинаковые поля.
conn.update("User", [ {
"id": 2,
"userName": "Michael",
"userEmail": "mike@bcd.com"
}, {
"id": 3,
"userName": "Maria",
"userEmail": "mary@bcd.com"
}]);
// Выполнение обновления на основе запроса.
conn.update("User", {
"userName": "Maria",
"userEmail": "mary@xyz.com"
}, "where sex = ?", [ "female" ]);
conn.delete(tableName, id || idArray[, idColumnName]), удаление данных на основе первичного ключа. Вы можете указать имя столбца первичного ключа, если оно не указано, будет использоваться id.
var conn = $db.connect(); // Использование источника данных по умолчанию.
// Удаление строки с id равным 1.
conn.delete("User", 1);
// Удаление строк с id равными 1 и 2.
conn.delete("User", [ 1, 2 ]);
// В этом удалении столбец первичного ключа называется pk, а не id.
conn.delete("User", [ 1, 2 ], "pk");
conn.del(tableName, whereSql [, parameters]), выполнение удаления на основе запроса.
var conn = $db.connect(); // Использование источника данных по умолчанию.
// Удаление всех пользователей мужского пола.
conn.del("User", "where sex = ?", ["male"]);
Все соединения по умолчанию используют кэширование и автоматическую фиксацию.
По умолчанию результаты каждого запроса сохраняются в текущем объекте соединения. При повторном запросе с теми же параметрами результат будет взят из кэша. Если это нежелательно (например, каждый запрос уникален и сохранение результатов в кэше занимает слишком много памяти), можно отключить кэширование глобально в объекте $db в файле global.js с помощью $db.cache = false или для конкретного соединения с помощью conn.cache = false.
Чтобы отключить автоматическую фиксацию, установите conn.autoCommit = false в объекте соединения. После этого необходимо вручную вызывать conn.commit() для фиксации изменений или conn.rollback() для их отмены.
KJServlet предоставляет простой объект журнала, который по умолчанию выводит данные в стандартный поток вывода Java. Методы объекта:
Уровень журнала по умолчанию — «info», поэтому при использовании $log.d(tag, message) информация в консоль выводиться не будет. Уровень журнала можно изменить в файле global.js:
$log.level = "debug";
Также поддерживается log4j. Для его использования необходимо заменить глобальный объект $log на новый. Получить объект log4j можно с помощью встроенного метода $logFac.getLogger("log4j"). Интерфейс объекта log4j совпадает с интерфейсом стандартного объекта журнала, но метод $log.level работать не будет. Необходимо создать файл log4j.properties для настройки уровня логирования и пути к файлу журнала в соответствии со спецификацией log4j (см. документацию log4j).
Необходимо также самостоятельно настроить зависимости log4j, например, при использовании maven добавить в файл pom.xml следующую конфигурацию:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
Этот объект предоставляет простые функции проверки. Он позволяет сократить количество написанных операторов if. Пример использования:
var obj = { "name": "keijack", "password": "kj$servlet0.10", "password2": "123456789", "age": "13", "savage": "10000", "code": "1234" };
var rules = {
"name": [
{
"rule": "required"
}, {
"rule": "length",
"min": 3,
"max": 20,
"message": "Длина имени должна быть между {min} и {max}."
}, {
"rule": "regex",
"pattern": "/^[a-zA-Z]*$/",
"message": "Введите буквы латинского алфавита."
}, {
"rule": function (val) {
var user = loadUserByName(val);
return user != null;
},
"message": "Это имя уже занято, выберите другое."
}
],
"passwrod": [
{
"rule": "required"
}, {
"rule": "length",
"min": 6,
"max": 20,
"message":
``` **Пароль должен быть длиной от {min} до {max} символов.**
В запросе описывается использование библиотеки для проверки данных на основе определённых правил. В библиотеке есть встроенные правила: «required», «length», «number», «equalTo», «regex» и функция. Также можно настроить сообщение об ошибке, которое будет добавлено в список ошибок при их наличии.
Если ошибок нет, метод возвращает false. Можно упростить конфигурацию, если не нужно настраивать сообщения об ошибках и используется только одно правило для поля.
Также в запросе упоминается Nashorn — это среда выполнения JavaScript на базе движка Rhino. Она не является многопоточной и вряд ли станет таковой в ближайшее время. Однако приложение KJServlet работает в J2EE-контейнере, где каждый запрос обрабатывается в отдельном потоке. Поэтому приложение должно быть многопоточным. Для этого предлагается создать контекстный объект для каждого запроса. Это делает KJServlet многопоточным приложением.
Для обмена данными между потоками предлагается использовать Redis или базу данных. Но если вы хотите сделать это с помощью кода, то можно использовать глобальный объект $MTSGlobal. Он представляет собой потокобезопасный класс Java ConcurrentHashMap. С его помощью можно создавать объекты для обмена данными.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )