Pertanyaan Bagaimana cara menghindari kode Java di file JSP?


Saya baru mengenal Java EE dan saya tahu bahwa sesuatu seperti tiga baris berikut

<%= x+1 %>
<%= request.getParameter("name") %>
<%! counter++; %>

adalah cara lama sekolah coding dan di JSP versi 2 ada metode untuk menghindari kode Java di file JSP. Dapatkah seseorang tolong beri tahu saya jalur JSP 2 alternatif, dan apa teknik ini disebut?


1522
2017-07-05 07:24


asal


Jawaban:


Penggunaan skriplet (itu <% %> hal-hal) di JSP memang sangat putus asa sejak lahirnya taglibs (seperti JSTL) dan EL (Bahasa Ekspresi, itu ${} hal) kembali pada tahun 2001.

Kerugian utama dari skriplet adalah:

  1. Reusability: Anda tidak dapat menggunakan kembali skriplet.
  2. Dapat diganti: Anda tidak bisa membuat abstrak skriplet.
  3. Kemampuan OO: Anda tidak dapat menggunakan warisan / komposisi.
  4. Debuggability: jika scriptlet mengeluarkan pengecualian di tengah jalan, yang Anda dapatkan hanyalah halaman kosong.
  5. Testability: scriptlets tidak dapat diuji unit.
  6. Maintainability: per pulsa lebih banyak waktu diperlukan untuk menjaga logika kode mingled / cluttered / duplicated.

Matahari Oracle sendiri juga merekomendasikan di Konvensi pengkodean JSP untuk menghindari penggunaan skriplet kapan pun fungsi yang sama dimungkinkan oleh kelas (tag). Berikut beberapa kutipan relevansi:

Dari JSP 1.2 Spesifikasi, sangat disarankan agar Perpustakaan Tag Standar JSP (JSTL) digunakan dalam aplikasi web Anda untuk membantu mengurangi kebutuhan untuk scriptlets JSP di halaman Anda. Halaman-halaman yang menggunakan JSTL, secara umum, lebih mudah dibaca dan dipelihara.

...

Di mana mungkin, hindari skrip JSP kapan pun pustaka tag menyediakan fungsionalitas yang setara. Hal ini membuat halaman lebih mudah dibaca dan dipelihara, membantu memisahkan logika bisnis dari logika presentasi, dan akan membuat halaman Anda lebih mudah untuk berevolusi menjadi halaman-halaman JSP 2.0-style (Spesifikasi JSP 2.0 mendukung tetapi tidak menekankan penggunaan scriptlets).

...

Dalam semangat mengadopsi pola desain model-view-controller (MVC) untuk mengurangi penggabungan antara tingkat presentasi dari logika bisnis, Scriptlets JSP tidak boleh digunakan untuk menulis logika bisnis. Sebaliknya, scriptlets JSP digunakan jika diperlukan untuk mengubah data (juga disebut "objek nilai") kembali dari memproses permintaan klien ke dalam format klien-siap yang tepat. Bahkan kemudian, ini akan lebih baik dilakukan dengan servlet pengontrol depan atau tag khusus.


