Skip to content

2. İlk örnek

Örneklerimizin çoğu, Struts 2 ile uygulanan tek web katmanıyla sınırlı olacaktır:

Temel bilgiler edinildikten sonra, çok katmanlı bir mimariye sahip daha karmaşık bir örnek üzerinde çalışacağız.

2.1. Örneğin oluşturulması

İlk uygulamamızı oluşturuyoruz.

  • [1]'te,
  • [2]'te Java Web / Web Uygulaması türünü seçiyoruz
  • [3]'te projeye bir ad veriyoruz
  • [4]'te, projenin konumunu belirliyoruz.
  • [5]'te, yeni projeyi ana proje olarak belirleyin.
  • [6] adımında, Tomcat sunucusu seçilir. NetBeans 7.01 kurulumu sırasında, Apache Tomcat ve Glassfish 3.1 olmak üzere iki sunucu kurulmuştur.
  • [7] adımında, Struts 2 çerçeve ile çalışacağımızı belirtiyoruz. Bu imkânı bize Struts 2 eklentisinin kurulumu sağlıyor. Eklenti olmadan Struts 2 çerçevesi bize sunulmaz.
  • [8] adımında, üzerinde çalışacağımız örnek projenin oluşturulması istenir.
  • [9]'te, hangi Struts 2 kütüphanelerinin kullanılacağını kontrol edebiliriz.
  • [10]'te, oluşturulan proje yer almaktadır. Buna daha sonra tekrar döneceğiz.
  • [11] dosyasında, projenin kütüphaneleri yer almaktadır. Bunlar Struts 2 eklentisi tarafından entegre edilmiştir. Eklentiye sahip değilseniz, bu kütüphaneleri indirilen Struts 2 dağıtımının [lib] klasöründe bulabilirsiniz. Bu durumda 12. ve 13. adımları izleyin.

2.2. Dosya sisteminde oluşturulan proje

  • dosya sisteminde [1] olarak oluşturulur; [Projects] sekmesi, projenin "geliştirici" görünümünü sunar
  • [2]'te, [Files] sekmesi dosya sistemindeki proje klasörünü gösterir
  • [2A]'te, [Web Pages] dalı, [2]'te [web] [2B] klasörüyle temsil edilir
  • [3A]'te, [Source Packages] dalı, [2]'te [java] ve [3B] klasörleriyle temsil edilir

2.3. [META-INF/context.xml] yapılandırma dosyası

Bu dosya şöyledir:


