<Jsp: useBean> olmadan neden <jsp: getProperty> kullanamıyorum?

Jan 01 2021

Diyelim ki kodu olan sunucu uygulaması:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    foo.Person p = new foo.Person("Evan");
    req.setAttribute("person", p);

    RequestDispatcher view = req.getRequestDispatcher("/result.jsp");
    view.forward(req, resp);
}

, bu, result.jspverilen adı (Evan) yazdırmaya gider . İşte nasıl görüneceğine dair bir resim (kaynak Head First Servlets ve JSP):

Aynı istek kapsamında oldukları için <jsp:useBean>çağırarak aynı Person nesnesini döndürdüğünü biliyorum . Diğer tarafta da, arayacak anlamıyla değer "kişi" niteliğini bulmaya .. ve sonunda baskı Evan .getAttribute()<jsp:getProperty>findAttribute()

Ama ya kullanmazsam <jsp:useBean>? Bu, kapsam isteği üzerine "kişi" özelliğine erişemediğim anlamına mı geliyor ? Ben, hala çıkmasına neden bile kullandığım olmasaydı <jsp:useBean>.ben aynı olmalıdır yüzden değerini hem iç ( "kişi") kimliği içinde <jsp:useBean>ve adı içeriden <jsp:getProperty>? Basit kaldırma <jsp:useBean>programımı bozuyor.

<jsp:getProperty>Çağrıları bilmek, kapsamlar sayfası> istek> oturum> uygulamada öznitelikleri bulmak için bağımsız değişken olarak kullanılacak findAttribute()tek bir öznitelik ( öznitelik-adı gibi ) olsaydı daha mantıklı olmaz mıydı ? Neden bu iki etiketi "bağlamalıyım": ve ?<jsp:useBean><jsp:getProperty>

Yanıtlar

2 LiveandLetLive Jan 01 2021 at 03:03

Aşağıdaki kod hakkında ne düşünüyorsunuz?

public class Main {
    public static void main(String[] args) {
        System.out.println(person);
    }
}

Başarıyla derlenmeyeceğini zaten doğru bir şekilde tahmin etmiş olmalısınız .

Şimdi, aşağıdaki kod ne olacak?

public class Main {
    public static void main(String[] args) {
        Person person = new Person();// Declaring person
        System.out.println(person);
    }
}

Tabii ki, başarıyla derlenecektir 1 çünkü artık derleyici ne personolduğunu anlıyor .

Benzer şekilde, kullanarak

<jsp:getProperty name="person" property="name">

personolarak ilan etmeden

<!-- Declaring person -->
<jsp:useBean id="person" class="foo.Person" scope="request" />

başarıyla derlenmeyecek .


1 Person.classOrada olduğunu varsayarsak .

1 Bogdan Jan 01 2021 at 18:18

TL; DR: Sadece kullanmak gerektiğini hatırlamalıyız <jsp:getProperty>ile <jsp:useBean>şartname öyle diyor çünkü. <jsp:useBean>fasulyeyi <jsp:getProperty>kullanmadan önce JSP işlemciye tanıtması gerekir.

Daha uzun açıklama:

Neden <jsp:getProperty>onsuz kullanamıyorum <jsp:useBean>?

Çünkü "bir şekilde" birlikte çalışmak üzere tasarlanmışlardı. Neden böyle karar verildiğini bilmiyorum (bunu sadece JSP spesifikasyonunun tasarımcıları cevaplayabilir), ancak spesifikasyonun kendisi hakkında söyleyecekleri var <jsp:getProperty>:

Ada göre adlandırılan nesne, jsp: useBean eylemi veya bu ad için ilişkili bir VariableInfo girişine sahip özel bir eylem kullanılarak JSP işlemcisine "tanıtılmış" olmalıdır. Nesne bu şekilde tanıtılmadıysa, sayfa uygulaması belirtimi ihlal ettiğinden, kapsayıcı uygulamasının bir çeviri hatası oluşturması önerilir (ancak gerekli değildir).

"Biraz" birlikte çalışmak için tasarlanmış diyorum, çünkü bazı durumlarda <jsp:getProperty>onsuz kullanabilirsiniz <jsp:useBean>, ancak JSP işlemcisini JSP.5.3 belirtim kuralını yok sayacak şekilde yapılandırmanız gerekir (buna izin veren sunucular için).

Bu çok net değil, bu yüzden bazı kodlarla ne olacağını görelim.

Aşağıdaki JSP'ye sahibim:

-------------------------------------------------------------------
<jsp:useBean id="person" class="test.Person" scope="application" />
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
<jsp:getProperty name="person" property="name" />
-------------------------------------------------------------------

Bu sınırlayıcıları daha sonra JSP tarafından oluşturulan sunucu uygulamasında bulabilmem için kullandım, burada şu kodla sonuçlanıyorlar:

  out.write("\t\t-------------------------------------------------------------------\r\n");
  out.write("\t\t");
  test.Person person = null;
  synchronized (application) {
    person = (test.Person) _jspx_page_context.getAttribute("person", javax.servlet.jsp.PageContext.APPLICATION_SCOPE);
    if (person == null){
      person = new test.Person();
      _jspx_page_context.setAttribute("person", person, javax.servlet.jsp.PageContext.APPLICATION_SCOPE);
    }
  }
  out.write("\r\n");
  out.write("\t\t+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n");
  out.write("\t\t");
  out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString((((test.Person)_jspx_page_context.findAttribute("person")).getName())));
  out.write("\r\n");
  out.write("\t\t-------------------------------------------------------------------\r\n");

Eğer bakarsanız, <jsp:getProperty>bunun bir döküm yaptığını görebilirsiniz test.Person:

org.apache.jasper.runtime.JspRuntimeLibrary.toString((((test.Person)_jspx_page_context.findAttribute("person")).getName()))

Ama bu nereden geldi? Gözlerinde farklı <jsp:getProperty>bir fasulye adını (belirtmek person) ve bir özellik adını ( name), ancak hiçbir sınıf. Yani bu nitelikler yalnızca sonuçlanır findAttribute("person")ve sonra sonuçlanır getName(). Ders nereden alındı? Ve cevap şu ki, <jsp:useBean>bunu JSP işlemciye tanıtmak için yapılan önceki çağrı .

Bu yüzden <jsp:useBean>, fasulyeyi JSP işlemcisine tanıtmak için aramanız gerekir, böylece işlemci <jsp:getProperty>onu gördüğünde neyle uğraştığını bilir. Yani temelde <jsp:useBean>onu tanımlar, sonra <jsp:getProperty>kullanır. Eğer aramazsan <jsp:useBean>, <jsp:getProperty>JSP işlemcisi şikayet tanımsız bir şey kullanmaya çalışır ve bir istisna geri almak:

jsp: 'person' adlı fasulye için getProperty. Ad, daha önce JSP'ye göre tanıtılmamıştı.5.3

Ancak özellikleri okursanız, şöyle der:

[...] bir çeviri hatası oluşturmak için kapsayıcı uygulaması önerilir (ancak zorunlu değildir) [...]

Örneğin Tomcat kullanıyorsanız, org.apache.jasper.compiler.Generator.STRICT_GET_PROPERTYkullanılan nesnenin <jsp:getProperty>daha önce JSP işlemcisine "tanıtılması" gerekliliğini kontrol eden bir sistem özelliği vardır (temelde, JSP.5.3 kuralını uygulamak veya uygulamamak). Örneğin bu Tomcat dokümantasyon sayfasına bakın .

Öyleyse, Tomcat sunucumu bir sistem değişkeni ile başlatırsam:

-Dorg.apache.jasper.compiler.Generator.STRICT_GET_PROPERTY=false

Sonra kullanabilirsiniz <jsp:getProperty>olmadan <jsp:useBean>ben tanıtmak sağlanmaktadır, personbir servlet gelen gibi (FASULYE İÇİNDE BAZI KAPSAMI BAŞKA BİR YOL request.setAttribute(), session.setAttribute()ya application.setAttribute()böylece <jsp:getProperty>bir yapabilirsiniz pageContext.findAttribute()adında bir fasülye ve görünüm personve onu bulmak.

Bu sistem özelliğini kullanırsanız, <jsp:getProperty>etiket tarafından oluşturulan çıktı değişir. Artık buna bağlı değildir <jsp:useBean>ve oyuncu kadrosu kaldırılır:

out.write("\t\t+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n");
      out.write("\t\t");
      out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString(org.apache.jasper.runtime.JspRuntimeLibrary.handleGetProperty(_jspx_page_context.findAttribute("person"), "name")));
      out.write("\r\n");
      out.write("\t\t-------------------------------------------------------------------\r\n");

Birisi tüm bu karmaşanın nasıl ortaya çıktığıyla ilgileniyorsa, bakılacak sınıflar (bir Tomcat sunucusu için): org.apache.jasper.compiler.Validatorve org.apache.jasper.compiler.Generator.