Bagaimana cara mengganti skriplet sepenuhnya bergantung pada satu-satunya tujuan dari kode / logika. Lebih dari sering kode ini harus ditempatkan dalam kelas Java yang lengkap:

  • Jika Anda ingin memohon sama Kode Java aktif setiap permintaan, kurang-atau-lebih terlepas dari halaman yang diminta, mis. memeriksa apakah seorang pengguna login, lalu terapkan menyaring dan tulis kode yang sesuai di doFilter() metode. Misalnya.:

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
            ((HttpServletResponse) response).sendRedirect("login"); // Not logged in, redirect to login page.
        } else {
            chain.doFilter(request, response); // Logged in, just continue request.
        }
    }
    

    Ketika dipetakan pada yang sesuai <url-pattern>menutupi halaman JSP yang menarik, maka Anda tidak perlu menyalin kode yang sama pada semua halaman JSP.


  • Jika Anda ingin menjalankan beberapa kode Java preprocess permintaan, mis. pramuat beberapa daftar dari database untuk ditampilkan di beberapa tabel, jika perlu berdasarkan beberapa parameter kueri, lalu terapkan servlet dan tulis kode yang sesuai di doGet() metode. Misalnya.:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            List<Product> products = productService.list(); // Obtain all products.
            request.setAttribute("products", products); // Store products in request scope.
            request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response); // Forward to JSP page to display them in a HTML table.
        } catch (SQLException e) {
            throw new ServletException("Retrieving products failed!", e);
        }
    }
    

    Cara ini berhubungan dengan pengecualian lebih mudah. DB tidak diakses di tengah-tengah rendering JSP, tetapi jauh sebelum JSP ditampilkan. Anda masih memiliki kemungkinan untuk mengubah respon setiap kali akses DB melempar pengecualian. Dalam contoh di atas, kesalahan default 500 halaman akan ditampilkan yang dapat Anda sesuaikan dengan suatu <error-page> di web.xml.


  • Jika Anda ingin menjalankan beberapa kode Java postprocess permintaan, mis. memproses formulir kirim, kemudian menerapkan servlet dan tulis kode yang sesuai di doPost() metode. Misalnya.:

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = userService.find(username, password);
    
        if (user != null) {
            request.getSession().setAttribute("user", user); // Login user.
            response.sendRedirect("home"); // Redirect to home page.
        } else {
            request.setAttribute("message", "Unknown username/password. Please retry."); // Store error message in request scope.
            request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to JSP page to redisplay login form with error.
        }
    }
    

    Cara ini berhubungan dengan tujuan halaman hasil yang berbeda lebih mudah: menampilkan ulang formulir dengan kesalahan validasi jika terjadi kesalahan (dalam contoh khusus ini Anda dapat menampilkan kembali menggunakan ${message} di EL), atau hanya mengambil ke halaman target yang diinginkan dalam hal keberhasilan.


  • Jika Anda ingin menjalankan beberapa kode Java kontrol rencana eksekusi dan / atau tujuan dari permintaan dan tanggapan, kemudian terapkan servlet menurut Pola Pengontrol Depan MVC. Misalnya.:

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            Action action = ActionFactory.getAction(request);
            String view = action.execute(request, response);
    
            if (view.equals(request.getPathInfo().substring(1)) {
                request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
            } else {
                response.sendRedirect(view);
            }
        } catch (Exception e) {
            throw new ServletException("Executing action failed.", e);
        }
    }
    

    Atau hanya mengadopsi kerangka MVC seperti JSF, Spring MVC, Gawang, dll sehingga Anda berakhir hanya dengan halaman JSP / Facelets dan kelas Javabean tanpa perlu servlet khusus.


  • Jika Anda ingin menjalankan beberapa kode Java mengendalikan aliran di dalam halaman JSP, maka Anda perlu mengambil (tag) kontrol aliran (ada) seperti Inti JSTL. Misalnya. menampilkan List<Product> dalam sebuah tabel:

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    ...
    <table>
        <c:forEach items="${products}" var="product">
            <tr>
                <td>${product.name}</td>
                <td>${product.description}</td>
                <td>${product.price}</td>
            </tr>
        </c:forEach>
    </table>
    

    Dengan tag bergaya XML yang cocok di antara semua HTML itu, kode lebih mudah dibaca (dan dengan demikian lebih mudah dipelihara) daripada sekelompok skrip dengan berbagai pembuka dan penutup tanda kurung ("Di mana sih penjepit penutup ini milik?"). Bantuan yang mudah adalah mengkonfigurasi aplikasi web Anda untuk melempar pengecualian kapan pun skriplet masih digunakan dengan menambahkan potongan berikut web.xml:

    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <scripting-invalid>true</scripting-invalid>
        </jsp-property-group>
    </jsp-config>
    

    Di Facelet, penerus JSP, yang merupakan bagian dari Java EE yang menyediakan kerangka MVC JSFsudah tidak mungkin untuk digunakan skriplet. Dengan cara ini Anda secara otomatis dipaksa untuk melakukan hal-hal "dengan cara yang benar".


  • Jika Anda ingin menjalankan beberapa kode Java akses dan tampilan "Backend" data di dalam halaman JSP, maka Anda perlu menggunakan EL (Expression Language), itu ${} sesuatu. Misalnya. menampilkan ulang nilai masukan yang dikirimkan:

    <input type="text" name="foo" value="${param.foo}" />
    

    Itu ${param.foo} menampilkan hasil dari request.getParameter("foo").


  • Jika Anda ingin meminta beberapa utilitas Kode Java langsung di halaman JSP (biasanya public static metode), maka Anda perlu mendefinisikannya sebagai fungsi EL. Ada standarnya fungsi taglib di JSTL, tapi Anda juga dapat dengan mudah membuat fungsi sendiri. Berikut contoh bagaimana JSTL fn:escapeXml berguna untuk mencegah XSS  serangan.

    <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
    ...
    <input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />
    

    Perhatikan bahwa sensitivitas XSS sama sekali tidak terkait secara khusus dengan Java / JSP / JSTL / EL / apa pun, masalah ini perlu diperhitungkan dalam setiapaplikasi web yang Anda kembangkan. Masalahnya skriplet adalah bahwa ia tidak menyediakan cara pencegahan builtin, setidaknya tidak menggunakan API Java standar. Penerus JSP, Facelets, telah memustahilkan pelarian HTML, jadi Anda tidak perlu khawatir tentang lubang XSS di Facelets.

