Проект больше не будет поддерживаться, поскольку Nashorn объявлен устаревшим и будет удалён из JDK.
KJServlet представляет собой легковесный веб-фреймворк на JavaScript, который позволяет писать серверный код на JavaScript. Он основан на Nashorn — скриптовом движке, представленном в Java 8. Другими словами, в отличие от Node.js, работающего на движке V8, этот фреймворк работает в среде JVM. Это означает, что вы можете использовать все виды библиотек Java для создания собственных веб-приложений.
Это также очень свободный фреймворк, он позволяет вам писать свой JavaScript разными способами. Например, при написании контроллера вы можете использовать функции или методы в объекте JavaScript; вы можете написать ответ в функции обратного вызова или просто вернуть объект JSON и позволить фреймворку выполнить рендеринг.
Этот документ является справочным руководством по функциям фреймворка KJServlet. Поскольку это очень новый фреймворк и написан одним человеком (мной), могут быть некоторые ошибки, которые я не обнаружил. Если вы обнаружите какие-либо проблемы или у вас есть вопросы или предложения, или вы хотите принять участие в этом проекте, пожалуйста, дайте мне знать, вот мой адрес электронной почты: keijack.wu@gmail.com.
О лицензии: мы предоставляем два вида лицензий, по умолчанию используется GPL. Но если вы хотите использовать этот фреймворк в своём бизнесе и не хотите открывать исходный код своей системы, обратитесь за лицензией Apache.
Как видно из названия проекта, это сервлет, поэтому вы можете легко встроить его в любые проекты J2EE. Следуйте этим шагам, чтобы запустить демонстрацию:
kjservlet-[version].jar
и поместите его в свой проект, обычно это папка: [webapps]/WEB-INF/lib
pom.xml
: <dependency>
<groupId>me.keijack.kjservlet</groupId>
<artifactId>kjservlet</artifactId>
<version>0.1.0</version>
</dependency>
web.xml
: <servlet>
<display-name>k-js-servlet</display-name>
<servlet-name>KJServlet</servlet-name>
<servlet-class>org.keijack.kjservlet.KJServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>KJServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
demo.js
в папку classpath, которая обычно находится в [webcontent]/WEB-INF/classes
.demo.js
, например:function sayHello(req){
var name=req.param["name"];
return "<!DOCTYPE html><html><head><title>Say Hello</title></head><body>Hello, " + name + "</body></html>";
}
http://[your_server_host]:[your_server_port]/[your_servlet_context]/demo/sayHello?name=World
, тогда вы увидите «Hello World» в браузере.Для получения дополнительной информации, пожалуйста, прочитайте Руководство пользователя.
Как видите, в демонстрации нет конфигураций маршрутов, но как же фреймворк находит маршрут? Здесь используются каталоги.
Возьмём демонстрацию из Начало работы в качестве примера, если вы поместите demo.js в каталог path
в пути к классам (так что реальный путь demo.js будет [webcontent]/WEB-INF/classes/path/demo.js
), то вы будете использовать http://[your_server_host]:[your_server_port]/[your_servlet_context]/path/demo/sayHello?name=World
для посещения функции контроллера.
На самом деле у вас есть несколько способов настроить маршрут. Файл global.js
в корневой папке classpath будет запущен при подготовке среды выполнения. В этом файле вы можете переопределить глобальную переменную $webapp, которая повлияет на маршрутизацию. Текст запроса:
is "classpath:" fileSuffix : ".js", // What suffix is your js file, default is ".js" suffix : "", // If your url have a suffix, like ".do", please set it here }, resources : [ ".html", "/images/" ], // the url match these pattern will be treated as the static files };
If you want to get more information about this `global.js` file, please read the **The global.js file** chapter.
The last portion of the url is the controller function name, which is `sayHello` in the example above. In this example the function `sayHellow` in the `demo.js` will be called.
There is also another way to route to the controller function, we will talk about that later.
KJServlet is function related design, it's OK for you to use global functions. In fact, every request will run in its own scope -- We will go deeper into that latter -- so it doesn't matter even you have duplicated function names in different controller files. But if you want to arrange your codes well by using spaces and objects, the framework supports that as well.
In the example above, if you defined an object like the following in your `demo.js` file:
```javascript
var person = {
yieldName : function(req) {
var name = req.parameters.name;
return "<!DOCTYPE html><html><head><title>Say Hello</title></head><body>My name is " + name + "!</body></html>";
}
};
Then you can use the following url to visit:
http://[your_server_host]:[your_server_port]/[your_servlet_context]/demo/person.yieldName?name=John
You can add alias to routes, at your $webapp object, add a property named alias
. for example:
$webapp = {
controller : {
fileHome : "classpath:/org/keijack/kjservlet/demo/controller", // Where your js files are, default is "classpath:"
fileSuffix : ".js", // What suffix is your js file, default is ".js"
suffix : "", // If your url have a suffix, like ".do", please set it here
},
aliases : {
"/yieldMyName" : "/demo/person.yieldName",
},
resources : [ "*.html", "/images/*" ], // the url match these pattern will be treated as the static files
};
Then the following url can also visit the controller defined in the example above.
http://[your_server_host]:[your_server_port]/[your_servlet_context]/yieldMyName?name=John
## Import Other Script Files
The last chapter shows you how to route a url to a function in a Javascript file. You won't just define one function as the controller in most cases. You will have to call other functions, but how could you call the function in other script files?
Nashorn provides a function load(path), but normally, we recommend you to use a function name imports(path) instead.
There are several reasons that you should use imports():
* In one scope -- global.js runs on the global scope, and every request runs on its own scope --, no matter how many times you call the import function, it only import the same file once. It's more efficient when your scripts import some common function that you define in a common script file.
* It's much easier to handle location, it use the relative path rather than absolute path. *Notice! In controller script files and the files imported by them, the relative root is the fileHome you define in `$webapp`. While in global.js and the files it imports, `classpaht:` is the relative root.*
* in imports function, the path can use `.` to separate path just like the package path in Java. Both `org.keijack.kjservlet.service` and `org/keijack/kjservlet/service` are accepted. *Notice! In controller script files and the files imported by them, the suffix is the one you define in `$webapp`. While in global.js and the files it imports, `.js` is only suffix that supported.*
## Writing Controllers
### The Request and the Response arguments
Just like the normal servlet that you will write when you implements javax.servlet.Servlet Interface in Java code, the framework will give you two arguments to your controller function. You should get user data from the first argument the
**Перевод текста запроса на русский язык:**
Это «classpath:»
fileSuffix: «.js», // Какой суффикс у вашего файла js, по умолчанию — «.js»
суффикс: "", // Если в вашем URL есть суффикс, например «.do», пожалуйста, установите его здесь
},
ресурсы: [«* .html», «/ images/*»], // URL-адреса, соответствующие этим шаблонам, будут обрабатываться как статические файлы
};
Если вы хотите получить дополнительную информацию об этом файле global.js, пожалуйста, прочтите главу «Файл global.js».
Последняя часть URL — это имя функции контроллера, которое в приведённом выше примере равно «sayHello». В этом примере будет вызвана функция sayHellow в файле demo.js.
Есть и другой способ маршрутизации к функции контроллера, мы поговорим об этом позже.
KJServlet — это функциональный дизайн, можно использовать глобальные функции. Фактически каждый запрос выполняется в своей собственной области видимости — мы рассмотрим это позже — поэтому не имеет значения, даже если у вас есть дублированные имена функций в разных файлах контроллеров. Но если вы хотите упорядочить свои коды с помощью пробелов и объектов, фреймворк также поддерживает это.
В приведённом выше примере, если вы определили объект, подобный следующему, в своём файле demo.js:
```javascript
var person = {
yieldName: function (req) {
var name = req.parameters.name;
return "<!DOCTYPE html><html><head><title>Say Hello</title></head><body>My name is" + name +"!</body></html>";
}
};
Тогда вы можете использовать следующий URL для посещения:
http://[ваш_сервер_хост]:[ваш_порт_сервера]/[контекст_вашего_сервлета]/demo/person.yieldName?имя=Джон
Вы можете добавить псевдоним к маршрутам в объекте $webapp, добавив свойство с именем alias. Например:
$webapp = {
контроллер: {
файл_дома: "classpath:/org/keijack/kjservlet/demo/контроллер", // Где находятся ваши файлы js, по умолчанию - "classpath:"
fileSuffix: ".js", // Какой суффикс имеет ваш файл js, по умолчанию — ".js"
суффикс: "", // Если ваш URL имеет суффикс, например ".do", пожалуйста, установите его здесь
},
псевдонимы: {
"/yieldMyName": "/demo/person.yieldName",
},
ресурсы: ["* .html", " / images/*"], // URL-адреса, соответствующие этим шаблонам, будут обрабатываться как статические файлы
};
Затем следующий URL также может посетить контроллер, определённый в приведённом выше примере.
http://[ваш_сервер_хост]:[ваш_порт_сервера]/[контекст_вашего_сервлета]/yieldMyName?имя=Джон
В последней главе показано, как направить URL на функцию в файле JavaScript. В большинстве случаев вы будете определять не одну функцию как контроллер. Вам придётся вызывать другие функции, но как вы могли бы вызвать функцию в других файлах сценариев?
Nashorn предоставляет функцию load (путь), но обычно мы рекомендуем вам использовать функцию с именем imports (путь) вместо неё.
Существует несколько причин, по которым вам следует использовать импорт ():
Точно так же, как обычный сервлет, который вы напишете, когда реализуете интерфейс javax.servlet.Servlet в коде Java, фреймворк предоставит вам два аргумента вашей функции контроллера. Вы должны получить данные пользователя из первого аргумента. Использование объекта $renderer
Текст запроса представляет собой техническую документацию, связанную с разработкой и тестированием программного обеспечения. Основной язык текста — английский.
Используя объект $renderer, ваш стиль кода, вероятно, будет выглядеть так:
function dosth(req){
var param = req.parameters;
var serviceResult = someServiceObject.doService(param);
return $renderer.json(serviceResult);
}
Вы можете использовать ещё более простой способ сделать это, например:
function dosth(req){
var param = req.parameters;
var serviceResult = someServiceObject.doService(param);
return serviceResult;
}
Фреймворк сделает обёртку за вас. Вы также можете вернуть строку, например:
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"
MVC — хорошо известный шаблон проектирования, основной принцип которого заключается в разделении слоя бизнес-логики (Model), слоя управления (controller) и слоя представления (View), чтобы сделать код более понятным и лёгким для чтения, поддержки и расширения.
Веб-разработчики любят использовать шаблоны MVC, особенно разработчики Java, поэтому они проделали большую работу по созданию всевозможных движков шаблонов. Благодаря этому мы можем легко использовать MVC в нашей структуре.
KJServlet поддерживает шаблонизаторы JSP, Freemarker и Velocity.
Использовать шаблон очень просто, вот так:
function dosth(req){
var param = req.parameters;
var serviceResult = someServiceObject.doService(param);
return $renderer.view("/WEB-INF/pages/view.jsp", serviceResult);
}
Шаблонизатор по умолчанию — JSP; если вы хотите изменить его, настройте его в $webapp в файле global.js
.
$webapp = {
controller : {
fileHome : "classpath:/org/keijack/kjservlet/demo/controller", // Где находятся ваши js файлы, по умолчанию "classpath:"
fileSuffix : ".js", // Какой суффикс у вашего js файла, по умолчанию ".js"
suffix : "",
},
resources : [ "*.html", "/images/*" ],
view : {
resolver : "jsp", // Резолвер, "jsp" по умолчанию, вы можете изменить его на "freemarker" или "velocity" Префикс представления:
suffix : ".jsp", // суффикс представления
Контроллер будет иметь следующий вид:
```javascript
function dosth(req){
var param = req.parameters;
var serviceResult = someServiceObject.doService(param);
return $renderer.view("view", serviceResult); // и файл шаблона будет /WEB-INF/pages/view.jsp
}
Обратите внимание! При изменении резолвера на freemarker
или velocity
необходимо импортировать соответствующие jar-файлы в проект. Если вы используете резолвер freemarker и создаёте веб-приложение с помощью maven, то в ваш pom.xml
должна быть добавлена следующая зависимость:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.26-incubating</version>
</dependency>
Второй параметр, который называет данные $renderer.view(templateFileLocation, data, header), должен быть объектом 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.
return data.age >= 18;
},
"age": 28,
"department": { "name": "HR",
"phone": "+01xxxxxx",
},
"subordinates": ["Mike", "Lily"]
};
Обратите внимание: пожалуйста, не используйте this
в таких функциях, поскольку они будут заключены в Java-объект JSFunctionWrapper
, где this
будет указывать на него.
Тогда в вашем файле шаблонов:
<!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", // Где находятся ваши js-файлы, по умолчанию используется "classpath:"
fileSuffix : ".js", // Какой суффикс у вашего js-файла, по умолчанию — ".js"
suffix : "",
},
resources : [ "*.html", "/images/*" ],
view : {
resolver : function(viewFileLocation, data, headers){
// viewFileLocation уже связан с префиксом и суффиксом.
// здесь вы можете реализовать свою логику
var html = ...;
// наконец, не забудьте вернуть результат.
return $renderer.html(html, headers);
},
prefix : "/WEB-INF/pages/", // префикс представления
suffix : ".jsp", // суффикс представления
},
}
``` **$event.publish("eventName", data);**
*Обратите внимание! $event работает только в области запроса, это означает, что вы не можете использовать объект $event в global.js и импортированных в него скриптах.*
## Websocket
### Конфигурация
Чтобы использовать websocket, добавьте определение объекта `$websocket` в свой `global.xml`:
```javascript
$websocket = {
fileHome: "classpath:", // Где находятся ваши файлы обработчиков js. По умолчанию 'classpath:'.
fileExtension: ".js", // Расширение ваших файлов обработчиков js. По умолчанию '.js'.
endpoints: [
{
endpoint: "/ws/echo/{pathValue0}/{pathValue1}", // URL, к которому ваш клиент подключается к серверу.
handler: "/ws/echo/echo.upper", // Путь и объект вашего файла обработчика js.
onHandShake: function(conf, request, response) { // этот метод является необязательным
// ваши коды здесь. Объекты conf, request и response являются объектами Java.
}
},
"/ws/chatRoom/checkin", // простой способ, без onHanShake, значение endpoint и значение handler совпадают.
]
}
В приведённой выше конфигурации ваши файлы обработчиков javascript для websocket будут храниться в пути к классам Java, который, вероятно, будет /WEB-INF/classes
, и с расширением .js
. Зарегистрировано два конечных пункта, клиент websocket будет подключаться к URL ws://[имя_сервера]:[порт_сервера]/[контекст_webapp]/ws/echo/pv0/pv1
, а файл обработчика javascript будет иметь имя echo.js
и располагаться в папке classpath:/ws
. В этом файле javascript есть как минимум один объект, например:
var echo = {
upper: {
onOpen: function(session, conf) {
// Этот метод будет вызываться при открытии сессии.
},
onMessage: function(session, message) {
// ваши коды
},
onClose: function(session, closeReason) {
// ваши коды
},
onError: function(session, throwable) {
// ваши коды
}
}
}
С момента запуска сессии до её завершения будут вызваны четыре метода. Они следующие:
session
— это объект JSON, conf
— объект Java, тот же объект, который передаётся методу onHandShake
, настроенному в global.js
.session
— тот же объект, который был передан методу onOpen
. Переменная message
— текстовое сообщение, отправленное клиентом на сервер.session
— тот же объект, который был передан методу onOpen
. closeReason
— оригинальный объект CloseReason J2EE.session
— тот же объект, который был передан методу onOpen
. throwable
— исключение или ошибка, выброшенные бизнес-логикой.Все эти четыре метода являются необязательными, вы можете выбрать те, которые вам нужны.
session
session.oriSession — исходный объект Java Session.
session.id — идентификатор этой сессии.
session.sessionId — псевдоним session.id.
session.getId() — метод, возвращающий session.id.
session.sendText(text, isLast) — метод отправки текста клиенту. Если переменная isLast
передана, сессия отправит весь текст, только если isLast == true
.
session.sendPing(pingMsg) — отправить сообщение ping.
session.sendPong(pongMsg) — отправить сообщение pong.
session.sendBytes(bytes) — отправка массива байтов Java. Если переменная bytes
не является объектом byte[]
, этот метод ничего не сделает.
session.sendBinary(binary) — отправка двоичных данных. binary
должен быть объектом java.nio.ByteBuffer
, иначе этот метод ничего не сделает.
session.sendJSON(jsonObject) — отправка объекта JSON в виде строки.
session.sendJson(jsonObject) — псевдоним session.sendJSON(jsonObject)
.
session.sendJavaObject(javaObject) — отправка Java-объекта.
session.send(data) — этот... Метод найдёт подходящий метод отправки для отправки сообщения.
session.uri — URI этого веб-сокета.
session.requestURI — псевдоним session.uri.
session.pathValues — значения пути, настроенные в конечной точке. Это объект JSON, ключ — это слова, которые настраиваются в конечной точке и окружены символами {}, а значение — это слова, которые вы передаёте при подключении.
session.pathValue — псевдоним session.pathValues.
session.pathVals — псевдоним session.pathValues.
session.pathVal — псевдоним session.pathValues.
session.queryString — строка запроса из URL подключения.
session.pathParameters — псевдоним session.pathValues.
session.pathParams — псевдоним session.pathValues.
session.pathParam — псевдоним session.pathValues.
session.parameterValues — как и в запросе Http, он поступает из строки запроса, значения этого объекта всегда представляют собой массив.
session.paramValues — псевдоним session.parameterValues.
session.paramVals — псевдоним session.parameterValues.
session.requestParameterMap — псевдоним session.parameterValues.
session.parameters — аналогично session.parameterValues, но значение этого объекта всегда является строкой. Если в строке запроса есть более одного значения с одинаковым именем, здесь будет первое.
Вы можете сохранить сеанс для глобального использования и отправлять текст в других потоках, однако, поскольку Nashorn не является многопоточным безопасным, пожалуйста, проверьте раздел «Многопоточная безопасность», чтобы найти решение.
В KJservlet есть два вида областей видимости. Одна — глобальная область, которая инициализируется после загрузки сервлета. Некоторые внутренние сценарии и наиболее важный глобальный сценарий — gloabl.js — будут выполняться в это время.
Другая область — область действия запроса. Когда приходит запрос, сервлет вызовет метод диспетчеризации синглтона KJServletRuntime. Метод диспетчеризации вычислит маршрут, найдёт контроллер js и затем запустит его в новой области.
Затем происходит небольшой трюк. После загрузки скрипта контроллера сама функция контроллера будет работать в глобальной области видимости. Таким образом, ваши функции контроллера могут получить доступ к объектам и функциям в обеих областях. Это означает, что вне функции контроллера и функций, которые она вызывает, вы не можете использовать объекты и функции, определённые в global.js.
При подключении через веб-сокет каждая сессия будет работать только в одной области, которая будет запущена перед обратным вызовом onOpen и завершится после обратного вызова onClose.
Файл global.js предназначен для воздействия на глобальную область видимости, этот файл находится в корневой папке пути класса и должен иметь имя global.js. Вам разрешено импортировать файлы сценариев, но, в отличие от файлов сценариев контроллеров, вы должны поместить все свои глобальные файлы под путь класса и его подпапку, и все ваши глобальные файлы должны использовать суффикс «.js».
Поскольку этот файл запускается только один раз при инициализации среды выполнения, рекомендуется, чтобы все объекты, используемые всеми (или, по крайней мере, большинством) функций контроллера, были помещены сюда, например, объект пула соединений с базой данных, некоторые ваши собственные конфигурации, такие как ключ доступа AWS и секретный ключ доступа.
Наиболее распространённая конфигурация, которую вы будете использовать здесь, — это $webapp, который влияет на ваши маршруты, расположение ваших сценариев контроллера, преобразователь MVC и перехватчики, всё это уже обсуждалось в предыдущих главах.
Мы предоставляем некоторые объекты для упрощения вашего кодирования. И появляется всё больше и больше плагинов.
Вы можете использовать imports("$db"); для импорта этого объекта в контекст вашей области видимости. Но рекомендуется импортировать его в вашу глобальную область и настроить там соединение.
Все зависимости не будут автоматически импортироваться в проект, поэтому, когда вы используете этот объект, просто управляйте своими зависимостями в... Подключение к базе данных
Если вы используете MySQL:
<!-- Если вы используете mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.43</version>
</dependency>
Если вы используете пул соединений Druid:
<!-- Если вы используете druid connection pool -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.2</version>
</dependency>
Использование в простом виде
Просто используйте:
// Хотя вам следует импортировать файл $db в ваш global.js, но каждое соединение имеет свой собственный стиль жизни, поэтому следующий код должен быть помещён в вашу функцию контроллера.
var conn = $db.connect("jdbc:mysql://127.0.0.1:3306/db", "username", "password");
Но, как мы говорили выше, мы не хотим разбрасывать все URL, имя пользователя и пароль по всему коду. Поэтому следующий способ лучше.
// Это должно быть помещено в ваш `global.js`
$db.addDatasource("default", {
url : "jdbc:mysql://127.0.0.1:3306/kjtest",
user : "username",
password : "password"
});
// и в вашей функции контроллера вы можете использовать это
var con = $db.connect("default");
// поскольку источник данных называется «default», вы можете игнорировать этот аргумент при получении соединения:
var con = $db.connect();
Обратите внимание! Этот метод поддерживает только MySQL и его вариант MariaDB, и вы должны обрабатывать зависимость драйвера mysql в вашем pom.xml.
Если вы не используете MySQL или хотите использовать пул подключений
Используйте это:
// Если вы используете пул подключений Druid, поместите это в свой `global.js`:
$db.addDatasource("druid", "com.alibaba.druid.pool.DruidDataSource", {
url : "jdbc:mysql://127.0.0.1:3306/kjtest",
username : "username",
password : "password",
filters : "stat",
maxActive : 20,
initialSize : 1,
maxWait : 60000,
minIdel : 1,
timeBetweenEvictionRunsMillis : 60000,
minEvictableIdleTimeMillis : 30000,
testWhileIdle : true,
testOnBorrow : false,
testOnReturn : false,
poolPreparedStatements : true,
maxOpenPreparedStatements : 20
}).init(); // Не каждый источник данных имеет этот метод init, пожалуйста, проверьте, прежде чем писать это.
// Затем в вашей функции контроллера
var conn = $db.connect("druid");
Объект подключения
После того как вы получите объект подключения, вы можете использовать select, insert, update, delete, чтобы выполнять свои задачи.
id | userName | userEmail | sex |
---|---|---|---|
1 | John | john@abc.com | male |
2 | Mike | mike@abc.com | male |
3 | Mary | mary@abc.com | female |
И в вашем коде:
var conn = $db.connect("druid");
var result = conn.select("select * from User where sex = ?", [ "male" ]); // Если второй аргумент является массивом параметров, его длина должна равняться количеству '?' в предыдущем строковом аргументе, который является предложением SQL.
print(JSON.stringify(result);
Тогда вы обнаружите, что вывод будет:
[
{"id": 1, "userName": "John", "userEmail": "john@abc.com", "sex": "male"},
{"id": 2, "userName": "Mike", "userEmail": "mike@abc.com", "sex": "male"}
]
var conn = $db.connect(); // Присутствует источник данных с именем «default».
// Вставьте новую строку в таблицу.
// Результат updateCount показывает, сколько строк было вставлено.
var updateCount = conn.insert("User", {
"userName" : "Ben",
"userEmail" : "ben@xyz.com",
"sex" : "male"
});
// Вставка нескольких строк в таблицу. **conn.insert("User", [{
"userName" : "Ben",
"userEmail" : "ben@xyz.com",
"sex" : "male"
}, {
"userName" : "Kate",
"userEmail" : "kate@xyz.com",
"sex" : "female"
}]);**
* **conn.update(tableName, object || object-array[, whereQuery[, queryPrameters]])** — обновить таблицу с помощью заданного объекта или массива объектов. Если передан SQL-запрос where, обновление будет выполнено через это условие, иначе будет использоваться свойство id в объектах.*
**Пример:**
* *следующее предложение обновит строку с идентификатором 2 в таблице User, поскольку столбец 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"
}]);
* *обновление через SQL-запрос:*
conn.update("User", {
"userName" : "Maria",
"userEmail" : "mary@xyz.com"
}, "where sex = ?", [ "female" ]);
* **conn.delete(tableName, id || idArray[, idColumnName])** — удалить строки по id, можно указать имя столбца id.*
Пример:
* *удалить строку с id равным 1:*
conn.delete("User", 1);
* *удалить две строки:*
conn.delete("User", [ 1, 2 ]);
* *если ваш первичный ключ не id, а pk:*
conn.delete("User", [ 1, 2 ], "pk");
* **conn.del(tableName, whereSql [, parameters])** — удаление строк по заданным условиям запроса.*
Пример:
* *удаление всех строк с sex равным male:*
conn.del("User", "where sex = ?", ["male"]);
* **conn.execute(sql [, parameters])** — если вы хотите выполнить сложный SQL, используйте этот метод.*
Пример:
conn.excute("update table `User` set `name` = ? where id in (select id....)", ['John', ...]);
### Кэширование и AutoCommit
Все соединения здесь выполняют кэширование и автоматическую фиксацию.
С кэшированием каждый запрос будет кэшироваться в объекте соединения, и при повторном запросе будет возвращён результат из кэша. Если вы не хотите использовать кэширование, вы можете указать это в объекте $db ($db.cache = false) в вашем global.js или в объекте подключения, чтобы отключить только одно подключение (conn.cache = false).
Если вы хотите отключить автофиксацию, установите её в объекте подключения: conn.autoCommit = false, тогда вы сможете использовать conn.commit() и conn.rollback() для фиксации или отката.
### Объект $log
KJServlet предоставляет простой логгер для записи сообщений. По умолчанию он использует только стандартный поток вывода системы. Все его методы:
* $log.d(tag, message, error) — регистрирует сообщение отладки, параметр error является необязательным.
* $log.i(tag, message, error) — записывает информационное сообщение, параметр error является необязательным.
* $log.w(tag, message, error) — регистрирует предупреждающее сообщение, параметр error является необязательным.
* $log.e(tag, message, error) — регистрирует сообщение об ошибке, параметр error является необязательным.
* $log.f(tag, message, error) — регистрирует фатальное сообщение, параметр error является необязательным.
Уровень журнала по умолчанию — «информация», это означает, что если вы используете $log.d(tag, message), в консоли не будет отображаться журнал. Пожалуйста, установите уровень отладки в global.js:
$log.level = "debug";
Мы также поддерживаем регистратор log4j, если вы хотите его использовать, замените им стандартный объект $log в global.js:
$log = $logFac.getLogger("log4j");
Интерфейс регистратора log4j такой же, как у стандартного логгера. Однако $log.level будет... **Не работает, и вам необходимо создать файл log4j.properties, чтобы указать, где и как будут регистрироваться сообщения.** (Пожалуйста, ознакомьтесь с руководствами пользователя log4j для получения дополнительной информации).
Вам также следует самостоятельно обработать зависимость в вашем файле `pom.xml`, добавив следующую зависимость:
```xml
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
$validator
Этот объект предоставляется для упрощения процесса валидации объектов. Пожалуйста, проверьте приведённый ниже код:
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": "Допустимы только символы a-z и A-Z"
}, {
"rule": function (val) {
var user = loadUserByName(val);
return user != null;
},
"message": "Это имя уже используется, пожалуйста, выберите другое"
}
],
"passwrod": [
{
"rule": "required"
}, {
"rule": "length",
"min": 6,
"max": 20,
"message": "Длина пароля должна быть от {min} до {max}"
}],
"password2": [
{
"rule": "equalsTo",
"target": "password"
}
],
"age": [
{
"rule": "number",
"min": 18,
"max": 60,
"message": "Ваш возраст должен быть между {min} и {max}. "
}
],
"savage": [
{
"rule": "number"
}
],
"code": [
{
"rule": "required"
}
]
};
var result = $validator.hasError(obj, rules);
Объект obj
выше — это объект, который необходимо проверить, а rules
— это конфигурационный объект, содержащий все поля для проверки, и каждое поле имеет массив правил. Существует несколько внутренних поддерживаемых правил:
required
— объект должен иметь это поле, и значение этого поля не должно быть нулевым. Вы также можете использовать notNull
, чтобы назвать это правило.length
— если это поле не равно нулю (если вы хотите, чтобы это поле было обязательным, используйте правило required
, чтобы указать), длина этого поля должна находиться между min
и max
, которые вы указываете в этом правиле.number
— это поле должно быть числом, вы можете указать min
и max
для обработки диапазона этого поля.equalTo
— вы можете указать цель, значение которой должно совпадать со значением этого поля.regex
— это поле должно соответствовать регулярному выражению, которое вы должны указать в свойстве pattern
.message
, и когда поле недействительно по этому правилу, это сообщение будет добавлено к результату. Фактически результат будет выглядеть так:{
name: ["Это поле обязательно", "Длина имени должна быть от 3 до 20"]
}
Конечно, если с проверяемым объектом всё в порядке, результатом будет false
.
Вы также можете упростить объект правил, когда требуется только одно свойство, вы можете просто использовать это свойство в качестве значения, но не в формате объекта правила, например:
var rules = {
"name": [
"required",
{
"rule": "length",
"min": 3,
"max": 20,
"message": "Длина имени должна быть от {min} до {max}"
},
/^[a-zA-Z]*$/,
function (val) {
var user = loadUserByName(val);
return user != null;
}
],
"passwrod": [
"required",
{
"rule": "length",
"min": 6,
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )