<?xml version="1.0"?>
<!DOCTYPE employee [
<!ELEMENT employee (Name, Dept, Title)>
<!ELEMENT Name (#PCDATA)>
<!ELEMENT Dept (#PCDATA)>
<!ELEMENT Title (#PCDATA)>
]>
<employee>
<Name>John Goodman</Name>
<Dept>Manufacturing</Dept>
<Title>Supervisor</Title>
</employee>
XML-схема
• Для включения в документ ссылку на файл схемы нужно указать в корневом элементе соответствующие атрибуты, например:
<? xmlversion ="1.0"?>
< configuration xmlns: xsi = http://www.w3.org/2001/XMLSchema-instance
xsi: noNamespaceSchemaLocation ="config.xsd">
…
< /configuration >
• В данном случае в составе корневого элемента содержится информация о том, что при проверке документа должен использоваться файл схемы config.xsd.
• Если применяется пространство имен – синтаксис усложняется.
• Схема определяет тип каждого элемента
• Это может быть простой или сложный тип
• Некоторые простые типы предопределены в XML-схеме:
• xsd:string
• xsd:int
• xsd:boolean
• Можно определять собственные простые типы
• Вместо префикса xsd (обозначает пространство имен XSLSchemaDefinition), можно применять xs:
• Определяя элемент, следует указать его тип:
• <xsd:element name="name" type="xsd:string"/>
• <xsd:element name=“size" type="xsd:int"/>
• Простые типы можно объединять в сложные:
< xsd : complexTypename = " FontType ">
<xsd:sequence>
<xsd:element ref = "name" />
<xsd:element ref = “size" />
<xsd:element ref = “style" />
</ xsd : sequence >
</ xsd : complexType >
• FontType – последовательность элементов name, size и style.
• Атрибут ref используется для ссылки на определения, находящиеся в схеме.
• Возможны вложенные определения.
• Для определения атрибутов необходимо включать элементы xsd:attribute.
Dom и SAX
• Для разборки XML-документа необходимо выполнить синтаксический анализ или разбор его содержимого.
• Анализатором ( parser ) называется программа, которая считывает файл, подтверждает корректность его формата, разбивает данные на составные элементы и предоставляет программисту доступ к ним.
• Существует два основных типа XML-анализаторов:
§ DOM -анализатор ( DocumentObjectModel ) считывает XML-документ и представляет его в виде древовидной структуры.
§ SAX -анализатор ( SimpleAPIforXML ) генерирует события по мере чтения XML-документа.
• DOM-анализатор представляет документ как древовидную структуру, SAX-анализатор генерирует события в ходе разбора документа.
• При обработке больших документов DOM-анализатор неэффективен, так как требуется память для хранения всей древовидной структуры, SAX-анализатор более экономичный.
• Сформированную древовидную структуру можно многократно и по-разному обходить, при использовании SAX-анализатора события генерируются последовательно в порядке возникновения и повторный обход документа невозможен.
Dom
• Пакет org.w3c.dom содержит определения типов интерфейсов, например, Document и Element.
• Ряд компаний, например, IBM и Apache, разработали собственные варианты DOM-анализаторов, которые реализуют эти интерфейсы.
• В API обработки XML-документов(JavaAPIforXMLProcessing-JAXP) компании Sun предусмотрена возможность подключения данных анализаторов.
• Кроме того, компания Sun включила в состав пакета JDK собственный анализатор.
Для считывания XML-документа потребуется объект DocumentBuilder , который можно получить с помощью класса DocumentBuilderFactory .
DocumentBuilder Factory factory = DocumentBuilder Factory.newInstance();
DocumentBuilder builder = factory.new DocumentBuilder();
File f = … // можноиспользовать URL или InputStream
Document doc = builder.parse(f);
• Объект Documentявляется внутренним представлением древовидной структуры XML-документа.
• Он состоит из экземпляров классов, реализующих интерфейс Node и его дочерние интерфейсы (Attr , Comment , Document , Element , Text).
• Анализ содержимого документа начинается с вызова метода getDocumentElement (), который возвращает корневой элемент
Elementroot = doc.getDocumentElement();
• Метод getTagName () возвращает имя дескриптора элемента.
• Для извлечения элементов, дочерних по отношению к данному (вложенных элементов, текста, комментариев или других узлов) предназначен метод getChilNodes (), возвращающий набор данных типа NodeList .
• Метод item () возвращает элемент набора с заданным индексом.
• Метод getLength () возвращает общее количество элементов.
• Методы getFirstChild () и getLastChild () используются для получения первого и последнего дочернего узла.
• Метод getNextSibling () позволяет получить следующий узел того же уровня.
• Метод getAttributes () возвращает карту NameNodeMap с объектами типа Node, описывающими атрибуты.
• Методы getNodeName () и getNodeValue () извлекают имя и значение атрибута соответственно.
• Метод getAttributes ("имя ") извлекает значение атрибута по имени.
Пример 2
• import org.w3c.dom.*;
• import javax.xml.parsers.*;
• public class MyXml {
• public static void main(String[] args) {
• try {
• DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
• DocumentBuilder builder = factory.newDocumentBuilder();
• Document doc = builder.parse("G:\\Haulmont\\java_SE\\config.xml");
• System.out.print("The elements are: ");
• printElements(doc);
• System.out.println("The attributes of each element are: ");
• printElementAttributes(doc);
• } catch (Exception e) { System.out.println(e.toString()); }
• }
• static void printElements(Document doc) {
• NodeList nl = doc.getElementsByTagName("*");
• for (int i = 0; i < nl.getLength(); i++) {
• System.out.print(nl.item(i).getNodeName() + " ");
• }
• System.out.println();
• }
• static void printElementAttributes(Document doc) {
• NodeList nl = doc.getElementsByTagName("*");
• for (int j = 0; j < nl.getLength(); j++) {
• Element e = (Element) nl.item(j);
• System.out.println(e.getTagName() + ":");
• NamedNodeMap nnm = e.getAttributes();
• if (nnm != null) {
• for (int i = 0; i < nnm.getLength(); i++) {
• Node n = nnm.item(i);
• System.out.print(" " + n.getNodeName() + " = " + n.getNodeValue());
• }
• }
• System.out.println();
• } } }
SAX
• Для использования SAX-анализатора необходимо создать обработчик событий, которые происходят во время разбора XML-документа.
• В интерфейсе ContentHandlerопределено несколько методов, к которым обращается анализатор:
§ Методы startElement () и endElement () вызываются при получении открывающего и закрывающего дескрипторов.
§ Метод characters () вызывается при получении символьных данных.
§ Методы startDocument () и endDocument () вызываются в начале и в конце документа.
• Для получения SAX-анализатора используется следующая команда:
SAXParserFactoryfactory = SAXParserFactory . newInstance ();
SAXParser parser = factory.newSAXParser();
• Для обработки документа следует использовать команду:
parser . parse ( source , handler );
Здесь source – это источник входных данных, который может быть файлом, URL или входным потоком;
handler – подкласс класса DefaultHandler , в котором определены методы, объявленные в интерфейсах ContentHandler , DTDHandler , EntityResolver , ErrorHandler .
• Эти методы не выполняют никаких действий.
Пример 3
• import java.io.IOException;
• import javax.xml.parsers.*;
• import org.xml.sax.*;
• import org.xml.sax.helpers.*;
• class CustomSAXParser extends DefaultHandler{
• public void startDocument() throws SAXException {
• System.out.println("Start parse XML...");
• }
• public void startElement(String namespaceURI, String localName,
• String qName, Attributes atts) throws SAXException {
• System.out.println("Start element " + qName + ":");
• }
• public void endElement(String namespaceURI, String localName,
• String qName) throws SAXException {
• System.out.println("End element " + qName + ":");
• }
• public void endDocument() {
• System.out.println("Stop parse XML...");
• }
• public static void main(String[] args) {
• try {
• SAXParserFactory factory = SAXParserFactory.newInstance();
• SAXParser parser = factory.newSAXParser();
• CustomSAXParser custom = new CustomSAXParser();
• parser.parse("G:\\Haulmont\\java_SE\\config.xml", custom);
• } catch (IOException ex) {
• ex.printStackTrace();
• } catch (ParserConfigurationException ex) {
• ex.printStackTrace();
• } catch (SAXException ex) {
• ex.printStackTrace();
• } } }
Создание XML-документов
• Используется пакет javax . xml . transform .
• Удобнее создать древовидную структуру DOM, представляющую документ, а затем записать содержимое этого дерева в файл.
• В первую очередь следует сгенерировать пустой документ с помощью метода newDocument () класса DocumentBuilder
Documentdoc = builder . newDocument ();
• Затем для создания элементов документа нужно применить метод createElement () класса Document
ElementrootElement = doc . createElement ( rootName );
ElementchildElement = doc . createElement ( childName );
• Далее создаем текстовые узлы с помощью метода createTextNode ().
Text textNode = doc.createTextNode(textContents);
• Длявключениявдокументкорневогоэлементаидлясвязываниядочернихузловсродительскимииспользуетсяприведенныйнижекод:
doc.appendChild(rootElement);
rootElement.appendChild(childElement);
childElement.appendChild(textNode);
• Приформированиидерева DOM атрибутыэлементовзадаютсяспомощьюметодаsetAttribute()классаElement
rootElement.setAttribute(name, value);
Для записи дерева DOM в выходной поток к документу применяется преобразование (XSLT-преобразование), в процессе которого не выполняется никаких действий и результат записывается в выходной поток.
• Для включения узла DOCTYPE в состав выходных данных нужно указать в качестве свойств идентификаторы SYSTEM и PUBLIC
Transformer t = Transformer Factory . newInstance (). newTransformer ();
t .setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, system Identifier );
t .setOutputProperty(OutputKeys.DOCTYPE_ PUBLIC , publicIdentifier );
t . transform ( newDOMSource ( doc ), newStreamResult ( new FileOutputStream ( file )));
Пример 4
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import java.io.*;
public class WriteXML {
public static void main(String[] args) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("G:\\Haulmont\\java_SE\\config.xml");
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
FileOutputStream f = new FileOutputStream("G:\\Haulmont\\java_SE\\config1.xml");
t.transform(new DOMSource(doc), new StreamResult (f));
} catch (Exception e) {
e.printStackTrace();
}
}
}
Hibernate
ORM (Object-relational mapping) — это отображение объектов какого-либо объектно-ориентированного языка в структуры реляционных баз данных.
Преимущества ORM
• Нет необходимости писать рутинные insert/update/delete/select для CRUD(create, read, update, delete) операций.
• Условия связи между объектами (строками таблиц) указываются декларативно в одном месте.
• Возможность использовать полиморфные запросы для иерархий классов.
• Высокая степень независимости от конкретной СУБД.
Недостатки ORM
• Возможны проблемы с производительностью для сложных запросов на объектном SQL.
• Затрудняет использование специфических конструкций языка SQL конкретной СУБД.
• Потеря объектно-реляционного соответствия.
ORM-решением для языкаJava является технологияHibernate, которая не только связывает Java классы с таблицами базы данных, но также предоставляет средства для автоматического построения запросов и извлечения данных и может значительно уменьшить время разработки, которое обычно тратится на ручное написание SQL иJDBCкода. Hibernate генерирует SQL вызовы и освобождает разработчика от ручной обработки результирующего набора данных и конвертации объектов.
Mapping (сопоставление, проецирование) Java-классов с таблицами БД осуществляется с помощью конфигурационныхXMLфайлов илиJava-аннотаций. Обеспечиваются возможности по организации отношений между классами «один-ко-многим» и «многие-ко-многим».
Для применения Hibernate на практике во-первых, необходимо описать XMLфайл, содержащий информацию о настройках связи с БД и о способе Mapping.Располагаться он должен в самом корне дерева классов.
Пример 5
Файлhibernate.cfg.xml.
<hibernate-configuration>
<session-factory>
<!-- PostgreSQL connection settings -->
<property name="connection.driver_class">org.postgresql.Driver</property>
<property name="connection.url">jdbc:postgresql://localhost:5433/orm</property>
<property name="connection.username">postgres</property>
<property name="connection.password">sa</property>
<property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hbm2ddl.auto">update</property>
<!-- Other hibernate settings -->
<property name="show_sql">true</property>
<!-- Annotated classes (Mapping from Annotations) -->
<mapping package="org.haulmont.catalog.model"/>
<mapping class="org.haulmont.catalog.model.Shop"/>
<mapping class="org.haulmont.catalog.model.Book"/>
<mapping class="org.haulmont.catalog.model.Magazine"/>
<mapping class="org.haulmont.catalog.model.Author"/>
<!-- Mapping from configuration file (as an alternative to annotations) -->
<!--<mapping resource="mapping.hbm.xml"/>-->
</session-factory>
</hibernate-configuration>
§ connection.driver_classПоказывает класс драйвера, который используется для соединения с базой данных.
§ connection.url –URL для соединения с базой данных.
§ connection.username– логин к базе данных.
§ connection.password– пароль к базе данных.
§ dialect– т.к. Hibernate может работать с разными базами данных, и каждая имеет какие-то особенности (генерация первичного ключа, страничный вывод, функции), нам надо указать, с какой базой мы работаем. В данном случае у нас PostgreSQL, что мы и указываем.
§ hbm2ddl.auto - свойство, которое указывается что нужно сделать со схемой БД при инициализации. Может принимать такие значения:
update - сверяет схему БД с имеющимися конфигурациями классов, если мы внесли какие-то изменения, они автоматически занесуться в БД. При этом данные, которые были занесены в базу не изменятся - даже, если мы решили удалить некоторые поля из таблицы, они все одно останутся;
create - каждый раз при запуске приложения, схема БД будет создаваться наново. Все данные, которые были занесены раньше, будут удалены;
create-drop - каждый раз при запуске приложения, схема БД будет создаваться наново, а при завершении - удаляться. Все данные, которые были занесены во время работы приложения, будут удалены по завершению приложения;
validate - при инициализации будет совершена проверка соответствуют ли конфигурации классов и схема БД. Если мы внесли изменение в конфигурацию какого-то класса, а схема в БД не была изменена, выбросится исключение;
§ show_sql– данное свойство указывает, будут ли выводится SQL-запросы, которые генерит Hibernate на консоль. В процессе отладки это бывает очень удобно.
§ тэг – mapping. Он используется для перечисления всех классов, которые имеют связь с базой данных. Т.е. если вы хотите использовать какой-то класс для связи с какой-то таблицей, вы должны его здесь указать.
Во-вторых, нужноописатьклассы для работы с данными.
Пример 6
§ Класс Shop связан с таблицей SHOP .
§ Первичный ключ – ID, связан со свойством id (функции getId ()/setId ()).
§ Для генерации значений первичного ключа ID используется sequenceSEQ _ ID .
§ Атрибут NAME связан со свойством name (функции getName ()/setName ()).
§ Объекты Shop содержат список Item:
§ связь “один-ко-многим” (@ OneToMany)
§ обязательная (nullable=false)
§ Внешний ключ, определяющий связь – SHOP _ ID .
§ Список Item загружаются по требованию (FetchType . LAZY).
§ При сохранении объекта Shop автоматически сохраняются все его items (CascadeType . ALL).
Рассмотрим подробнее используемые аннотации:
§ @Entity– говорит о том, что данный класс представляет собой сущность, которую надо сохранять в базе данных.
§ @Table– показывает, какая таблица используется для хранения.
§ @Id– говорит о том, что данное поле является идентификатором.
§ @GeneratedValue– аннотация дает указание, что данная величина будет генериться.
§ @Column–аннотация для указания имени столбца, с которым связано поле класса.
§ @JoinColumn – данная анотация по сути похожа на @Column. Только она указывает, что колонка является связующей.
§ @ManyToOne – аннотация указывает, что поле указывает на другой класс, который связан с текущим классом связью многие-к-одному. Здесь также указывается правило каскадаcascade= CascadeType.REFRESH– в упрощенном виде оно гласит “что сделали с тобой, то сделай и со связью. CascadeType.ALLобозначает выполнение каскадных операций при save-update и delete, по умолчанию Hibernate будетигнорировать ассоциации, поэтому “разруливать” зависимости придется самостоятельно. Запись fetch=FetchType.LAZY указывает, что загрузка данного поля будет только в случае обращения к данному полю. Пока программа этого не делает, поле будет пустым.
§ @OneToMany– такая запись говорит о том, что поле служить для связи один-ко-многим (потому и список).
§ @ManyToMany– эта аннотация говорит о том, что поле будет использовано для связи много-ко-многим.
§ @JoinTable– указывает имя таблицы, которая используется для организации связи много-ко-многим. Параметр joinColumns указывает название столбца, который является ссылкой на текущий класс, параметр inverseJoinColumns указывает на колонку, в которой находится ссылка на класс с другой стороны.
В качестве альтернативы аннотациям возможно использование XML-файла с настройками (файл mapping.cfg.xml.). Во-третьих, нужноописатькласс для работы с HibernateAPI.
§ Работая с данными в объектно-ориентированном языке, мы работаем с объектами, заполняя и считывая значения полей, создавая новые или изменяя существующие объекты, определяя зависимости между объектами.
§ При операции save () мы передаем объект типа Shop, который сохраняется в базу данных по описанным правилам отображения. В том числе сохраняются и все зависимые объекты (Item).
§ Составляя запросы к базе данных, мы уже указываем не столбцы таблицы, а свойства объектов.
Обратите внимание на работу с транзакциями: начало транзакции( метод beginTransaction()), подтверждение транзакции (метод commit()), откат транзакции (метод rollback()).
Пример 7, 8
Servlets
Servlet (сервлет) – это класс на Java, расширяющий возможности сервера, к которому происходят обращения в рамках модели «запрос-отклик». Теоретическиможет поддерживать любой тип запросов, но чаще всего используются HTTP-сервлеты.
Servlet container(контейнер сервлета) - контейнер, обеспечивающий сетевые службы, при помощи которых посылаются запросы и ответы, декодируются запросы и форматируются ответы.Все контейнеры сервлетов должны поддерживать HTTPпротокол, но могут также поддерживать дополнительные протоколы, например, HTTPS.
Distributed servlet container (распределенный контейнер сервлета)- контейнер сервлета, запускающий Web-приложения, которые помечены как распределенные и выполняются на нескольких виртуальных машинах Java. При этом виртуальные машины могут быть запущены, как на одном, так и на разных компьютерах.
Servlet context (контекст сервлета) - объект, содержащий представление(вид) Web-приложения,в котором запущен сервлет. Используя контекст, сервлет может вести журнал событий, получать URL-ссылки на ресурсы,а также устанавливать и хранить атрибуты, которые могут использоваться другими сервлетами в приложении.
Servlet mapping (отображение сервлета)- определяет связь между структурой URL и сервлетом. Используется для отображения запросов в сервлеты. Если контейнер, обрабатывающий запрос, является JSP-контейнером, то неявно отображается URL,содержащий расширение.jsp.
Жизненный цикл сервлета
· Если экземпляр сервлета не существует, то контейнер:
1. загружает класс сервлета;
2. создает его экземпляр;
3. вызывает метод init() .
· При получении запроса вызывается метод service(), которому передаются объекты запроса и отклика.
· Если контейнеру требуется удалить объект сервлета, то вызывается метод destroy().
Особенности сервлетов
· Существуют механизмы реагирования на события, связанные с деятельностью сервлетов в приложении:
l javax.servlet. Событие Listener
l javax.servlet. Событие Event
· Для обработки события требуется:
l написать класс, реализующий интерфейс.
l снабдить этот класс аннотацией @ WebListener(пакет javax . servlet . annotation).
· Требуется учитывать то, что сервлет является разделяемым ресурсом и работает с разделяемыми ресурсами.
· Не следует использовать поля класса для хранения состояния, а особенно для передачи состояния между вызовами.
Объект запроса
· Реализует интерфейс javax.servlet.ServletRequest.
· Позволяет узнать характеристики запроса, в том числе значения параметров:
l String getParameter(String name)
l Enumeration getParameterNames()
l и ряд других методов
· Позволяет получить доступ к потоку запроса:
l ServletInputStream getInputStream()
l BufferedReader getReader()
l Можно вызвать только один из этих двух методов
· Позволяет получить параметры запроса
l int getContentLength()
l String getContentType()
l String getProtocol()
l и т.д.
Объект отклика
· Реализует интерфейс javax.servlet.ServletResponse
· Основные методы:
l ServletOutputStream getOutputStream()
Далее для вывода используются обычные средства бинарного вывода
l PrintWriter getWriter()
Далее для вывода используются обычные средства символьного вывода
l Можно вызвать только один из этих двух методов.
· Позволяет установить параметры отклика
l Для установки типа отклика используется метод setContentType ()
l Для установки кодировки используется метод setCharacterEncoding ()
l Сбрасывает текущий буфер клиентуflushBuffer ()
l Очищает буфер и сбрасывает статус reset ()
HTTP Servlet
· javax.servlet.http.HttpServlet - абстрактный класс, позволяющий создавать сервлеты, удобные для Web.
· Наследные классы должны переопределять хотя бы один из методов обработки запроса.
· Обычно это один из методов:
l void doGet(HttpServletRequest req, HttpServletResponse resp)
l void doPost(HttpServletRequest req, HttpServletResponse resp)
· Классы снабжаются аннотацией @WebServlet.
Пример 9. Класс сервлета
importjava.io.*;
importjavax.servlet.*;
importjavax.servlet.http.*;
importjavax.servlet.annotation.*;
@WebServlet("/MyServlet.html")
public class MyServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
PrintWriter out = response.getWriter();
try {
out.print("<html><body>This is text document, which has "
+ "<a href=\"other.html\">link</a>"
+ " to another document</body></html>");
}
finally {
out.close(); }
}
}
Поддержка сессий
· В HTTP-сервлетах в объектах запроса и отклика добавляются дополнительные методы.
· Среди них появляются методы работы с сессиями, включая работу с Cookies(англ. печенье) - небольшой фрагмент данных, отправленный веб-сервером и хранимый на компьютере пользователя. Веб-клиент (обычно веб-браузер) всякий раз при попытке открыть страницу соответствующего сайта пересылает этот фрагмент данных веб-серверу в составе HTTP-запроса. Применяется для сохранения данных на стороне пользователя, на практике обычно используется для аутентификации пользователя, хранения персональных предпочтений и настроек пользователя, отслеживания состояния сеанса доступа пользователя, ведения статистики опользователях.
· Для передачи значений между запросами можно использовать атрибуты сессии.
l HttpSession.getAttribute(String name)
l HttpSession.setAttribute(String name, Object value)
l И ряд других методов
Пример 1 0 .
public class CashierServlet extends HttpServlet {
public void doGet (HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Get the user's session and shopping cart
HttpSession session = request.getSession();
ShoppingCart cart =(ShoppingCart)session.getAttribute("cart");
//...
}
}
out.println("<a href=\"" +
response.encodeURL(request.getContextPath() +
"/bookcatalog") + "\">");
Дата: 2019-02-19, просмотров: 348.