<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/exemple-01"/>
  1. satır, web uygulamasının bağlamının /exemple-01 olduğunu gösterir. [http://machine:port/exemple-01/...] türündeki tüm URL dosyaları bu uygulama tarafından işlenecektir. Bu bağlam, [2] projesinin özelliklerinde bulunabilir: projeye sağ tıklayın / Properties / Run.

2.4. [WEB-INF/web.xml] yapılandırma dosyası

Her web uygulaması, uygulamanın [WEB-INF] klasöründeki [web.xml] dosyası ile yapılandırılır. Oluşturulan dosya şöyledir:


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <URL-pattern>/*</URL-pattern>
    </filter-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>example/HelloWorld.JSP</welcome-file>
    </welcome-file-list>
</web-app>
  • 3-6. satırlar, Struts 2’nin [org.apache.struts2.dispatcher.FilterDispatcher] sınıfı tarafından uygulanan bir filtreyi tanımlar. MVC modelinin C denetleyicisi rolünü üstlenecek olan bu sınıftır.
  • 7-10. satırlar: URL modeliyle, bu modele uyan URL'leri işlemekle görevli filtre arasında bir bağlantı tanımlar. Burada, tüm URL (/* şablonu) isteklerinin struts2 adlı filtre tarafından işlenmesi gerektiği belirtilmiştir. Bu, 3-6. satırlarda tanımlanan filtredir. Dolayısıyla burada, tüm URL istekleri Struts 2 denetleyicisinden geçecektir.
  • 11-15. satırlar: bir kullanıcı oturumunun süresini tanımlar; burada bu süre 30 dakikadır. Farklı istekler sırasında, bir kullanıcı ilk isteğinde kendisine atanan ve daha sonra her yeni istekte sistematik olarak gönderdiği bir oturum jetonuyla izlenir. Bu, web sunucusunun kullanıcıyı tanımasını ve kullanıcı için "hafıza" olarak adlandırılan oturumu yönetmesini sağlar. İki istek arasında 30 dakikadan fazla zaman geçerse, kullanıcı için yeni bir oturum jetonu oluşturulur; böylece kullanıcı "hafızasını" kaybeder ve yeni bir oturum başlatır.
  • 16-18. satırlar: Kullanıcı, herhangi bir belge talep etmeden web uygulamasını sorguladığında görüntülenecek dosyayı tanımlar. Böylece, talep edilen URL dosyası [http://machine:port/exemple-01] olduğunda, sunulan URL dosyası [http://machine:port/exemple-01/example/HelloWord.JSP] olacaktır.

2.5. [struts.xml] yapılandırma dosyası

[struts.xml] dosyası, Struts 2'nin yapılandırma dosyasıdır. Bu dosya, projenin ClassPath dizininde herhangi bir yerde bulunabilir. Yukarıdaki NetBeans projesinde, projenin ClassPath dizini iki daldan oluşur:

  • Kaynak Paketleri
  • Kütüphaneler

Bu iki dalda bulunan tüm klasörler veya kütüphaneler, dolayısıyla projenin ClassPath'sinin bir parçasıdır. [struts.xml]'i <default package> içine yerleştirmek yaygın bir uygulamadır. Burada içeriği şu şekildedir:


<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <include file="example.xml"/>
    <!-- Varsayılan paket için yapılandırma. -->
    <package name="default" extends="struts-default">
    </package>
</struts>
  • 5. ve 10. satırlar: belgenin kök etiketi <struts> etiketidir
  • 6. satır: [example.xml] dosyası buraya eklenir. Dolayısıyla kendi yapılandırmasını da beraberinde getirir. Buna daha sonra tekrar döneceğiz.
  • 8-9. satırlar: Burada "default" adlı bir paket tanımlanmaktadır. Bir paket, aynı URL'e sahip bir Struts 2 eylem grubunu yapılandırmaya olanak tanır. Örneğin, [/chemin/Action1] ve [/chemin/Action2]. Böylece bu eylemler için bir paket tanımlayabiliriz:

<package name="employes" namespace="/employes" extends="struts-default">
... configuration
    </package>

Yukarıdaki paket "çalışanlar" olarak adlandırılır ve URL ile /employes/Action eylemlerini yapılandırır. Paket, "extends" anahtar sözcüğüyle başka bir paketten miras alabilir. Yukarıda, employes paketi, struts-default paketinden miras almaktadır. Bu paket, struts2-core.jar kütüphanesindeki [struts-default.xml] dosyasında bulunur:

[struts-default.xml] dosyasında tanımlanan "struts-default" paketi, bir eylemin çağrılması sırasında yürütülen yakalayıcıların listesi de dahil olmak üzere çeşitli ayarları yapılandırır. Bir Struts 2 uygulamasının MVC yapısına geri dönelim:

URL biçimindeki bir [http://machine:port/.../Action]'i işlemek için, [FilterDispatcher] denetleyicisi, istenen eylemi uygulayan sınıfın bir örneğini oluşturur ve bu sınıfın yöntemlerinden birini, varsayılan olarak execute adlı yöntemi yürütür. Bu execute yöntemine yapılan çağrı, bir dizi ara alıcıdan geçecektir:

Hem interceptörler hem de eylem aynı isteği işler. struts-default paketinde tanımlanan interceptor listesi çoğu durumda yeterlidir. Bu nedenle Struts paketlerimiz her zaman struts-default paketini genişletecektir. Farklı interceptorların ne işe yaradığını öğrenmek için [ref2]'in 4. bölümünü okuyabilirsiniz.

struts.xml yapılandırma dosyasına geri dönelim:


<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <include file="example.xml"/>
    <!-- Varsayılan paket için yapılandırma. -->
    <package name="default" extends="struts-default">
    </package>
</struts>
  • 8. satır: default adlı paketin özel bir rolü vardır. Bu paket, diğer paketlerde yapılandırılmamış eylemleri işler. Burada, 8-9. satırlarda default paketi için herhangi bir yapılandırma yapılmamıştır. Dolayısıyla bu paketin tanımını silebiliriz.

Şimdi, [struts.xml] dosyasının 6. satırında yer alan [example.xml] dosyasına bakalım:


<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <package name="example" namespace="/example" extends="struts-default">
        <action name="HelloWorld" class="example.HelloWorld">
            <result>/example/HelloWorld.JSP</result>
        </action>
    </package>
</struts>
  • 8. satır: struts-default paketini genişleten example adlı bir paketi tanımlar. Bu paket, /example/Action türündeki URL'leri yönetir (ad alanı /example).
  • 9-11. satırlar: HelloWorld adlı bir eylemi (name özniteliği) tanımlar; bu eylem, URL ve /example/Helloworld'e karşılık gelir. Bu eylem, example.HelloWorld sınıfının bir örneği (class özniteliği) tarafından işlenir.
    • [FilterDispatcher] denetleyicisi, bu sınıfın execute yöntemini çalıştırır.
    • Bu yöntem, “navigasyon anahtarı” olarak adlandırılan bir karakter dizisi döndürür.
    • Farklı gezinme anahtarları, <result name="anahtar"/> etiketleriyle tanımlanmalıdır (10. satır). name özniteliği bulunmadığında, varsayılan olarak success anahtarı kullanılır. Yukarıdaki örnekte durum budur. Dolayısıyla, example.HelloWorld sınıfının execute yöntemi, [FilterDispatcher] denetleyicisine success anahtarını döndürmelidir.
    • [FilterDispatcher] denetleyicisi daha sonra [/example/HelloWorld.JSP] sayfasını görüntüler (10. satır).

[struts.xml] ve [example.xml] dosyalarını birleştirirsek, gereksiz görünen default paketini silersek, her şey sanki [struts.xml] dosyası tek bir [example.xml] dosyasına indirgenmiş gibi gerçekleşir.

2.6. HelloWorld eylemi

İncelenen [struts.xml] dosyasına göre, istemci tarafından talep edilen URL dosyası /example/HelloWorld olduğunda HelloWorld eylemi tetiklenir. Bunun üzerine execute yöntemi yürütülür. Bu yöntem bir gezinme anahtarı döndürmelidir. Daha önce gördüğümüz gibi, tek bir navigasyon anahtarı vardı: success ve bu durumda kullanıcıya yanıt olarak /example/HelloWorld.JSP sayfası gönderildi.

HelloWorld eyleminin kodu şöyledir:

package example;

import com.opensymphony.xwork2.ActionSupport;

public class HelloWorld extends ActionSupport {

    public String execute() throws Exception {
        setMessage(getText(MESSAGE));
        return SUCCESS;
    }

    public static final String MESSAGE = "HelloWorld.message";

    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
  • 5. satır: HelloWorld sınıfı, Struts 2'nin ActionSupport sınıfından türetilmiştir. Bu durum hemen hemen her zaman geçerlidir. Bu sayede, 8. satırdaki getText yöntemi gibi belirli yöntemlerden yararlanılabilir.
  • 7-10. satırlar: Struts denetleyicisi çağrıldığında yürütülen execute yöntemi. Bu yöntemin bir karakter dizisi döndürmesi gerektiği biliniyor; bu nedenle 7. satırdaki imza da buna göre belirlenmiştir. Burada, yine ActionSupport içinde tanımlanan SUCCESS sabitini döndürecektir. Benzer şekilde, execute yönteminin sonucu için başka sabitler de tanımlanmıştır:
Constante
Valeur
SUCCESS
"success"
ERROR
"error"
INPUT
"input"
LOGIN
"login"

Yani burada, execute yöntemi, success dizesini oluşturur. [struts.xml] dosyasına bakarsak, kullanıcıya yanıt olarak /example/HelloWorld.JSP sayfası döndürülecektir.

  • 8. satır: execute yöntemi, 14. satırdaki message alanını getText(" HelloWorld.message ") değeriyle başlatır. getText yöntemi, üst sınıf olan ActionSupport'e aittir. Bu yöntem, kullanılan dile göre bir dosyadan metin almayı sağlar. Varsayılan olarak, eylemle aynı pakette bulunan package.properties dosyası burada kullanılacaktır. Bu dosyanın iki sürümü vardır:

[package.properties] dosyası şöyledir:

HelloWorld.message= Struts is up and running ...

Bu dosya, clé=valeur biçiminde bir dizi metin satırından oluşur. Bu dosya kullanılırsa, getText("HelloWorld.message") ifadesinin değeri "Struts is up and running ..." olacaktır.

[package_es.properties] dosyası ise şöyledir:

HelloWorld.message= ¡Struts está bien! ...

İstemci tarayıcısı tarafından kullanılan dil İspanyolca ise (package_es.properties dosyasındaki es özniteliği), getText("HelloWorld.message") dosyasının değeri ¡Struts está bien! olacaktır. ... Diğer tüm durumlarda ise [package.properties] dosyası kullanılacaktır.

2.7. HelloWorld.JSP görünümü

Bu, Struts yapbozunun son parçasıdır. URL /example/HelloWorld adresi istendiğinde görüntülenen görünüm budur. İlk isteğin, nihayetinde bu yanıtı görüntülemek için hangi labirentten geçtiğini gördük. Sayfanın kodu şöyledir:


<%@ page contentType="text/html; charset=UTF-8" %>

<%@ taglib prefix="s" uri="/struts-tags" %>

<html>
    <head>
        <title><s:text name="HelloWorld.message"/></title>
    </head>

    <body>
        <h2><s:property value="message"/></h2>

        <h3>Languages</h3>
        <ul>
            <li>
                <s:url id="URL" action="HelloWorld">
                    <s:param name="request_locale">en</s:param>
                </s:url>
                <s:a href="%{URL}">English</s:a>
            </li>

            <li>
                <s:url id="URL" action="HelloWorld">
                    <s:param name="request_locale">es</s:param>
                </s:url>

                <s:a href="%{URL}">Espanol</s:a>

            </li>
        </ul>
    </body>
</html>
  • Sayfa, HTML etiketleri (5., 6. satırlar, ...) ve 3. satırda tanımlanan bir kütüphaneden gelen etiketleri kullanmaktadır. Tüm <s:xx> etiketleri bu kütüphaneye aittir.
  • 7. satır: <s:text> etiketi, istemci tarayıcısının diline göre farklı bir metin görüntülenmesini sağlar. name özniteliği, mesaj dosyalarında aranacak anahtarı belirtir. Burada da package_xx.properties dosyaları kullanılacaktır. Bu dosyaların yalnızca HelloWorld.message anahtarına sahip tek bir mesaj içerdiğini hatırlayalım.
  • 11. satır: <s:property name="özellik"> etiketi, ActionContext adlı bir nesnenin bir özelliğinin değerini yazmaya olanak tanır. Bu nesnede şunlar bulunur:
    • yürütülen eylemin özellikleri. name="message" ifadesi, mevcut eylemin message alanının değerini görüntüler. Bu alanın değerini almak veya başlatmak için, alana bağlı get ve set yöntemleri kullanılır. Dolayısıyla bu yöntemlerin mevcut olması gerekir.
    • <s:property name="#request['clé']"> ile belirtilen mevcut isteğin öznitelikleri
    • <s:property name="#session['clé']"> ile belirtilen kullanıcı oturumunun öznitelikleri
    • <s:property name="#application['clé']"> ile belirtilen uygulamanın kendisinin özellikleri
    • istemci tarayıcısı tarafından gönderilen parametreler <s:property name="#parameters['clé']">
    • <s:property name="#attr['clé']"> notasyonu, sırasıyla sayfada, istekte, oturumda ve uygulamada aranan bir nesnenin değerini gösterir.
  • 16-18. satırlar: <s:url > etiketi, bir URL tanımlamak için kullanılır. id özniteliği, oluşturulacak URL'e bir ad verir. Bu ad daha sonra 19. satırda kullanılır. action özniteliği, URL'in hangi eyleme yönlendirileceğini belirtir.
  • 17. satır: <s:param ..> etiketi, URL'e ?param1=valeur1&param2=valeur2&... biçiminde parametreler eklemeye olanak tanır. Burada eklenecek parametre ?request_locale=es olacaktır.

Sonuç olarak, oluşturulan URL dosyası şu şekilde olacaktır:

Bu URL'i anlamak için, [HelloWorld.JSP] sayfasının iki durumda görüntülendiğini hatırlamak gerekir:

  • (devamı)
    • URL'in doğrudan talebi üzerine [/exemple-01/example/HelloWorld.JSP]
    • [/exemple-01/example/HelloWorld.action] eyleminin talebi üzerine

Her iki durumda da URL'in yolu /exemple-01/example.'tir. <s:url action= "... "> etiketi, bu yola action özniteliği ile tanımlanan eylemi ekler. Böylece /example-01/example/HelloWorld elde edilir. Ardından, önceki URL'e .action sonekini ve varsa URL'in parametrelerini ekler. Elde edilen URL /example-01/example/HelloWorld.action?request_locale=en, [struts.xml] dosyasında tanımlanan HelloWorld eylemini çağırırken request_locale=en parametresini de aktaracaktır. Bu parametre, HelloWorld eylemi tarafından değil, sayfaların uluslararasılaştırılmasını yöneten Struts interceptörlerinden biri tarafından işlenecektir. request_locale parametresi tanınacak ve işlenecektir. Sayfaların dili İngilizce (en) olacaktır.

  • 19. satır: Bir HTML bağlantısı tanımlar. <a> etiketinin href özniteliği bir karakter dizisi bekler. Burada, 16. satırda tanımlanan ve id'si URL olan URL değerini kullanmak istiyoruz. Bunun için href="%{URL}" yazılır. URL değişkeni değerlendirilir ve değeri href özniteliğine atanır. Çoğu durumda, değişkenlerin değerlendirilmesi örtük olarak gerçekleşir. Örneğin, şu yazıldığında
<s:property name= "message "/>

yazıldığında, "message" dizesi değil, message özelliğinin değeri görüntülenir. Ancak diğer durumlarda, değişkenlerin veya özelliklerin değerlendirilmesini zorlamak gerekir. Eğer href="URL" yazılmış olsaydı, href özniteliğine URL dizesi atanmış olacaktı.

  • 23-27. satırlar: Sayfaların dilini İspanyolca'ya değiştirmek için bir HTML bağlantısı oluşturur.

2.8. Uygulamanın çalıştırılması

Projeyi çalıştırıyoruz:

  • [1]'te, [exemple-01] projesinin çalıştırılması başlatılır. Tomcat web sunucusu, henüz çalışmıyorsa otomatik olarak başlatılır. URL, [/exemple-01] ve [3] dosyaları istenir. Ardından [web.xml] dosyası kullanılır:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <URL-pattern>/*</URL-pattern>
    </filter-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>example/HelloWorld.JSP</welcome-file>
    </welcome-file-list>
</web-app>
  • çünkü istenen URL [/exemple-01] dosyasında herhangi bir sayfa belirtilmediğinden, Tomcat 16. ve 18. satırlardaki <welcome_file-list> etiketini kullanacaktır. Dolayısıyla, URL /exemple-01/example/HelloWorld.JSP sunulacaktır.
  • Struts 2, tüm URL'leri (8. ve 9. satır) işlediği için, bu URL, Struts tarafından filtrelenecektir. Bu, bir eyleme değil, bir sayfaya (JSP) karşılık geldiğinden, sonuncusu görüntülenecektir.
  • Dolayısıyla, [2] adresinde gördüğümüz şey, daha önce incelediğimiz HelloWorld.JSP sayfasıdır.
  • [4]'te, <title><s:text name="HelloWorld.message"/></title> etiketinin ve <h2><s:property value="message"/></h2> etiketinin etkisini göstermediğini görüyoruz. Bunun nedeni, hiçbir eylemin çağrılmamış olmasıdır. Dolayısıyla, eylemden önce çalıştırılan yakalayıcılar listesi, özellikle de uluslararasılaştırmayı yöneten yakalayıcı, çalıştırılmamıştır. Uluslararasılaştırma etiketi <s:text ...> doğru şekilde işlenemedi. Ayrıca, Action1 sınıfının message alanına referans veren message özelliği mevcut değildir. Bu nedenle sayfa görüntülenmemiştir.

Şimdi, [English] bağlantısını takip edelim. Aşağıdaki sayfaya ulaşırız:

  • [1]'te, istenen URL'e yönlendiriliyoruz. Bu URL adresinin oluşumunu daha önce açıklamıştık. Bu sefer bir Struts eylemi isteniyor: [example.xml] içinde tanımlanan HelloWorld eylemi.

<struts>
    <package name="example" namespace="/example" extends="struts-default">
        <action name="HelloWorld" class="example.HelloWorld">
            <result>/example/HelloWorld.JSP</result>
        </action>
    </package>
</struts>
  • Bu eylemin execute yöntemi yürütüldü. Bu yöntemin success anahtarını döndürdüğünü görmüştük. Yukarıdaki 4. satırdan, /example/HelloWorld.JSP sayfasının müşteriye yanıt olarak geri gönderildiği sonucuna varabiliriz. Bunu [3]'te görüyoruz.
  • [1] adresinde, istenen URL sayfasının request_locale=en parametresiyle ayarlandığını görüyoruz. Artık sayfaların dili İngilizce olacaktır. Nitekim bu dil seçimi, kullanıcı oturumunda saklanır ve kullanıcı bu seçimi değiştirene kadar geçerliliğini korur.
  • [2] ve [3] örneklerinde, uluslararasılaştırma sürecinin işleyişini görebiliriz. <title><s:text name="HelloWorld.message"/></title> ve <h2><s:property value="message"/></h2> etiketleri bu sefer istenen sonucu verdi.

Şimdi [Espanol] bağlantısını seçersek, sayfayı İspanyolca olarak görürüz:

2.9. Conclusion

NetBeans için Struts 2 eklentisi tarafından otomatik olarak oluşturulan bir örneği inceledik. Bir isteğin işleyişini takip etmenin oldukça zor olduğunu gördük. Aşağıdaki unsurlar devreye giriyor:

  • [web.xml], [struts.xml] yapılandırması
  • yürütülen eylem: yakalayıcılar ve execute yöntemi.

Başlangıçta Struts 2'nin işleyişi karmaşık görünebilir. Buna alışmak biraz zaman alır. Şimdi, Struts'un her bir özel noktasını açıklayan bir dizi örnek sunacağız.