|
Здравствуйте, подскажите пожалуйста где можно достать материалы по курсу Кросс-платформенные и многозвенные технологии, о которых говориться, к примеру, в Лекции 2. Пример "Служба мгновенных сообщений" |
Технология Enterprise Java Beans. Часть 1
Тестовый клиент для ShoppingBasketBean
Тестовый клиент для компонента ShoppingBasketBean создает один экземпляр компонента и делает тестовый заказ.
public class TestClient2
{
public static void main(String args[])
{
try
{
Context jndiContext = createJBossContext();
Object ref = jndiContext.lookup("ShoppingBasketBean");
ShoppingBasketHome home = (ShoppingBasketHome) PortableRemoteObject.narrow(ref, ShoppingBasketHome.class);
ShoppingBasketRemote remote = home.create("Boris");
System.out.println("Starting to work with the shop");
remote.addCommodity(2);
remote.addCommodity(3);
remote.addCommodity(4);
remote.processOrder();
}
catch (RemoteException e)
{
e.printStackTrace();
}
catch (NamingException e)
{
e.printStackTrace();
}
catch (CreateException e)
{
e.printStackTrace();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
public static Context createJBossContext() throws NamingException
{
Properties p = new Properties();
p.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
p.put("java.naming.provider.url", "jnp://127.0.0.1:1099");
p.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
Context jndiContext = new InitialContext(p);
return jndiContext;
}
}В консоль данный тестовый клиент ничего не выводит, но можно посмотреть результат его работы, выполнив два запроса в базе данных в SQL*PLUS:
- select * from ORDERS;
- select * from COMMODITY_ORDER.
Результаты выполнения запросов показаны на Рис. 3.40. Как видно, в таблице ORDERS появилась информация о новом заказе, а в таблице COMMODITYORDERS - информация о составе заказа.
Дескрипторы развертывания
Дескрипторы развертывания определены для трех компонентов в одном файле ejb-jar.xml. Дескрипторы сеансовых компонентов без состояния CommoditiesListBean и OrdersListBean ничем не отличаются от дескрипторов развертывания компонентов из предыдущих примеров. У компонента ShoppingBasketBean в элементе session-type будет стоять вместо Stateless- Stateful.
<?xml version="1.0" encoding="UTF-8"?> <ejb-jar id="ejb-jar ID" version="2.1" xmlns = "http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd"> <description>Beans for the Shopping Basket</description> <display-name>ShoppingBasketBean</display-name> <enterprise-beans> <session> <ejb-name>CommoditiesListBean</ejb-name> <home>shoppingBasket.CommoditiesListHome</home> <remote>shoppingBasket.CommoditiesListRemote</remote> <ejb-class>shoppingBasket.CommoditiesListBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> <session> <ejb-name>OrdersListBean</ejb-name> <home>shoppingBasket.OrdersListHome</home> <remote>shoppingBasket.OrdersListRemote</remote> <ejb-class>shoppingBasket.OrdersListBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> <session> <ejb-name>ShoppingBasketBean</ejb-name> <home>shoppingBasket.ShoppingBasketHome</home> <remote>shoppingBasket.ShoppingBasketRemote</remote> <ejb-class>shoppingBasket.ShoppingBasketBean</ejb-class> <session-type>Stateful</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> </ejb-jar>
Клиентское приложение
В этом примере в качестве клиентского приложения будет выступать веб-приложение, написанное при помощи сервлетов и JSP.В данном пособии не ставиться цель научить с нуля программировать на сервлетах и JSP. Поэтому предполагается, что некоторые знания по этой теме у читателя уже есть.
Логика работы данного веб-приложения будет заключаться в следующем: пользователю отображается некоторая веб-страница, генерируемая при помощи JSP.После чего пользователь с этой веб-страницы может перейти на другую веб-страницу, либо послать данные на обработку некоторому сервлету (либо при помощи формы, либо просто посредством ссылки). Компоненты EJB хранятся в контексте JSP -сессии (Session).Помимо этого в контексте сессии хранится имя пользователя, под которым он вошел в систему. Для любого веб-магазина характерны следующие страницы:
- Страница входа. Здесь пользователь вводит свое имя и пароль. В этом примере в качестве этой страницы будет использоваться страница index.jsp.
- Страница со списком товаров для покупки. Здесь пользователь может выбрать среди списка всего доступного в магазине что-нибудь себе по вкусу. В примере это goodlist.jsp.
- Страница с корзиной. Здесь отображается текущее состояние корзины. Пользователь может пересчитать количество товаров в корзине или вообще удалить какой-то или какие-то товары из корзины. В примере это basket.jsp.
- Страница "Спасибо за покупку". Отображается, когда клиент сделал заказ. Предлагает посетить магазин еще раз. В примере это thankyou.jsp.
- Страница с информацией о предыдущих заказах. Здесь пользователь может узнать когда и какие заказы он уже делал в этом магазине. В примере это prevorders.jsp.
Помимо страниц, необходимы еще сервлеты, которые будут обрабатывать действия пользователя. Сервлеты необходимы для:
- Добавления товара в корзину, сервлет AddToCartServlet.
- Пересчета товаров в корзине, сервлет RecalculateServlet.
- Выполнения заказа, сервлет MakeOrderServlet.
- Входа в систему, сервлет LoginServlet.
- Выхода из системы, сервлет LogoutServlet.
Помимо сервлетов, будет использоваться фильтр сервлетов. Если пользователь не вошел в магазин, этот фильтр будет перенаправлять его на страницу входа index.jsp, в случае если он вдруг попытается запросить какую-либо другую страницу или сервлет. Фильтр называется AuthFilter.
Рассмотрим страницу входа в магазин.
<%@ page language="java" contentType="text/html; charset=cp1251"
pageEncoding="cp1251"%>
<%String username = (String) session.getAttribute("username");
// Пользователь уже вошел в магазин - отправляем его на страницу
// со списком товаров
if (username != null) {
application.getRequestDispatcher("/goodlist.jsp").forward(request, response);
}
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=cp1251">
<title>Login</title>
</head>
<body>
// Данные отправляются сервлету LoginServlet. В URL-адресах ему поставлен
// в соответствие адрес, заканчивающийся на login.
// Стоит отметить, что мы не используем пароли для пользователей.
// Каждый волен входить под тем именем, которое ему нравится.
<form action="login" method="post"> <table>
<tr>
<td> Login:
</td> <td>
<input type="text" name="username"></input>
</td>
</tr> <tr>
<td>
<input type="SUBMIT" value="Login"></input> </td>
</tr> </table> </form>
</body>
</html>Страница входа в систему показана на Рис. 3.41.
Теперь рассмотрим сервлет входа в систему. Он обрабатывает только Р0SТ -запросы. Данный сервлет, получив данные формы, сохраняет имя пользователя в контексте сессии. Затем он получает удаленные интерфейсы трех ЕJB -компонентов и также сохраняет их в контексте сессии. Теперь они будут доступны на всех остальных страницах в магазине.
public class LoginServlet extends HttpServlet
{
private Context jndiContext = null;
private static final long serialVersionUID = 4562488849398632419L;
public LoginServlet()
{
super();
try
{
jndiContext = createJBossContext();
}
catch (NamingException e)
{
e.printStackTrace();
}
}
private static Context createJBossContext() throws NamingException
{
Properties p = new Properties();
p.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
p.put("java.naming.provider.url", "jnp://127.0.0.1:1099");
p.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
Context jndiContext = new InitialContext(p);
return jndiContext;
}
protected void doPost(HttpServletRequest req, HttpServletResponse res)
{
String loginName = req.getParameter("username");
HttpSession session = req.getSession();
// Если пользователь еще не вошел в магазин
if (session.getAttribute("username") == null)
{
// Сохраняем имя пользователя в контексте сессии
session.setAttribute("username", loginName);
Object ref;
try
{
// Получаем и сохраняем три удаленных интерфейса
// компонентов EJB в сессии.
ref = jndiContext.lookup("ShoppingBasketBean");
ShoppingBasketHome home = (ShoppingBasketHome) PortableRemoteObject.narrow
(ref, ShoppingBasketHome.class);
ShoppingBasketRemote remote = home.create(loginName);
session.setAttribute("basketbean", remote);
ref = jndiContext.lookup("CommoditiesListBean");
CommoditiesListHome homeCom = (CommoditiesListHome)
PortableRemoteObject.narrow(ref, CommoditiesListHome.class);
CommoditiesListRemote remoteCom = homeCom.create();
session.setAttribute("commoditiesbean", remoteCom);
ref = jndiContext.lookup("OrdersListBean");
OrdersListHome homeOrd = (OrdersListHome)
PortableRemoteObject.narrow(ref, OrdersListHome.class);
OrdersListRemote remoteOrd = homeOrd.create();
session.setAttribute("ordersbean", remoteOrd);
}
catch (NamingException e)
{
e.printStackTrace();
}
catch (CreateException e)
{
e.printStackTrace();
}
catch (RemoteException e)
{
e.printStackTrace();
}
}
// Отправляем пользователя на страницу с товарами
RequestDispatcher reqDispatcher = getServletContext().getRequestDispatcher("/goodlist.jsp");
try
{
reqDispatcher.forward(req, res);
}
catch (java.io.IOException e)
{
e.printStackTrace();
}
catch (javax.servlet.ServletException e)
{
e.printStackTrace();
}
}
}Перейдем к странице с товарами. Здесь вся логика сводится к получению компонента CommoditiesListBean из контекста сессии, и отображения доступных товаров. Для каждого товара определена ссылка на сервлет добавления товара AddToCartServlet.В таблице COMMODITIESLIST у каждого объекта было определено такое поле как IMAGEPATH - в нем хранится путь до изображения, которое соответствует товару. При помощи Google™ находим фотографии различных пачек сигарет и поместим их в каталог img.
<%@ page language="java" contentType="text/html;
charset=cp1251" pageEncoding="cp1251"%>
<%@page import="shoppingBasket.CommoditiesListRemote"%>
<%@page import="java.util.List"%>
<%@page import="java.util.Iterator"%>
<%@page import="dataObjects.Commodity"%>
<%@page import="java.text.NumberFormat"%>
<%@page import="java.util.Locale"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html> <head>
<meta http-equiv="Content-Type" content="text/html; charset=cp1251">
<title>Cigarette store</title>
</head>
<body>
<h1>Welcome to the finest internet cigarettes store!</h1>
<h2>Here is the list of commodities available for purchase</h2>
// Переход к корзине с товарами
<a href="basket.jsp">Goto Basket</a><br>
// Переход к предыдущим заказам
<a href="prevorders.jsp">View previous orders</a><br>
<table border="0" cellpadding="0" cellspacing="0">
<%
// Получаем удаленный интерфейс ComoditiesListBean
CommoditiesListRemote remote = (CommoditiesListRemote)
session.getAttribute("commoditiesbean");
List list = remote.getAvailableCommodities();
NumberFormat format = NumberFormat.getCurrencyInstance(Locale.US);
for (Iterator iter = list.iterator(); iter.hasNext();)
{ Commodity commodity = (Commodity) iter.next();
%>
<tr>
<td style="padding-left:10px; padding-right:10px;">
<%=commodity.getName()%>
</td>
<td style="padding-left:10px; padding-right:10px;">
<%=commodity.getDescription()%> </td>
<td style="padding-left:10px; padding-right:10px;">
<%=format.format(commodity.getPrice())%> </td>
// Ссылка на сервлет AddToServlet
<td style="padding-left:10px; padding-right:10px;"> <a
href="addtocart?good id=<%=commodity.getId()%>">Add to cart</a> </td>
<td style="padding-left:10px; padding-right:10px;">
<img src="<%=commodity.getImagePath()%>"/></td>
</tr>
<%
}
%>
</table>
// Переход к странице с корзиной для того, чтобы оформить заказ
<a href="basket.jsp">Make order</a><br>
// Выход из системы посредством LogoutServlet
<a href="logout">Logout</a>
</body> </html>Страница с фотографиями товаров (сигарет) изображена на Рис. 3.42. Сервлет AddToCartServlet получает в качестве параметра ID товара, из контекста сессии берет удаленный интерфейс ShoppingListBean,а затем выполняет вызов addCommodity (goodId). Стоит отметить, что ни сервлет, не компонент не проверяют факта существования товара с таким ID. Поэтому пользователь может "обмануть" магазин передав заведомо неправильный good_id в сервлет.
public class AddToCartServlet extends HttpServlet
{
private static final long serialVersionUID = -666156591413576322L;
public AddToCartServlet()
{
super();
}
protected void doPost(HttpServletRequest req, HttpServletResponse res)
{
doGet(req, res);
}
protected void doGet(HttpServletRequest req, HttpServletResponse res)
{
HttpSession session = req.getSession();
ShoppingBasketRemote remote = (ShoppingBasketRemote)
session.getAttribute("basketbean");
String strGoodId = req.getParameter("good id");
int goodId = 0;
try
{
goodId = Integer.parseInt(strGoodId);
}
catch (NumberFormatException e)
{
goodId = 0;
}
if (goodId > 0 && remote != null)
{
try
{
remote.addCommodity(goodId);
}
catch (RemoteException e)
{
e.printStackTrace();
}
}
RequestDispatcher reqDispatcher = getServletContext().getRequestDispatcher("/goodlist.jsp");
try
{
reqDispatcher.forward(req, res);
}
catch (java.io.IOException e)
{
e.printStackTrace();
}
catch (javax.servlet.ServletException e)
{
e.printStackTrace();
}
}
}


