Начнем с того, где мы будем хранить наш код и как обмениваться им с друзьями. Думаю, не все начинающие знают про репозитории, и эта часть именно для них.
После всего этого у Вас будет ссылка на Ваше пространство. Чтобы понять, что это такое - нужно взять один из ваших проектов (или создайте какой нибудь пустой проект в NetBeans). Нажимаете на нем правой кнопочкой и у Вас в меню будет доступно «Управление версиями» -> «импортировать в репозиторий Subversion». После этого будет диалоговое окно, в котом будет путь к репозиторию - это ссылка которую Вы получили на сайте во вкладке «Исходный код».
Далее, полностью удалите проект, который вы закоммитили. Дальше зайдите в папку, где у вас проекты хранятся, и проверьте что реально все удалено. Потом возвращаетесь в NetBeans и ищете в панели меню вкладку Группа(на панели где Файл, Вид, Правка, Переход, Источник...) в нем есть наш Subversion. И в подменю на нем есть «Получить». Дальше в диалоговых окнах надо будет указать ссылку на репозиторий (это ссылка которую вы получили на сайте во вкладке «Исходный код».) И когда он предложит выкачивать папки, то по дереву репозитория нужно будет найти ваш проект и выбрать его, и по окончанию вы выкачаете свой проект. Вот так происходит обмен кодом.
Ваш проект будет постоянно синхронизироваться с репозиторием и помечать файлы, которые были изменены, или новые(то что отличается от версии на репозитории). Чтобы обновить, нужно вызвать контекстное меню, и в закладке «Управление Версиями» будет большой список того, что можно делать с проектом. «Обновлять» - это обновить свои файлы; «Фиксировать» - ложить код который Вы написали или изменили в репозиторий; «Сбрасывать» - возвращаться к версии на репозитории, и «Сравнивать» - отображение изменений строк которые отличаются от удаленных. Это способ командного обмена кодом, который используется всегда и нужно к нему привыкать.
Вы уже скачали NetBeans, поигрались с SVN - теперь перейдем к делу. Создаете проект. Нажимаете «Создать проект», там выбираете Maven-> Веб-приложение. Называете как хотите, это все Ваша фантазия. Итак, у нас есть веб-приложение, сборка нашего проекта идет мавеном, у нас есть цель и теперь наступило время подумать над тем, как ее осуществить. То есть Вы, как разработчик, должны подумать над тем, как будет выглядеть Ваше приложение, какую иметь архитектуру, дерево пакетов и так далее. Общее количество строк кода здесь около 4000 и лучше позаботиться о красивой архитектуре заранее, иначе потом Вы просто не будете понимать что где и как у Вас работает, каким чудом Вы, к примеру, выводите последнюю купленную вещь, как считаете общую сумму покупок. И если Вас потом попросят что-то доделать или добавить - Вы осознаете что проще написать все с нуля.
Ну и конечно нам нужно прикинуть наш план действий.
2) Создаем HibernateUtil (вообще суффикс или приставка Util подразумевает, что код в этом классе есть универсальный и используется множеством классов).
Итак, в HibernateUtil мы размещаем SessionFactory. Он тяжеловесный. Этот код, по идее, должен быть независим от всего приложения, так как он устанавливает соединение с базой данных при старте и должен нам давать только Сессии с базой данных. Еще мы в этом классе регистрируем наши классы-сущности. Подробнее про этот класс расскажу позже. Засунем его тоже в отдельный пакет, к примеру, edu.shop.model.hbutil.HibernateUtil.java
3) Пишем DAO.
Что в нем писать? Пишем то, что мы хотим получить от базы данных, но нам не нужно думать как получились эти данные, важен результат. К примеру, мы определяем интерфейс ProductDAO и пишем в нем методы
List
В чем идея? Если бы это приложение писал я и Вы, Вы бы сказали: «Миха, мне нужны от БД следующие данные: все товары что у меня есть в БД». Я отвечаю: «не вопрос». И далее следующее развитие событий: вы в своем коде, везде где нужно делать запросы к базе пишете следующее%
*здесь обращение к методу*.getAllProducts(); - и видите, что компилятор не ругается, а реализацию этого интерфейса я мог еще не успеть написать. И какой итог? У Вас все скомпилилось, а рабочего кода даже нет. Здесь мы применим Enums и паттерн Factory, и еще кое-что, но всему свое время. Именно в DAO нужно уделить особое внимание обработке исключений, хотя бы генерировать страницы с ошибками. Чтобы Вы быстро находили кусок неработающего кода. Иначе, Вы просто замучаетесь с отладкой.
3)Здесь начнется наша работа с Spring MVC. Это долгая история и этому будет посвящена отдельная статья. Сразу скажу - это самое сложное в этом приложении. Но я Вам покажу и более простой вариант, как выводить все, не особо заботясь про паттерн MVC.
Затронем использование скриплетов.
4) Здесь у нас будут вспомогательные классы, добавляющие всякие вкусности в наш проект: подсчет общей суммы покупок; последняя купленная вещь; вспомогательные переменные, которые пригодятся нам для работы метода, который, к примеру, будет выводить нам с БД вещи не дороже 5000 грн, или не дешевле 500; вывод всех ноутбуков марки Асус. Этот пункт тесно взаимосвязан с предыдущим.
Пока остановимся на этом. С остальным разберемся чуть позже. Итак, у нас есть намеченный план, приступим к его реализации.
Примечание. Корзина, в которой будут храниться наши купленные товары, будет как таблица в БД, это я сделал т.к на ней покажу некоторые основы работы с БД. Для реального случая целесообразнее будет использовать коллекции для хранения наших товаров.
1) Product
2) Notebook
3) Camera
4) Book
5) Cable
6) Customer
7) Cart
Поговорим немного о том, что такое класс-сущность.
Entity (Сущность) - POJO-класс, связанный с БД с помощью аннотации (@Entity) или через XML. К такому классу предъявляются следующие требования:
Должен иметь пустой конструктор (public или protected);
- Не может быть вложенным, интерфейсом или enum;
- Не может быть final и не может содержать final-полей/свойств;
- Должен содержать хотя бы одно @Id-поле.
При этом entity может:
Entities могут быть связаны друг с другом: один-к-одному, один-ко-многим, многие-к-одному и многие-ко-многим.
Использовать мы будем аннотации. И тут сразу у нас появляется возможность описать двумя способами. Либо мы будем писать аннотации непосредственно над полями, либо над геттерами. Скажу одно: правильно писать над геттерами, а причину Вы спросите в гугле. Не могу я все темы абсолютно здесь описать.
Есть еще одно что хочу сказать. Для этого придется показать 2 примера описания класса сущности. Итак, первый пример:
Коментарии к нему я написал в самом коде:
Import java.io.Serializable; import javax.persistence.*; import javax.validation.constraints.Size; /** * * @author Mikhail Shumenko */ @Entity //Этой аннотацией мы указываем, что данный класс является сущностью. @Table(name = "CART")// Этой аннотацией мы указываем, что за эту сущность в БД отвечает таблица с именем CART //Хочу отметить, что регистр не важен, эту анотацию можно не указывать, тогда хибернейт создаст нам БД с //именем как у класса public class CartEntity implements Serializable { //Здесь мы пишем аннотации над полями. Правильно писать над геттерами //Описываем Id таблицы @Id //Указываем, что это поле класса отвечает за столбец в таблице с именем Id //Если мы его указывать не будем, хибернейт создаст столбец с именем как у поля. @Column(name = "ID") //Здесь написать можно много)) Почему я написал здесь так? В общем можно в //@GeneratedValue(strategy=GenerationType.вместо TABLE написать AUTO) тогда //при первой загрузке таблицы, Id сгенерируются автоматически от 1 до своего максимального значения. //Если у вас 20 вещей в таблице, то сгенерируется от 1 до 20. //Но при последующих добавлениях, id у добавленной вещи будет примерно таким - 345768. //Я написал все так, чтобы последний мой id хранился в таблице и генерировался потом адекватно при последующих добавлениях. //Также есть SEQUENCE, но он не поддерживается в Derby, а работать мы будем именно с ней. //В общем, это нюансы. Можете узнать про них самостоятельно @TableGenerator(name = "cartid", table = "cartpktb", pkColumnName = "idCart", pkColumnValue = "idCartValue",allocationSize = 1) @GeneratedValue (strategy = GenerationType.TABLE, generator = "cartid") private Integer id; //Указываем максимальный размер. Это строка из 25 символов. @Size(max = 25) @Column(name = "NAMEITEM") //Если тип нашего поля String, то и создаваться будет столбец с типом VARCHAR(в Derby) //Если Integer, то будет столбец, в который поместить можно только Integer //boolean в Derby - это столбец с типом SMALLINT private String nameItem; @Column(name = "PRICE") private Integer price; public CartEntity() { } public CartEntity(String nameItem, int price) { this.nameItem = nameItem; this.price = price; } public CartEntity(Integer id,String nameItem, int price) { this.id=id; this.nameItem = nameItem; this.price = price; } public CartEntity(Integer id) { this.id = id; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getNameItem() { return nameItem; } public void setNameItem(String nameItem) { this.nameItem = nameItem; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } }
Итак, у Вас есть два примера классов сущностей. Создайте остальные, используя эти примеры. Такие поля как: модель, год публикации, имя, стоимость - все на Вашу фантазию. Включите обязательно поле Available(в переводе наличие). Оно Вам потом пригодится. Можете сделать его булевым и добавить столбец с именем количество. Это все нам пригодится.
Его смысл:
- Весь доступ к базе данных в системе производится через DAO для инкапсуляции.
- Каждый экземпляр DAO отвечает за один первичный доменный объект или сущность. Если доменный объект имеет независимый цикл жизни, он должен иметь свой собственный DAO.
- DAO отвечает за операции создания, чтения (по первичному ключу), обновления и удаления (то есть, CRUD (create, read, update, delete)) доменного объекта.
- DAO может разрешать запросы, основанные на критерии, отличном от первичного ключа. Я ссылаюсь на такие методы как finder или finders. Метод finder обычно возвращает коллекцию доменных объектов, за которые отвечает DAO.
- DAO не занимается обработкой транзакций, сессий или соединений. Это делается вне DAO для обеспечения гибкости.
Подробнее всегда расскажет гугл.
Мы пока напишем DAO для наших продуктов.
Итак, подумаем что нам вообще нужно. Таблица Product будет иметь 4 поля Id,nameProduct,available+amount+actionForServlet. Она нам будет нужна, чтобы создать на нашем сайте категории. Над последним полем пока не заморачиваемся. Единственное что нам нужно - это получение списка продуктов.
Пишем интерфейс
public interface ProductDAO {
ProductDAO INSTANCE_PRODUCT= new ProductDAOImpl();
List
Реализация нашего интерфейса. Пояснения смотрим в коде
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package edu.shop.model.dao;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
/**
*
* @author Mikhail Shumenko
*/
public class ProductDAOImpl implements ProductDAO {
@Override
public List
Итак, теперь у нас есть возможность получать данные из БД. Вы можете, используя скриплеты, создать незамысловатый цикл for-each и вывести свою продукцию на вашу страницу index.jsp
Категория | //INSTANCE_PRODUCT что это такое? //В ProductDAO описана такая переменная, отвечает за создание ProductDAOImpl //Ну у нас все будет по-другому, можете особо не запоминать это. //ProductDAO INSTANCE_PRODUCT= new ProductDAOImpl(); <% for (Product product:ProductDAO.INSTANCE_PRODUCT.getProducts()) {%>"><%=product.getName()%> | <%}%>
---|---|
Наличие | <% for (Product product: ProductDAO.INSTANCE_PRODUCT.getProducts()) {%><%=product.getAvailable()%> | <%}%>
Но это на первое время, а вообще так делать плохо. Это нарушает наш паттерн MVC. Как сделать правильно я объясню в следующем уроке, если мне дадут инвайт. Во втором уроке мы займемся Spring, в третьем коснемся паттерна Factory, и углубимся в хибернейт. Для особо нетерпеливых, покажу как нужно удалять из БД, сохранять в БД и удалять полностью все из БД. Ну, а как сделать, чтобы все это взаимодействовало в целом с нашим приложением и подробное рассмотрение оставим на потом.
Также Вам нужен будет файл настройки Hibernate. Создайте в Derby БД shop. Имя и пароль пользователя root и pass соответственно. Если не получится - не расстраивайтесь - я уделю еще этому время.
О том, как заполнять наши БД поговорим позже. Можете заполнить их вручную. Либо дождаться следующего урока.
В отличие от сервлетов, требующих компиляции java-файла для получения класса (файла *.class) jsp страница не требует компиляции и регистрации в дескрипторе поставки web.xml .
Контейнер сервлетов расширили препроцессором, переводящим запись JSP страницы в сервлет . Препроцессор обрабатывает страницу JSP автоматически при первом обращении к ней. Полученный в результате его работы сервлет тут же компилируется и выполняется. Откомпилированный сервлет затем сохраняется в WEB-контейнере также, как и все сервлеты, и выполняется при последующих вызовах страницы JSP.
Рассмотрим простой пример, в котором на JSP странице приветствия будут отображены текущая дата и время. Для разработки будет использована IDE Eclipse. На следующем скриншоте представлено определение типа проекта Dynamic Web Project .
Определим наименование проекта как HelloJSP и создадим в проекте файл index.jsp . Структура проекта представлена на следующем скриншоте.
В дескрипторе приложения web.xml в качестве страницы приветствия определен JSP файл index.jsp .
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.util.*, java.text.*" %> <%! String getFormattedDate() { SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy hh:mm:ss"); return sdf.format(new Date()); } %>
Начнем с того, где мы будем хранить наш код и как обмениваться им с друзьями. Думаю, не все начинающие знают про репозитории, и эта часть именно для них.
После всего этого у Вас будет ссылка на Ваше пространство. Чтобы понять, что это такое - нужно взять один из ваших проектов (или создайте какой нибудь пустой проект в NetBeans). Нажимаете на нем правой кнопочкой и у Вас в меню будет доступно «Управление версиями» -> «импортировать в репозиторий Subversion». После этого будет диалоговое окно, в котом будет путь к репозиторию - это ссылка которую Вы получили на сайте во вкладке «Исходный код».
Далее, полностью удалите проект, который вы закоммитили. Дальше зайдите в папку, где у вас проекты хранятся, и проверьте что реально все удалено. Потом возвращаетесь в NetBeans и ищете в панели меню вкладку Группа(на панели где Файл, Вид, Правка, Переход, Источник...) в нем есть наш Subversion. И в подменю на нем есть «Получить». Дальше в диалоговых окнах надо будет указать ссылку на репозиторий (это ссылка которую вы получили на сайте во вкладке «Исходный код».) И когда он предложит выкачивать папки, то по дереву репозитория нужно будет найти ваш проект и выбрать его, и по окончанию вы выкачаете свой проект. Вот так происходит обмен кодом.
Ваш проект будет постоянно синхронизироваться с репозиторием и помечать файлы, которые были изменены, или новые(то что отличается от версии на репозитории). Чтобы обновить, нужно вызвать контекстное меню, и в закладке «Управление Версиями» будет большой список того, что можно делать с проектом. «Обновлять» - это обновить свои файлы; «Фиксировать» - ложить код который Вы написали или изменили в репозиторий; «Сбрасывать» - возвращаться к версии на репозитории, и «Сравнивать» - отображение изменений строк которые отличаются от удаленных. Это способ командного обмена кодом, который используется всегда и нужно к нему привыкать.
Вы уже скачали NetBeans, поигрались с SVN - теперь перейдем к делу. Создаете проект. Нажимаете «Создать проект», там выбираете Maven-> Веб-приложение. Называете как хотите, это все Ваша фантазия. Итак, у нас есть веб-приложение, сборка нашего проекта идет мавеном, у нас есть цель и теперь наступило время подумать над тем, как ее осуществить. То есть Вы, как разработчик, должны подумать над тем, как будет выглядеть Ваше приложение, какую иметь архитектуру, дерево пакетов и так далее. Общее количество строк кода здесь около 4000 и лучше позаботиться о красивой архитектуре заранее, иначе потом Вы просто не будете понимать что где и как у Вас работает, каким чудом Вы, к примеру, выводите последнюю купленную вещь, как считаете общую сумму покупок. И если Вас потом попросят что-то доделать или добавить - Вы осознаете что проще написать все с нуля.
Ну и конечно нам нужно прикинуть наш план действий.
2) Создаем HibernateUtil (вообще суффикс или приставка Util подразумевает, что код в этом классе есть универсальный и используется множеством классов).
Итак, в HibernateUtil мы размещаем SessionFactory. Он тяжеловесный. Этот код, по идее, должен быть независим от всего приложения, так как он устанавливает соединение с базой данных при старте и должен нам давать только Сессии с базой данных. Еще мы в этом классе регистрируем наши классы-сущности. Подробнее про этот класс расскажу позже. Засунем его тоже в отдельный пакет, к примеру, edu.shop.model.hbutil.HibernateUtil.java
3) Пишем DAO.
Что в нем писать? Пишем то, что мы хотим получить от базы данных, но нам не нужно думать как получились эти данные, важен результат. К примеру, мы определяем интерфейс ProductDAO и пишем в нем методы
List
В чем идея? Если бы это приложение писал я и Вы, Вы бы сказали: «Миха, мне нужны от БД следующие данные: все товары что у меня есть в БД». Я отвечаю: «не вопрос». И далее следующее развитие событий: вы в своем коде, везде где нужно делать запросы к базе пишете следующее%
*здесь обращение к методу*.getAllProducts(); - и видите, что компилятор не ругается, а реализацию этого интерфейса я мог еще не успеть написать. И какой итог? У Вас все скомпилилось, а рабочего кода даже нет. Здесь мы применим Enums и паттерн Factory, и еще кое-что, но всему свое время. Именно в DAO нужно уделить особое внимание обработке исключений, хотя бы генерировать страницы с ошибками. Чтобы Вы быстро находили кусок неработающего кода. Иначе, Вы просто замучаетесь с отладкой.
3)Здесь начнется наша работа с Spring MVC. Это долгая история и этому будет посвящена отдельная статья. Сразу скажу - это самое сложное в этом приложении. Но я Вам покажу и более простой вариант, как выводить все, не особо заботясь про паттерн MVC.
Затронем использование скриплетов.
4) Здесь у нас будут вспомогательные классы, добавляющие всякие вкусности в наш проект: подсчет общей суммы покупок; последняя купленная вещь; вспомогательные переменные, которые пригодятся нам для работы метода, который, к примеру, будет выводить нам с БД вещи не дороже 5000 грн, или не дешевле 500; вывод всех ноутбуков марки Асус. Этот пункт тесно взаимосвязан с предыдущим.
Пока остановимся на этом. С остальным разберемся чуть позже. Итак, у нас есть намеченный план, приступим к его реализации.
Примечание. Корзина, в которой будут храниться наши купленные товары, будет как таблица в БД, это я сделал т.к на ней покажу некоторые основы работы с БД. Для реального случая целесообразнее будет использовать коллекции для хранения наших товаров.
1) Product
2) Notebook
3) Camera
4) Book
5) Cable
6) Customer
7) Cart
Поговорим немного о том, что такое класс-сущность.
Entity (Сущность) - POJO-класс, связанный с БД с помощью аннотации (@Entity) или через XML. К такому классу предъявляются следующие требования:
Должен иметь пустой конструктор (public или protected);
- Не может быть вложенным, интерфейсом или enum;
- Не может быть final и не может содержать final-полей/свойств;
- Должен содержать хотя бы одно @Id-поле.
При этом entity может:
Entities могут быть связаны друг с другом: один-к-одному, один-ко-многим, многие-к-одному и многие-ко-многим.
Использовать мы будем аннотации. И тут сразу у нас появляется возможность описать двумя способами. Либо мы будем писать аннотации непосредственно над полями, либо над геттерами. Скажу одно: правильно писать над геттерами, а причину Вы спросите в гугле. Не могу я все темы абсолютно здесь описать.
Есть еще одно что хочу сказать. Для этого придется показать 2 примера описания класса сущности. Итак, первый пример:
Коментарии к нему я написал в самом коде:
Import java.io.Serializable; import javax.persistence.*; import javax.validation.constraints.Size; /** * * @author Mikhail Shumenko */ @Entity //Этой аннотацией мы указываем, что данный класс является сущностью. @Table(name = "CART")// Этой аннотацией мы указываем, что за эту сущность в БД отвечает таблица с именем CART //Хочу отметить, что регистр не важен, эту анотацию можно не указывать, тогда хибернейт создаст нам БД с //именем как у класса public class CartEntity implements Serializable { //Здесь мы пишем аннотации над полями. Правильно писать над геттерами //Описываем Id таблицы @Id //Указываем, что это поле класса отвечает за столбец в таблице с именем Id //Если мы его указывать не будем, хибернейт создаст столбец с именем как у поля. @Column(name = "ID") //Здесь написать можно много)) Почему я написал здесь так? В общем можно в //@GeneratedValue(strategy=GenerationType.вместо TABLE написать AUTO) тогда //при первой загрузке таблицы, Id сгенерируются автоматически от 1 до своего максимального значения. //Если у вас 20 вещей в таблице, то сгенерируется от 1 до 20. //Но при последующих добавлениях, id у добавленной вещи будет примерно таким - 345768. //Я написал все так, чтобы последний мой id хранился в таблице и генерировался потом адекватно при последующих добавлениях. //Также есть SEQUENCE, но он не поддерживается в Derby, а работать мы будем именно с ней. //В общем, это нюансы. Можете узнать про них самостоятельно @TableGenerator(name = "cartid", table = "cartpktb", pkColumnName = "idCart", pkColumnValue = "idCartValue",allocationSize = 1) @GeneratedValue (strategy = GenerationType.TABLE, generator = "cartid") private Integer id; //Указываем максимальный размер. Это строка из 25 символов. @Size(max = 25) @Column(name = "NAMEITEM") //Если тип нашего поля String, то и создаваться будет столбец с типом VARCHAR(в Derby) //Если Integer, то будет столбец, в который поместить можно только Integer //boolean в Derby - это столбец с типом SMALLINT private String nameItem; @Column(name = "PRICE") private Integer price; public CartEntity() { } public CartEntity(String nameItem, int price) { this.nameItem = nameItem; this.price = price; } public CartEntity(Integer id,String nameItem, int price) { this.id=id; this.nameItem = nameItem; this.price = price; } public CartEntity(Integer id) { this.id = id; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getNameItem() { return nameItem; } public void setNameItem(String nameItem) { this.nameItem = nameItem; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } }
Итак, у Вас есть два примера классов сущностей. Создайте остальные, используя эти примеры. Такие поля как: модель, год публикации, имя, стоимость - все на Вашу фантазию. Включите обязательно поле Available(в переводе наличие). Оно Вам потом пригодится. Можете сделать его булевым и добавить столбец с именем количество. Это все нам пригодится.
Его смысл:
- Весь доступ к базе данных в системе производится через DAO для инкапсуляции.
- Каждый экземпляр DAO отвечает за один первичный доменный объект или сущность. Если доменный объект имеет независимый цикл жизни, он должен иметь свой собственный DAO.
- DAO отвечает за операции создания, чтения (по первичному ключу), обновления и удаления (то есть, CRUD (create, read, update, delete)) доменного объекта.
- DAO может разрешать запросы, основанные на критерии, отличном от первичного ключа. Я ссылаюсь на такие методы как finder или finders. Метод finder обычно возвращает коллекцию доменных объектов, за которые отвечает DAO.
- DAO не занимается обработкой транзакций, сессий или соединений. Это делается вне DAO для обеспечения гибкости.
Подробнее всегда расскажет гугл.
Мы пока напишем DAO для наших продуктов.
Итак, подумаем что нам вообще нужно. Таблица Product будет иметь 4 поля Id,nameProduct,available+amount+actionForServlet. Она нам будет нужна, чтобы создать на нашем сайте категории. Над последним полем пока не заморачиваемся. Единственное что нам нужно - это получение списка продуктов.
Пишем интерфейс
public interface ProductDAO {
ProductDAO INSTANCE_PRODUCT= new ProductDAOImpl();
List
Реализация нашего интерфейса. Пояснения смотрим в коде
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package edu.shop.model.dao;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
/**
*
* @author Mikhail Shumenko
*/
public class ProductDAOImpl implements ProductDAO {
@Override
public List
Итак, теперь у нас есть возможность получать данные из БД. Вы можете, используя скриплеты, создать незамысловатый цикл for-each и вывести свою продукцию на вашу страницу index.jsp
Категория | //INSTANCE_PRODUCT что это такое? //В ProductDAO описана такая переменная, отвечает за создание ProductDAOImpl //Ну у нас все будет по-другому, можете особо не запоминать это. //ProductDAO INSTANCE_PRODUCT= new ProductDAOImpl(); <% for (Product product:ProductDAO.INSTANCE_PRODUCT.getProducts()) {%>"><%=product.getName()%> | <%}%>
---|---|
Наличие | <% for (Product product: ProductDAO.INSTANCE_PRODUCT.getProducts()) {%><%=product.getAvailable()%> | <%}%>
Но это на первое время, а вообще так делать плохо. Это нарушает наш паттерн MVC. Как сделать правильно я объясню в следующем уроке, если мне дадут инвайт. Во втором уроке мы займемся Spring, в третьем коснемся паттерна Factory, и углубимся в хибернейт. Для особо нетерпеливых, покажу как нужно удалять из БД, сохранять в БД и удалять полностью все из БД. Ну, а как сделать, чтобы все это взаимодействовало в целом с нашим приложением и подробное рассмотрение оставим на потом.
Также Вам нужен будет файл настройки Hibernate. Создайте в Derby БД shop. Имя и пароль пользователя root и pass соответственно. Если не получится - не расстраивайтесь - я уделю еще этому время.
О том, как заполнять наши БД поговорим позже. Можете заполнить их вручную. Либо дождаться следующего урока.
JavaServer Pages (JSP) позволяют вам отделить динамическую часть ваших страниц от статического HTML. Вы, как обычно, пишете обычный код в HTML, используя для этого любую программу для создания Web страниц. Затем вы заключаете динамическую часть кода в специальные таги, большинство которых начинаются с " <% " и завершаются " %> ". В качестве примера рассмотрим секцию JSP страницы, результатом которой будет что-то вроде "Спасибо за покупку Core Web Programming " по запросу с URL: http://host/OrderConfirmation.jsp?title=Core+Web+Programming:
Спасибо за покупку <%= request.getParameter("title") %>
Вы даете вашему файлу расширение.jsp и размещаете там же, где должны размещаться обычные Web страницы. Хотя то что вы написали больше похоже на обычный HTML файл чем на сервлет, просто за кадром JSP страница преобразуется в обычный сервлет с статическим HTML который просто направляется в поток вывода, связанный с методом сервлета service . Обычно это происходит при первом запросе страницы, и разработчики могут сразу после установки сами выполнить этот запрос, если хотят чтобы первый реальный пользователь при обращении к странице не столкнулся с небольшой задержкой, вызванной трансляцией JSP страницы в сервлет и его последующей компиляцией и загрузкой. Также отметим что большинство Web серверов позволяет вам задавать ссылки (aliases), так что адрес URL, указывающий на HTML файл в действительности будет указывать на сервлет или страницу JSP.
Помимо стандартных HTML конструкций существуют еще три основных типа конструкций JSP, котрые вы можете включить в страницу: элементы скриптов, директивы и действия. Элементы скриптов позволяют вам указать код на языке Java, который впоследствии станет частью в конечный сервлет, директивы дадут вам возможность управлять всей структурой сервлета, а действия служат для задания существующих используемых компонентов, а также для контроля поведением движка JSP. Для упрощения элементов скриптов, вы имеете доступ к нескольким заранее определенным переменным, таким, например, как переменная request , использованная в приведенном выше отрывке.
Обратите внимание что это руководство охватывает JSP версии 1.0. А начиная с версии 0.92 JSP претерпела множество изменений, и несмотря на то что эти изменения были лишь во благо, вы должны помнить что JSP версии 1.0 практически полностью не совместима с более ранними JSP движками. Также следует не забывать о том, что предлагаемое вашему вниманию руководство является частью более полного руководства по сервлетам и JSP доступного по адресу http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/ .
Элемент JSP | Синтаксис | Описание | Примечание |
---|---|---|---|
Выражение JSP | <%= выражение %> | Выражение обрабатывается и направляется на вывод | Эквивалент на XML: expression |
Скриплет JSP | <% код %> | Код добавляется в метод service. | Эквивалент на XML: код |
Объявление JSP | <%! код %> | Код добавляется в тело класса сервлета, вне метода service. | Эквивалент на XML: код |
Директива JSP page | <%@ page att="значение" %> | Директивы для движка сервлета с информацией об основных настройках. | Эквивалент на XML: import="пакет.class " contentType="MIME-Type " isThreadSafe="true |false " session="true |false" buffer="размер kb|none" autoflush="true |false" extends="пакет.class " info="сообщение" errorPage="url " isErrorPage="true|false " language="java" |
Директива JSP include | <%@ include file="url" %> | Файл в локальной системе, подключаемый при трансляции JSP в сервлет. | Эквивалент на XML: URL должен быть относительным. Для подключения файла в процессе запроса а не в ходе трансляции используйте действие jsp:include. |
Комментарий JSP | <%-- комментарий --%> | Комментарий; игнорируется при трансляции JSP страницы в сервлет. | Если вы хотите чтобы комментарий сохранился в конечном HTML, используйте обычный синтаксис HTML для описания комментариев: <-- комментарий -->. |
Действие jsp:include | Подключает файл при запросе страницы. | Если вы хотите чтобы файл подключался в процессе трансляции страницы, используйте директиву page совместно с атрибутом include. Внимание: некоторые сервера требуют чтобы подключаемые файлы были в формате HTML или JSP, в зависимости от настроек сервера (обычно данное ограничение базируется на указании расширений файлов). | |
Действие jsp:useBean | ... | Найти или создать Java Bean. | Возможные атрибуты:
id="имя " scope="page |request|session|application" class="пакет.class " type="пакет.class " beanName="пакет.class " |
Действие jsp:setProperty | Устанавливает свойства bean, или явно, или указанием на соответствующее значение параметра, передаваемое при запросе. | Допустимые атрибуты:
name="имяBean " property="имяСвойства |*" param="имяПараметра " value="значение " |
|
Действие jsp:getProperty | value="значение "/> | Получение и вывод свойств bean. | |
Действие jsp:forward | Передает запрос другой странице. | ||
Действие jsp:plugin |
... | Генерирует тэги OBJECT или EMBED, в зависимости от типа броузера, в котором будет выполнятся апплет использующий Java Plugin. |
Как правило большую часть вашей JSP страницы составляет статический HTML, называемый текстом шаблона . Во всех отношениях (кроме одного) этот HTML выглядит как обычный HTML, использующий те же правила синтаксиса, и он просто "передается" клиенту сервлетом, создаваемым для обработки страницы. При этом не только сам HTML выглядит нормальным, он может создаваться с применением тех инструментов, которые вы ранее использовали при создании Web страниц. Я, например, при создании большинства JSP страниц для этого руководства использовал Allaire"s HomeSite.
Единственным печальным исключением из правила что "текст шаблона передается в неизменном виде" является ситуация, когда в тексте вы хотите отобразить последовательность символов " <% ", для этого в тексте шаблона надо использовать сочетание символов " <\% ".
Элементы скриптов JSP позволяют вам вставлять код на Java в сервлет, создаваемый из текущей JSP страницы. Существуют три формы:
Выражения JSP применяются для того чтобы вставить значения Java непосредственно в вывод. Для этого используется следующая форма:
<%= Выражение на Java %>Выражения Java вычисляются, конвертируются в строку и вставляются в страницу. Эти вычисления происходит во время выполнения (то есть при при запросе страницы), а потому существует полный доступ к информации о самом запросе. Например, следующий код служит для отображения даты и времени запроса данной страницы:
Текущее время: <%= new java.util.Date() %>
Для того чтобы упростить эти выражения существует несколько заранее определенных переменных, которые вы можете использовать. Более детально они будут рассмотрены ниже, но тем не менее, рассматривая их применение при использовании выражений, приведем несколько наиболее важных:
Request , HttpServletRequest ;
response , HttpServletResponse ;
session , HttpSession ассоциируется с запросом (если таковой имеется);
out , PrintWriter
(буферизированный вариант типа JspWriter)
используется для отсылки выводимых
данных клиенту.
Пример: Имя вашего хоста: <%= request.getRemoteHost() %>
И, наконец, авторы, использующие XML, могут
применить альтернативный синтаксис для
выражений JSP:
Помните, что элементы XML в отличие от HTML чувствительны к регистру. Поэтому убедитесь в том, что используете строчные символы.
Если вы хотите сделать что-то большее чем вставка простых выражений, скриплеты JSP дадут вам возможность вставить любой код в метод сервлета, который будет создан при обработке данной страницы. Скриплеты имеют следующий вид:
<% Код на Java %>Скриплеты также имеют доступ к тем же автоматически определенным переменным, что и выражения. Поэтому, например, если вы хотите вывести что-нибудь на страницу, вы должны воспользоваться переменной out .
<% String queryData = request.getQueryString(); out.println("Дополнительные данные запроса: " + queryData); %>
Обратите внимание на то, что код внутри скриплета вставляется в том виде, как он записан, и весь статический HTML (текст шаблона) до или после скриплета конвертируется при помощи оператора print . Это означает что скриплеты не обязательно должны содержать завершенные фрагменты на Java, и что оставленные открытыми блоки могут оказать влияние на статический HTML вне скриплета. Например, следующий фрагмент JSP содержит смешанный текст шаблона и скриплеты:
<% if (Math.random() < 0.5) { %> Удачного Вам дня! <% } else { %> Не удачного Вам дня! <% } %> после преобразования приведет к чему-то вроде: if (Math.random() < 0.5) { out.println("Удачного вам дня!"); } else { out.println("Не удачного вам дня!"); }
Если вы хотите использовать последовательность символов " %> " внутри скриплета, вместо нее используйте " %\> ". Эквивалентом <% Код %> для XML является:
Объявления JSP позволят вам задать методы или поля, для вставки в тело класса сервлета (вне метода service , обрабатывающего запрос). Они имеют следующую форму:
<%! Код на Java %>Поскольку объявления не осуществляют вывода, обычно они используются совместно с JSP выражениями или скриплетами. В приведенном в качестве примера фрагменте JSP отображается количество запросов к данной странице с момента загрузки сервера (или с момента последнего изменения и перезагрузки сервлета):
<%! private int accessCount = 0; %> Количество обращений к странице с момента загрузки сервера: <%= ++accessCount %>
Также как и в скриплетах, если вам необходимо использовать последовательность символов " %> ", используйте для этого последовательность " %\> ". XML эквивалентом <%! Код %> является
Существуют два основных типа директив: page , которая позволяет вам совершать такие операции, как импорт классов, изменение суперкласса сервлета, и т.п.; и include , которая дает вам возможность вставить файл в класс сервлета при трансляции JSP файла в сервлет. Также следует упомянуть директиву taglib , которая не поддерживается в JSP версии 1.0, но позволяет авторам JSP задавать свои собственные тэги. Предполагается что эта директива станет основной особенностью JSP 1.1.
Эта директива позволяет вам включать файлы в процессе трансляции JSP страницы в сервлет. Использование директивы выглядит следующим образом:
<%@ include file="относительный url" %>
Заданный URL обычно интерпретируется относительно JSP страницы, на которой расположена ссылка, но, как и при использовании любых других относительных URL вы можете задать системе положение интересующего вас ресурса относительно домашнего каталога Web сервера, добавив в начало URL символ "/". Содержимое подключаемого файла обрабатывается как обычный текст JSP и поэтому может включать такие элементы как статический HTML, элементы скриптов, директивы и действия.
Например, многие сайты используют небольшую панель навигации на каждой странице. В связи с проблемами использования фреймов HTML часто эта задача решается размещением небольшой таблицы сверху или в левой половине страницы, HTML код которой многократно повторяется для каждой страницы сайта. Директива include наиболее естественный способ решения этой задачи, избавляющий разработчика от кошмара рутины копирования HTML в каждый отдельный файл. Это происходит следующим образом:
На этом простейшем примере показано использование различных конструкций JSP: выражений, скриплетов, объявлений и директив. Также вы можете скачать исходный файл или вызвать этот скриплет из Интернет .
Использование JavaServer Pages |
---|
Некое динамическое содержание созданное с использованием различных механизмов JSP:
Для упрощения кода в выражениях JSP и скриплетах, вам предоставлен набор их восьми автоматически определенных переменных, иногда называемых неявными объектами . Доступные переменные это request , response , out , session , application , config , pageContext и page . Далее мы рассмотрим каждую из них в отдельности
Это объект HttpServletRequest , связанный с запросом, который позволяет вам обращаться к параметрам запроса (через метод getParameter), типу запроса (GET , POST , HEAD , и т.д..), и входящим HTTP заголовкам (cookies, Referer , и т.д..). Проще говоря, request является подклассом ServletRequest и может отличаться от HttpServletRequest если используется протокол отличный от HTTP, что на практике практически никогда не встречается.
Это объект типа HttpServletResponse , связанный с ответом на запрос клиента. Обратите внимание что, поскольку поток вывода (см. out далее) буферизован, можно изменять коды состояния HTTP и заголовки ответов, даже если это недопустимо в обычном сервлете, но лишь в том случае если какие-то данные вывода уже были отправлены клиенту.
Это объект типа PrintWriter , используемый для отправки вывода клиенту. Однако, чтобы сделать объект response (см. предыдущий раздел) полезным, следует использовать буферизированный вариант PrintWriter - JspWriter . Помните что вы можете изменять размер буфера и даже отключить буферизацию, изменяя значение атрибута buffer директивы page . Этот вопрос подробно рассмотрен в . Также обратите внимание что out используется практически исключительно скриплетами, поскольку выражения JSP автоматически помещаются в поток вывода, что избавляет от необходимости явного обращения к out .
Это объект типа HttpSession , связанный с запросом. Сессии создаются автоматически, и эта переменная существует даже если нет ссылок на входящие сессии. Единственным исключением является ситуация, когда вы отключаете использование сессий используя атрибут session директивы page (см. ). В этом случае ссылки на переменную session приводят к возникновению ошибок при трансляции JSP страницы в сервлет.
В JSP представлен новый класс PageContext для изолированного использования специфических особенностей сервера, таких как более эффективные JspWriter s. Идея заключается в том, что если вы обращаетесь к ним через этот класс а не непосредственно, ваш код может исполняться на "обычных" движках сервлет/JSP.
По сути является синонимом для this , и не нужен при работе с Java. Эта переменная создавалась с расчетом на перспективу, когда возможно появятся другие языки программированя скриптов, отличные от Java.
Действия JSP используют конструкции с синтаксисом XML для управления работой движка сервлета. Вы можете динамически подключать файл, многократно использовать компоненты JavaBeans, направить пользователя на другую страницу или сгенерировать HTML для Java plugin. Допустимо применение следующих действий:
Все эти действия детально рассмотрены далее. Помните что как и во всем XML, имена элементов и атрибутов регистрозависимы.Простейший способ использовать bean
- это использование конструкции
для загрузки bean,
а затем использовать jsp:setProperty и jsp:getProperty
для модификации и получения его свойств.
Однако существуют еще два других способа.
Во-первых, вы можете использовать формат
контейнера, а именно:
Тело
для того чтобы обеспечить выполнение Тела
только в том случае, если экземпляр bean
создается впервые, а не тогда, когда находится
и используется уже существующий bean. Как
обсуждается далее, beans
могут совместно использоваться, поэтому не
каждое выражение jsp:useBean приводит к
созданию экземпляра нового bean.
Во-вторых, кроме id и class ,
существуют еще три других атрибута, которые
вы можете использовать: scope , type ,
и beanName . Эти атрибуты описаны в
следующей таблице.
Атрибут | Применение |
---|---|
id | Дает имя переменной, которая ссылается на bean. Если удается найти bean с теми же самыми значениями id и scope, то вместо создания нового экземпляра используется ранее созданный объект. |
class | Задает полное имя пакета bean. |
scope | Задает область, в которой bean должен быть доступен. Может принимать четыре допустимых значения: page , request , session и application . По умолчанию принимает значение page , означающее что bean доступен только на текущей странице (размещается в PageContext текущей страницы). Значение request означает что bean доступен только для текущего запроса клиента (размещается в объекте ServletRequest). Значение session означает что объект доступен всем страницам на протяжении жизни текущей HttpSession . И, наконец, значение application означает что он доступен всем страницам, использующим тот же самый ServletContext . Причина необходимости этого атрибута заключается в том что jsp:useBean приводит к созданию нового экземпляра объекта в том случае, если нет уже существующего объекта с тем же id и scope . Иначе используется уже существующий объект, и все элементы jsp:setParameter или любые другие между тэгами jsp:useBean игнорируются. |
type | Указывает тип переменной, которая ссылается на объект. Долже совпадать с именем класса, суперкласса или реализуемого интерфейса. Запомните что имя переменной задается через атрибут id . |
beanName | Дает имя bean, которое будет использовано методом instantiate . Можно задать type и beanName , и опустить атрибут class . |
Вы можете использовать jsp:setProperty для присвоения значений свойствам ранее описанных beans. Вы можете делать это двумя способами. Во-первых, вы можете использовать jsp:setProperty после, но вне элемента jsp:useBean , так как это показано в примере:
В этом случае jsp:setProperty выполняется независимо от того, был ли найден существующий bean или был создан новый экземпляр. Другим вариантом заключается в размещении jsp:setProperty в теле элемента jsp:useBean , как это показано в другом примере:
При этом jsp:setProperty выполняется лишь в том случае, если был создан новый экземпляр объекта, а не тогда, когда находится уже существующий.
Действие jsp:setProperty допускает применение следующих четырех атрибутов:
Атрибут | Применение |
---|---|
name | Этот обязательный атрибут служит для задания bean, свойства которого будут устанавливаться. Элемент jsp:useBean должен предшествовать использованию элемента jsp:setProperty . |
property | Этот обязательный атрибут устанавливает свойство, которое вы хотите установить. Однако существует частный случай: значение "*" означает что все параметры запроса, чьи имена совпадают с именами свойств bean будут переданы соответствующему методу установки свойств. |
value | Этот необязательный атрибут устанавливает значение свойства. Строковые значения автоматически преобразуются в числовые, boolean , Boolean , byte , Byte , char и Character с использованием стандартного метода valueOf соответствующего класса. Например, значение "true" для свойства boolean или Boolean будет конвертированно при помощи метода Boolean.valueOf , а значение "42" для свойства int или Integer будет конвертированно при помощи метода Integer.valueOf . Вы не можете одновременно использовать атрибуты value и param , но можете вообще их не использовать. Ознакомьтесь с описанием атрибута param , которое представлено ниже. |
param | Этот необязательный атрибут
устанавливает параметр запроса,
используемый для получения свойства.
Если в текущем запросе этот параметр
отсутствует, никаких действий не
происходит: система не
передает
значение null методу
устанавливающему свойства. Таким образом,
допустимо использование в bean свойств по
умолчанию, переопределяя их лишь в том
случае если этого требуют параметры
запроса. Например, следующий фрагмент
означает следующее: "установить
свойство numberOfItems в соответствии со
значением параметра запроса numItems ,
а если такой параметр в запросе
отсутствует - никакие действия не
выполняются."
|
Для того чтобы скачать исходник JSP, щелкните правой кнопкой мыши на ссылке на исходный код . Вы можете также скачать исходный код для NumberedPrimes bean на который ссылается элемент jsp:useBean . Просмотрите каталог исходных кодов для других классов Java используемых в NumberedPrimes . Лучший способ опробовать это в сети - начать с HTML страницы, которая является внешним интерфейсом .
Многократное использование JavaBeans в JSP |
---|
Этот элемент определяет значение свойства bean, конвертирует его в строку и направляет в поток вывода. Для выполнения действия требуется задание двух атрибутов: имени bean, которое предварительно задается в действии jsp:useBean, и имя свойства, значение которого должно быть определено. Далее приведен пример использования этого действия. За другими примерами обратитесь к разделам и .
Это действие позволяет вам передать запрос другой странице. Оно использует один атрибут, page , который должен содержать относительный URL. Ей может быть как статическое значение, так и вычисляемое в процессе запроса, что и показано на следующих двух примерах:
Это действие позволяет вам вставить элемент OBJECT или EMBED (в зависимости от типа используемого броузера), необходимый для запуска апплетов, использующих plugin Java.
Ниже приведены несколько конструкций, которые вы можете использовать в тех случаях, когда требуется вставить комментарий или использовать символы, зарезервированные для данного тэга:
Синтаксис | Назначение |
---|---|
<%-- комментарий --%> |
Для правильной работы серверных примеров требуется, чтобы на компьютере была установлена работа с Интернет . Реально выходить в Интернет не надо, идет соединение http://localhost:8084// . Но после запуска другого серверного приложения идет соединение по тому же адресу, поэтому документ берется из буфера – и показывается документ, созданный предыдущим приложением. Для показа правильного документа требуется нажать в браузере кнопку "обновить" , и в случае автономной работы в появившемся диалоге, предлагающем выбрать режим работы, выбрать "Подключиться" . Реального соединения с Интернет для адреса http://localhost:8084// не будет – все коммуникации станут проходить локально.
Первый из примеров иллюстрирует базовые конструкции JSP , его можно просмотреть, создав проект File/New Project…/ Samples/J2EE1.4/ Web /Tomcat JSP Example .
Второй пример – надстройка над JSP , специальный набор тегов JSP , разработанный группой экспертов для облегчения разработки серверных приложений . Пример можно просмотреть, создав проект File/New Project…/ Samples/J2EE1.4/Web / JSTL Example .
Порядок примеров в мастере создания приложений прямо противоположный рассматриваемому нами - сначала предлагается использовать JSTL как наиболее развитое средство, затем – JSP как средство более низкого уровня, и только затем Servlet – как средство еще более низкого уровня. Мы используем при рассмотрении обратный порядок, так как JSP использует сервлеты , а JSTL является надстройкой над JSP .
Рассмотрим подробнее первый пример.
Как и в предыдущем случае, при нажатии на гиперссылку "Execute" выполняется соответствующий пример – в данном случае запускается страница JSP . А при нажатии гиперссылки Source показывается HTML -страница с примерным видом исходного кода.
Страницы JSP представляют обычные HTML -документы, но имеющие расширение имени файла . jsp , а не. html или.htm . Это – заготовка HTML -документа, который будет показан пользователю-клиенту. При создании клиентского HTML -документа в этой заготовке выражения в фигурных скобках после знака доллара вычисляются, а в HTML -документ подставляется строковое представление результата.
Например, выражение вида ${1 + 2} выдаст в соответствующее место документа символ 3. Последовательность \$ означает, что выражение ${…} не вычисляется, а рассматривается как строка.
Имеется ряд встроенных в JSP тегов (объектов Java ):
Данные объекты применяются в виде
<%@ имяОбъекта параметр1=значение1 параметр2=значение2 ... %>
Пример их использования:
<%@ page session=true import="java.util.*" %>
Имеется возможность задания сценариев (интерпретируемого кода) с помощью специальных определений вида
<%@ код %>
Где код - сценарий Java для работы с документом или вычислений. Например,
<% for(int i=0; i
В частности, разрешается задавать собственные теги вида
<%@ имяБиблиотеки prefix="имяОбъекта" uri="путь к библиотеке" %>
После чего разрешается использовать теги вида < имяОбъекта:оператор>
Так делается в примере использования оператора out в JSTL Example . Используется пользовательский объект c (сокращение от customer - " покупатель "), задаваемый как prefix ="c", и оператор out , заданный в библиотеке taglib по адресу uri ="http://java.sun.com/jsp/jstl/core ":
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Отметим, что соответствующие библиотеки уже добавлены в проект. Для примера out это пакет org. apache .taglibs.standard.tag.el.core .
После запуска данного приложения в появившемся документе в списке Examples это первый пример - General Purpose Tags. При переходе по данной гиперссылке мы получаем пример
Рис.
10.6.
При нажатии на "шестеренки" получаем результат работы программы:
Соответствующий фрагмент исходного кода этого JSP -документа выглядит так:
|
В этом примере используется объект customer – " покупатель ", заданный в файле Customer . java , расположенном в пакете org. apache .taglibs.standard.examples. beans . То есть самом первом в Source Packages пакете примера. А также объект customers – "покупатели", заданный в файле Customers. java , расположенном в том же пакете.
В классе customer заданы поля lastName , phoneHome, phoneCell и другие. А также ряд методов, которые также можно вызывать в сценарии. С помощью оператора forEach (заданного аналогично оператору out ) осуществляется перебор всех объектов customer , агрегированных в объект customers - список покупателей. А с помощью тега c:out осуществляется вывод необходимой информации в документ.
В JSP имеется огромное количество возможностей. Это тема для отдельной книги. В данном учебном пособии данная технология затронута совсем немного – просто в порядке информирования о ее существовании и некоторых возможностях.
Точно так же, для программирования в локальных и глобальных компьютерных сетях в пакете java . net имеется огромное количество средств разного уровня, описание которых требует отдельной книги. Это и Web -адресация (классы URL, HttpURLConnection, URI, JarURLConnection, URLClassLoader ), и IP-адресация (классы InetAddress, InetAddress4, InetAddress6, NetworkInterface), и управление соединениями через сокеты (классы Socket, SocketAddress, InetSocketAddress, ServerSocket, SocketPermission ). Классы NetPermission , Authentificator и PasswordAuthentification обеспечивают поддержку авторизации ( запрос и обработку имени и пароля).
Кроме упомянутых возможностей пакета java . net имеется