Uygulama amacımız kitap mağazası ( bookstore ) oluşturmak ve sepete eklenen ürünleri session ve cookie ile güncellemek , görmek.
Uygulamamız AllBooks.java dosyasından başlayacak. Tüm dosyalarımız coreservlets paketinde bulunacak.
AllBooks.java
package coreservlets;
public class AllBooks extends CatalogPage {
// CatalogPage'den miras alır
private static final long serialVersionUID = 2573326764146699400L;
// Tüm kitaplar , yani techbooks ve kidsbooks , aynı bölüme toplandı ve AllBooks adı verildi.
// Hepsi aynı sayfada görünecekler.
public void init() {
// ids listesi ile kitapların id bilgileri tutulacak.
String[] ids = {"hall001", "hall002", "lewis001", "alexander001", "rowling001" ,"hall003","deneme" };
// "deneme" id'si tanımlı olmadığı için (Catalog içerisinde ) hata olarak gösterilecektir.
// set item'e parametre olarak liste verilir.
setItems(ids);
setTitle("All Books");
}
}
Tabii öncelikle bu id’lerin kontrol edilmeleri ve bir database’den kontrol edilmeleri gerekir. Biz burada database kullanmayacağımız için bu bilgilerin bir sınıf içerisinde tutarak ( sınıf içindeki listede) kontrolünü yapacağız. Bu bilgileri Catalog.java dosyasından alacağız ve kontrolü CatalogPage.java içerisinde kontrol edeceğiz. Catalog.java dosyasından bilgileri oluştururken ise CatalogItem.java dosyasında tanımlandığı şekliyle oluşturacağız.
CatalogPage.java
package coreservlets;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.Normalizer.Form;
@WebServlet("/catalogpage") // Burayı doldur
public class CatalogPage extends HttpServlet {
private static final long serialVersionUID = -992266179993976567L;
private CatalogItem[] items;
private String[] itemIDs;
private String title;
public CatalogPage() {
super();
}
protected void setItems(String[] itemIDs) {
// tüm kitapların id'sini tutan listeyi aldı
this.itemIDs = itemIDs;
items = new CatalogItem[itemIDs.length];
for(int i=0; i<items.length; i++) {
// AllBooks içerisinden setItems fonksiyonunu çağırmıştık
// ve kitap ıd'leri tutan bir liste vermiştik.
// şimdi bu id'lerin kontrol edilmeleri
// ve uyuşmayanların listeye konmaması gerekli
items[i] = Catalog.getItem(itemIDs[i]) ;
}
}
// title bilgisini kaydeder.
protected void setTitle(String title) {
this.title = title;
}
CatalogPage sınıfını bu dosya içerisinde oluşturduk. Sınıfın 3 adet değişkeni var. title , itemIDs listesi ve items listesi. Öncelikle setItems ve setTitle fonksiyonlarını inceleyelim.
setTitle içerisinde title sınıf değişkenine bu bilgi atanır. setItems fonksiyonu içerisinde ise parametre olarak verilen ( AllBooks içerisinde vermiştik ) ID bilgileri değişkene atanır ve ardından Catalog sınıfındaki getItem fonksiyonu ile ID bilgisi kontrol edilir.
CatalogPage.java devamı
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
if (items == null) {
response.sendError(11);
return;
}
String docType ="<!DOCTYPE html\\n"; // html 5
out.println(docType +
"<html>\\n" +
"<meta charset=\\"UTF-8\\">" +
"<head><title>" + title + "</title></head>\\n" +
"<body style=\\"background-color:bisque\\">\\n" +
"<h1 style=\\"align-items: center;\\">" + title + "</h1>");
// şimdi kitap bilgileri ekrana yazılmalı
for(int i=0; i<items.length; i++){
CatalogItem item;
out.println("<hr>");
item = items[i];
if (item == null) {
// item id'si
out.println("<FONT COLOR=\\"RED\\">" +
"Unknown item ID " + itemIDs[i] +
"</FONT>");
} else {
//
String formURL ="orderpage";
// Pass URLs that reference own site through encodeURL.
formURL = response.encodeURL(formURL);
out.println(
"<form action=\\"" + formURL + "\\">\\n" +
"<input type=\\"hidden\\" name=\\"itemID\\" " +
" value=\\"" + item.getItemID() + "\\">\\n" +
"<H2>" + item.getShortDescription() +
" ($" + item.getCost() + ")</H2>\\n" +
item.getLongDescription() + "\\n" +
"<p>\\n<center>\\n" +
"<input type=\\"submit\\" " +"value=\\"Add to Shopping Cart\\">\\n" +
"</center>\\n<p>\\n</form>");
}
}
out.println("<hr>\\n</body></h>");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
doGet metodunda out nesnesi oluşturulur. Ardından listenin kontrolü yapılır. Null ise hata döndürülür. Eğer null değilse bir döngü ile listedeki her bir eleman ( item ) ekrana yazdırılır. item bilgilerine ise CatalogItem içerisindeki yapı ile ulaşılır. Burada her item altında ayrıca Add to Shoping Cart yazılı submit butonu bulunuyor. Buranın input type’ı Hidden olmalı. Bu buton tıklandığında itemi sepete ekler. Bunu da action kısmında verilen orderpage( OrderPage.java) servlet’i içerisinde yapacaktır.
Şimdi CatalogItem sınıfını görelim.
CatalogItem.java
package coreservlets;
public class CatalogItem {
// Sayfada görülecek olan kitapların , YAPIsını oluşturan sınıf.
// 4 tane bilgi alır(itemID , shortDescription , longDescription , cost)
// Bu bilgileri kapsülleme ile değişkenlere atar.
private String itemID;
private String shortDescription;
private String longDescription;
private double cost;
public CatalogItem(String itemID, String shortDescription, String longDescription, double cost) {
setItemID(itemID);
// this.itemID = itemID;
setShortDescription(shortDescription);
// this.shortDescription = shortDescription;
setLongDescription(longDescription);
// this.longDescription = longDescription;
setCost(cost);
// this.cost = cost;
}
public String getItemID() {
return (itemID);
}
protected void setItemID(String itemID) {
this.itemID = itemID;
}
public String getShortDescription() {
return (shortDescription);
}
protected void setShortDescription(String shortDescription) {
this.shortDescription = shortDescription;
}
public String getLongDescription() {
return (longDescription);
}
protected void setLongDescription(String longDescription) {
this.longDescription = longDescription;
}
public double getCost() {
return (cost);
}
protected void setCost(double cost) {
this.cost = cost;
}
}
Kitapları ekranda gösterirken farklı bilgileri de tutarız. Bu bilgileri hangi yapıda tutacağımıza karar veren yapı bu sınıftır. Kapsülleme kullanılarak ilgili metodlar ( setter ) dışarıdan gizlenmiştir.
Catalog.java
package coreservlets;
public class Catalog {
// Burası bir çeşit şablon
private static CatalogItem[] itemList = {
// CatalogItem tipinde nesneler oluşturup bunları bir liste içerisinde tutuyoruz
// Bunlar ekranda gözükecek nesnelerin bilgileri
new CatalogItem(
"hall001",
"<I>Core Servlets and JavaServer Pages " + "2nd Edition</I> (Volume 1)" + " by Marty Hall and Larry Brown",
"The definitive reference on servlets " + "and JSP from Prentice Hall and \\n"+ "Sun Microsystems Press.<P>Nominated for " + "the Nobel Prize in Literature.",
39.95),
new CatalogItem(
"hall002",
"<I>Core Web Programming, 2nd Edition</I> " + "by Marty Hall and Larry Brown",
"One stop shopping for the Web programmer. " + "Topics include \\n" + "<UL><LI>Thorough coverage of Java 2; " + "including Threads, Networking, Swing, \\n"+ "Java 2D, RMI, JDBC, and Collections\\n" + "<LI>A fast introduction to HTML 4.01, "+ "including frames, style sheets, and layers.\\n" + "<LI>A fast introduction to HTTP 1.1, "+"servlets, and JavaServer Pages.\\n" + "<LI>A quick overview of JavaScript 1.2\\n"+"</UL>",
49.99),
new CatalogItem(
"lewis001",
"<I>The Chronicles of Narnia</I> by C.S. Lewis",
"The classic children's adventure pitting " + "Aslan the Great Lion and his followers\\n"+ "against the White Witch and the forces " + "of evil. Dragons, magicians, quests, \\n"+ "and talking animals wound around a deep " + "spiritual allegory. Series includes\\n"+ "<I>The Magician's Nephew</I>,\\n" + "<I>The Lion, the Witch and the Wardrobe</I>,\\n"+ "<I>The Horse and His Boy</I>,\\n" + "<I>Prince Caspian</I>,\\n"+ "<I>The Voyage of the Dawn Treader</I>,\\n" + "<I>The Silver Chair</I>, and \\n"+ "<I>The Last Battle</I>.",
19.95),
new CatalogItem(
"alexander001",
"<I>The Prydain Series</I> by Lloyd Alexander",
"Humble pig-keeper Taran joins mighty " + "Lord Gwydion in his battle against\\n"+ "Arawn the Lord of Annuvin. Joined by " + "his loyal friends the beautiful princess\\n"+ "Eilonwy, wannabe bard Fflewddur Fflam," + "and furry half-man Gurgi, Taran discovers "+ "courage, nobility, and other values along\\n" + "the way. Series includes\\n"+ "<I>The Book of Three</I>,\\n" + "<I>The Black Cauldron</I>,\\n"+ "<I>The Castle of Llyr</I>,\\n" + "<I>Taran Wanderer</I>, and\\n" + "<I>The High King</I>.",
19.95),
new CatalogItem(
"rowling001",
"<I>The Harry Potter Series</I> by J.K. Rowling",
"The first five of the popular stories " + "about wizard-in-training Harry Potter\\n"+ "topped both the adult and children's " + "best-seller lists. Series includes\\n"+ "<I>Harry Potter and the Sorcerer's Stone</I>,\\n"+ "<I>Harry Potter and the Chamber of Secrets</I>,\\n" + "<I>Harry Potter and the "+ "Prisoner of Azkaban</I>,\\n" + "<I>Harry Potter and the Goblet of Fire</I>, and\\n"+ "<I>Harry Potter and the " + "Order of the Phoenix</I>.\\n",
59.95) ,
new CatalogItem(
"hall003",
"<I>Kralın Yeni Aklı</I> by Roger Penrose ",
"" + "\\n"+ " " + "\\n"+ "<I>e</I>,\\n"+ "<I>s</I>,\\n" + "<I> "+ "</I>,\\n" + "<I>e</I>, \\n"+ "<I> he " + "i</I>.\\n",
99.95)
};
// id verirsek , o id'ye bağlı kitap bilgilerini liste içerisinden verir
// AllBooks'da oluşturduğum liste sadece id'leri tutuyordu.
// Şimdi bu id'leri kontrol etmeliyim
// Onu burada yapıyorum.
public static CatalogItem getItem(String itemID) {
; // yapı
if (itemID == null) {
return (null);
}
/* for (int i = 0; i < itemList.length; i++) {
item = itemList[i];
// item id'si kontrolü yapılır ve eşitlik durumunda item döndürülür.
if (itemID.equals(item.getItemID())) {
return (item);
}
}
*/
for( CatalogItem item2 : itemList) {
if(itemID.equals(item2.getItemID())) {
return (item2);
}
}
return null;
}
}
Catalog sınıfı kitap bilgilerini tutan bir konteyner diyebiliriz. CatalogItem tipinde itemList listesi ile tüm kitap bilgilerini ( CatalogItem yapısına uygun ) gireriz.
Aşağıda ise getItem fonksiyonu bulunmakta. Bu fonksiyonu ID kontrolü için kullanmaktayız. Yani üstte oluşturduğumuz örnek kitaplar içerisinden ID bilgilerini alırız ve dışarıdan girdiğimiz id ( AllBooks içerisinde vermiştik ) ile karşılaştırırırz. Eğer girilen id uyumsuz ise null döndürürüz. Eğer liste içerisindeki örneklerden biri ile uyumlu ise bu item’i döndürürüz
Şimdi kitapları Shopping Cart bölümüne eklediğimizde olacakları görelim.
CatalogPage içerisindeki form action tıklama durumunda bizi orderpage servletine atacaK. Yani OrderPage.java dosyasına
OrderPage.java
package coreservlets;
import ....;
@WebServlet("/orderpage")
public class OrderPage extends HttpServlet {
private static final long serialVersionUID = 1L;
public OrderPage() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
ShoppingCart cart;
String itemID = request.getParameter("itemID");
synchronized(session) {
cart = (ShoppingCart)session.getAttribute("shoppingCart");
// New visitors get a fresh shopping cart.
// Previous visitors keep using their existing cart.
if (cart == null) {
cart = new ShoppingCart();
session.setAttribute("shoppingCart", cart);
}
if (itemID != null) {
String numItemsString =
request.getParameter("numItems");
if (numItemsString == null) {
// If request specified an ID but no number,
// then customers came here via an "Add Item to Cart"
// button on a catalog page.
cart.addItem(itemID);
} else {
// If request specified an ID and number, then
// customers came here via an "Update Order" button
// after changing the number of items in order.
// Note that specifying a number of 0 results
// in item being deleted from cart.
int numItems;
try {
numItems = Integer.parseInt(numItemsString);
} catch(NumberFormatException nfe) {
numItems = 1;
}
cart.setNumOrdered(itemID, numItems);
}
}
}
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Status of Your Order";
String docType ="<!DOCTYPE HTML PUBLIC \\"-//W3C//DTD HTML 4.0 " +"Transitional//EN\\">\\n";
out.println(docType +
"<HTML>\\n" +
"<HEAD><TITLE>" + title + "</TITLE></HEAD>\\n" +
"<BODY BGCOLOR=\\"#FDF5E6\\">\\n" +
"<H1 ALIGN=\\"CENTER\\">" + title + "</H1>"
);
synchronized(session) {
List itemsOrdered = cart.getItemsOrdered();
if (itemsOrdered.size() == 0) {
out.println("<H2><I>No items in your cart...</I></H2>");
} else {
// If there is at least one item in cart, show table
// of items ordered.
out.println("<TABLE BORDER=1 ALIGN=\\"CENTER\\">\\n" +"<TR BGCOLOR=\\"#FFAD00\\">\\n" +" <TH>Item ID<TH>Description\\n" +" <TH>Unit Cost<TH>Number<TH>Total Cost");
ItemOrder order;
// Rounds to two decimal places, inserts dollar
// sign (or other currency symbol), etc., as
// appropriate in current Locale.
NumberFormat formatter = NumberFormat.getCurrencyInstance();
// For each entry in shopping cart, make
// table row showing ID, description, per-item
// cost, number ordered, and total cost.
// Put number ordered in textfield that user
// can change, with "Update Order" button next
// to it, which resubmits to this same page
// but specifying a different number of items.
for(int i=0; i<itemsOrdered.size(); i++) {
order = (ItemOrder)itemsOrdered.get(i);
out.println("<TR>\\n" +
" <TD>" + order.getItemID() + "\\n" +
" <TD>" + order.getShortDescription() + "\\n" +
" <TD>" + formatter.format(order.getUnitCost()) + "\\n" +
" <TD>" + "<FORM>\\n" + // Submit to current URL
"<INPUT TYPE=\\"HIDDEN\\" NAME=\\"itemID\\"\\n" +
" VALUE=\\"" + order.getItemID() + "\\">\\n" +
"<INPUT TYPE=\\"TEXT\\" NAME=\\"numItems\\"\\n" +
" SIZE=3 VALUE=\\"" + order.getNumItems() + "\\">\\n" +
"<SMALL>\\n" + "<INPUT TYPE=\\"SUBMIT\\"\\n "+
" VALUE=\\"Update Order\\">\\n" +
"</SMALL>\\n" + "</FORM>\\n" + " <TD>" +
formatter.format(order.getTotalCost())
);
}
String checkoutURL = response.encodeURL("Checkout.html");
System.out.println(checkoutURL);
// "Proceed to Checkout" button below table
out.println("</TABLE>\\n" +
"<FORM ACTION=\\"" + checkoutURL + "\\">\\n" +
"<BIG><CENTER>\\n" +
"<INPUT TYPE=\\"SUBMIT\\"\\n" +
" VALUE=\\"Proceed to Checkout\\">\\n" +
"</CENTER></BIG></FORM>"
);
}
out.println("</BODY></HTML>");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
Bu sınıf sayfada eklenen ögeleri bize gösterecek. doGet metodunda.
Burada öncelikle session nesnesi oluşturduk. Formdan ( name’i itemID ) gelen verileri request.getParameter ile itemID değişkenine aldık. synchronized ile session senkronizasyonu sağlandı.
ShoppingCart tipinde oluşturduğumuz nesne ile session.getAttribute ‘tan gelen bilgiyi tuttuk. Eğer gelen veri yoksa , yani null ise yeni cart oluşturulur ve değeri atanır.
Eğer itemID kısmı null değilse request üzerinden numItems bilgisi alınır ve sayfaya eklenir.
Ardından urunSayisi değişkenikontrol edilir. Burası sepet sayfasından ürün sayısını güncellemek içindir. Eğer orada sayı girilmemişse değişken null değer alır. Girilmişse cart nesnesinin setNumOrdered fonksiyonuna paramtre verilerek güncellenir.
Alt kısımda html içerik oluşturulur. Altında synchronized bloğu bulunmakta.
Burada önce itemleri bir liste içerisinde tutuyoruz. Bunu da cart nesnesinin içerisinde göreceğiz. Eğer listede eleman yoksa gerekli mesajı yazdırıyoruz.
Listede eleman varsa bir döngü ile her elemanı html içeriğe uygun olarak tablo içerisinde yazdırıyoruz.
En alt kısımda siparişi onaylayıp checkout sayfasına yönlendirilmek için ilgili içeriği oluşturur.
ShoppingCart.java
package coreservlets;
import java.util.*;
public class ShoppingCart {
// Eklenen ögeler için liste
private ArrayList<ItemOrder> itemsOrdered;
public ShoppingCart() {
// ilk oluşturulmada boş liste oluşturulur.
// Listedeki veriler ItemOrdere tipindedir.
// CatalogItem gibi.
itemsOrdered = new ArrayList<ItemOrder>();
}
public List<ItemOrder> getItemsOrdered() {
return(itemsOrdered); // listeyi döndürür
}
public synchronized void addItem(String itemID) {
ItemOrder order;
// ürün eklenir
for(int i=0; i<itemsOrdered.size(); i++) {
order = (ItemOrder)itemsOrdered.get(i);
// eğer itemID'ler eşleniyorsa sayı bir artırılır.
if (order.getItemID().equals(itemID)) {
order.incrementNumItems();
return;
}
}
ItemOrder newOrder = new ItemOrder(Catalog.getItem(itemID));
itemsOrdered.add(newOrder);
}
public synchronized void setNumOrdered(String itemID,int numOrdered) {
ItemOrder order;
for(int i=0; i<itemsOrdered.size(); i++) {
order = (ItemOrder)itemsOrdered.get(i);
if (order.getItemID().equals(itemID)) {
if (numOrdered <= 0) {
itemsOrdered.remove(i);
} else {
order.setNumItems(numOrdered);
}
return;
}
}
ItemOrder newOrder = new ItemOrder(Catalog.getItem(itemID));
itemsOrdered.add(newOrder);
}
}
Bu sınıf ise oluşturulduğunda bir liste de oluşturur ve bu liste üzerinden ekleme silme işlemlerini kontrol eder. Listenin elemanları ItemOrder tipindedir. Bu sınıf ise bir çeşit CatalogItem’a benzer yapıdır. Öğelerin bilgilerini geri döndürmek ve set etmek için fonksiyonları vardır.
ShoppingCart sınıfının yapıcı metod hariç 3 sınıfı vardır. Birincisi getItemsOrdered ile eklenmiş ögeleri ( listede) döndürür.
İkincisi addItem’dir. Burası Sepete ilk eklemede çağırılan kısımdır. Daha doğrusu ürünlerin olduğu kısımdan sepete ekleme yapıldığında çalıştırılır. Eğer eklenmiş ürünlerin sayılarını güncellersek de setNumOrdere fonksiyonu çalışır. Burada eğer girilen sayı negatif ise ürün silinir. Aksi halde girilen ürün sayısı set edilir.
ItemOrder.java
package coreservlets;
public class ItemOrder {
// Sepere eklenmiş ürünler içinn bir yapıdır.
//
private CatalogItem item;
private int numItems;
public ItemOrder(CatalogItem item) {
setItem(item);
setNumItems(1);
}
public CatalogItem getItem() {
return (item);
}
protected void setItem(CatalogItem item) {
this.item = item;
}
public String getItemID() {
return (getItem().getItemID());
}
public String getShortDescription() {
return (getItem().getShortDescription());
}
public String getLongDescription() {
return (getItem().getLongDescription());
}
public double getUnitCost() {
return (getItem().getCost());
}
public int getNumItems() {
return (numItems);
}
public void setNumItems(int n) {
this.numItems = n;
}
public void incrementNumItems() {
setNumItems(getNumItems() + 1);
}
public void cancelOrder() {
setNumItems(0);
}
public double getTotalCost() {
return (getNumItems() * getUnitCost());
}
}
Checkout.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Checking Out</TITLE>
</HEAD>
<BODY BGCOLOR="#FDF5E6">
<H1 ALIGN="CENTER">Checking Out</H1>
We are sorry, but our electronic credit-card-processing
system is currently out of order. Please send a check
to:
<PRE>
Marty Hall
coreservlets.com, Inc.
300 Red Brook Blvd., Suite 400
Owings Mills, MD 21117
</PRE>
Since we have not yet calculated shipping charges, please
sign the check but do not fill in the amount. We will
generously do that for you.
</BODY></HTML>