Lihat juga:


1852
2017-07-05 14:19



Sebagai Safeguard: Nonaktifkan Scriptlets For Good

Sebagai pertanyaan lain sedang membahas, Anda dapat dan selalu harus menonaktifkan scriptlets di blog Anda web.xml deskriptor aplikasi web.

Saya akan selalu melakukan itu untuk mencegah pengembang menambahkan skriplet, terutama di perusahaan yang lebih besar di mana Anda akan kehilangan ikhtisar cepat atau lambat. Itu web.xml pengaturan terlihat seperti ini:

<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
     <scripting-invalid>true</scripting-invalid>
  </jsp-property-group>
</jsp-config>

207
2017-08-14 21:59



JSTL menawarkan tag untuk conditional, loop, set, mendapat, dll. Misalnya:

<c:if test="${someAttribute == 'something'}">
   ...
</c:if>

JSTL bekerja dengan atribut permintaan - mereka paling sering diatur dalam permintaan oleh Servlet, yang ke depan ke JSP.


102
2017-07-05 07:28



Saya tidak yakin apakah saya mendapatkan ini benar.

Anda harus membaca sesuatu tentang MVC. Spring MVC & Struts 2 adalah dua solusi paling umum.


56
2017-07-05 07:29



Anda dapat menggunakan tag JSTL bersama dengan ekspresi EL untuk menghindari intermixing Java dan kode HTML:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<html>
    <head>
    </head>
    <body>

        <c:out value="${x + 1}" />
        <c:out value="${param.name}" />
    // and so on

    </body>
</html>

48
2017-07-05 08:45



Ada juga kerangka kerja berbasis komponen seperti Gawang yang menghasilkan banyak HTML untuk Anda. Tag yang berakhir di HTML sangat dasar dan hampir tidak ada logika yang tercampur. Hasilnya adalah halaman HTML yang hampir kosong dengan elemen HTML biasa. Kelemahannya adalah bahwa ada banyak komponen dalam Gawang API untuk belajar dan beberapa hal dapat menjadi sulit untuk dicapai di bawah batasan tersebut.


32
2018-03-22 18:24



Dalam pola Arsitektur MVC, JSP mewakili lapisan Tampilan. Menanamkan kode java di JSP dianggap sebagai praktik yang buruk. Kamu dapat memakai JSTL, freeMarker, kecepatan dengan JSP sebagai "mesin template". Penyedia data ke tag tersebut tergantung pada kerangka kerja yang Anda hadapi. Struts 2 dan webwork sebagai implementasi untuk penggunaan Pola MVC OGNL "Teknik yang sangat menarik untuk mengekspos Properti Kacang untuk JSP".


28
2018-02-04 10:41



Pengalaman menunjukkan bahwa JSP memiliki beberapa kekurangan, salah satunya sulit menghindari pencampuran markup dengan kode aktual.

Jika Anda bisa, maka pertimbangkan untuk menggunakan teknologi khusus untuk apa yang perlu Anda lakukan. Di Java EE 6 ada JSF 2.0, yang menyediakan banyak fitur bagus termasuk merekatkan kacang Java bersama dengan halaman JSF melalui #{bean.method(argument)} pendekatan.


25
2017-07-05 08:30