pengenalan
Seperti yang kita ketahui, kejayaan Java datang dengan tepat berkat evolusi perisian yang berusaha untuk menyambung ke rangkaian. Oleh itu, kami akan mengambil aplikasi konsol biasa " Hello World " sebagai asas dan memahami apa yang diperlukan untuk menjadi aplikasi rangkaian daripada aplikasi konsol. Jadi, pertama anda perlu membuat projek Java. Pengaturcara adalah orang yang malas. Pada zaman prasejarah, apabila ada yang memburu mamut, yang lain duduk dan cuba untuk tidak keliru dalam pelbagai jenis perpustakaan dan struktur direktori Java. Supaya pembangun dapat mengawal proses mencipta aplikasi, supaya dia boleh menulis "Saya mahukan perpustakaan versi 2 ini dan itu", mereka datang dengan alat khas - membina sistem. Dua yang paling terkenal ialah Maven dan Gradle . Untuk artikel ini kami akan menggunakan Gradle. Jika sebelum ini kita perlu membuat struktur direktori sendiri, kini Gradle, menggunakan Gradle Init Plugin, membolehkan kita mencipta projek Java dengan struktur direktori dan kelas Utama asas dalam satu arahan:gradle init --type java-application
Perintah ini melakukan pemula (init) untuk kami aplikasi Java (java-application ) dengan konsol Hello World. Selepas selesai, fail akan muncul dalam direktori - build.gradle . Ini ialah skrip binaan kami - iaitu skrip tertentu untuk mencipta aplikasi dengan penerangan tentang tindakan yang perlu dilakukan untuk ini. Mari bukanya dan tambah baris padanya: jar.baseName = 'webproject'
Gradle membenarkan anda melakukan pelbagai tindakan pada projek dan tindakan ini dipanggil tugasan . Dengan melaksanakan perintah (tugas) fail JAR akan dibuat gradle build
dalam direktori /build/libs . Dan, seperti yang anda sangka, namanya kini akan menjadi webproject.jar . Tetapi jika kita melaksanakan java -jar ./build/libs/webproject.jar
, kita akan mendapat ralat: no main manifest attribute
. Ini kerana untuk aplikasi java anda perlu melampirkan manifes - ini ialah penerangan tentang cara bekerja dengan aplikasi itu, cara melihatnya. Kemudian JVM, yang akan melaksanakan aplikasi java, akan mengetahui kelas mana yang menjadi titik masuk kepada program dan maklumat lain (contohnya, classpath). Jika kita melihat dengan lebih dekat kandungan skrip binaan, kita akan melihat pemalam disambungkan. Contohnya: apply plugin: 'java'
Jika kita pergi ke halaman Gradle Java Plugin , kita dapat melihat bahawa kita boleh mengkonfigurasi manifes:
jar {
manifest {
attributes 'Main-Class': 'App'
}
}
Kelas utama, titik masuk kepada program, telah dihasilkan untuk kami oleh Gradle Init Plugin. Dan ia juga dinyatakan dalam parameter mainClassName. Tetapi ini tidak sesuai dengan kami, kerana... tetapan ini merujuk kepada pemalam lain, Gradle Application Plugin . Jadi, kami mempunyai aplikasi Java yang memaparkan Hello World pada skrin. Aplikasi Java ini dibungkus dalam JAR (Java ARchive). Ia mudah, berasaskan konsol, tidak terkini. Bagaimana untuk mengubahnya menjadi aplikasi web?
API Servlet
Agar Java dapat berfungsi dengan rangkaian, spesifikasi yang dipanggil Servlet API muncul kembali pada zaman dahulu . Spesifikasi inilah yang menerangkan interaksi pelanggan-pelayan, menerima mesej daripada klien (contohnya, penyemak imbas) dan menghantar respons (contohnya, dengan teks halaman). Sememangnya, banyak yang telah berubah sejak itu, tetapi maksudnya ialah agar aplikasi Java menjadi aplikasi web, API Servlet digunakan. Untuk tidak membuat spekulasi secara tidak berasas, mari kita ambil spesifikasi itu: JSR-000340 JavaTM Servlet 3.1 . Pertama sekali, kami berminat dengan " Bab 1: Gambaran Keseluruhan ". Ia menerangkan konsep asas yang mesti kita fahami. Pertama, apakah itu servlet? Bab " 1.1 Apakah Servlet? " mengatakan bahawa Servlet ialah komponen Java yang diuruskan oleh bekas dan yang menjana kandungan dinamik. Seperti komponen Java yang lain, servlet ialah kelas Java yang disusun menjadi bytecode dan boleh dimuatkan ke dalam pelayan web menggunakan teknologi Java. Adalah penting bahawa servlet berinteraksi dengan klien web (contohnya, pelayar) dalam rangka kerja paradigma permintaan/tindak balas, yang dilaksanakan oleh Kontena Servlet. Ternyata Servlet tinggal dalam beberapa jenis Bekas Servlet. Apakah ini? Dalam bab " 1.2 Apakah itu Kontena Servlet? " dikatakan bahawa Kontena Servlet ialah sebahagian daripada pelayan web atau pelayan aplikasi yang menyediakan perkhidmatan rangkaian yang melaluinya permintaan dihantar dan respons dihantar. Bekas Servlet ini menguruskan kitaran hayat servlet. Semua Bekas Servlet dikehendaki menyokong protokol HTTP sekurang-kurangnya, tetapi mungkin menyokong yang lain. Contohnya, HTTPS. Adalah penting juga bahawa Kontena Servlet boleh mengenakan sebarang sekatan berkaitan keselamatan ke atas persekitaran di mana servlet dilaksanakan. Ia juga penting bahawa menurut " 10.6 Fail Arkib Aplikasi Web " aplikasi web mesti dibungkus dalam fail WAR (Arkib Web). Iaitu, sekarang kita perlu mengalih keluar balang dan pemalam aplikasi untuk sesuatu yang lain. Dan ini ialah pemalam Gradle WAR . Dan bukannya jar.baseName tentukan war.baseName Kerana Memandangkan kami tidak lagi menggunakan pemalam jar, kami juga telah mengalih keluar tetapan manifes. Apabila kami melancarkan JAR, Mesin Maya Java (JVM) perlu diberitahu melalui manifes cara bekerja dengan aplikasi kami. Kerana JVM menjalankannya. Aplikasi web, nampaknya, dilaksanakan oleh beberapa jenis pelayan web. Nampaknya dia perlu memberitahunya bagaimana untuk bekerja dengan aplikasi web kami? Dan ternyata ya. Aplikasi web mempunyai manifesto khas mereka sendiri. Ia dipanggil Deskriptor Deployment . Seluruh bahagian didedikasikan untuknya: “ 14. Deskriptor Deployment ”. Terdapat bahagian penting: " Bab 10:". Ia bercakap tentang aplikasi web dari sudut pandangan API Servlet. Contohnya, dalam bab " 10.5 Struktur Direktori " ia ditunjukkan di mana Deskriptor Deployment sepatutnya:/WEB-INF/web.xml
. Di mana hendak meletakkan WEB-INF? Seperti yang dinyatakan dalam pemalam Gradle WAR , ia menambah susun atur baharu : src/main/webapp
. Oleh itu, mari kita cipta direktori sedemikian, di dalamnya kita akan mencipta direktori WEB-INF, dan di dalamnya kita akan mencipta fail web.xml. Adalah penting bahawa direktori itu dipanggil WEB-INF, dan bukan META-INF! Mari salin daripada " 14.5.1 Contoh Asas " contoh XML:
specification is available at http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd
Iaitu, kita perlu menggantikan pautan ke skema dengan xsd yang ditentukan di mana-mana, tidak lupa menukarnya version="2.5"
kepada 3.1, dan juga menukar ruang nama di mana-mana ( xmlns dan dalam xsi:schemaLocation). Mereka menunjukkan dalam ruang nama yang mana kami akan bekerja (secara ringkasnya, nama elemen apa yang boleh kami gunakan). Jika anda membuka fail skema, targetNamespace akan mengandungi ruang nama yang sama yang harus kami tentukan:
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class App extends HttpServlet {
public String getGreeting() {
return "Hello world.";
}
public void doGet(HttpServletRequest request, HttpServletResponse response) {
response.setContentType("text/html");
try {
response.getWriter().println(getGreeting());
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
}
Tetapi projek kami belum siap lagi. Kerana kami kini bergantung pada Servlet API versi 3.1. Ini bermakna dalam skrip binaan kami, kami perlu menunjukkan pergantungan pada API Servlet. JVM perlu tahu bahawa apa yang anda tulis dalam kod adalah betul dan cara menggunakannya. Seperti yang kita ingat, spesifikasi pada asasnya hanyalah antara muka yang menerangkan bagaimana semuanya harus berfungsi. Dan pelaksanaannya terletak pada bahagian pelayan web. Oleh itu, tanpa API Servlet akan ada Cari perpustakaan yang diperlukan pada Maven Central: javax.servlet-api . Dan tambahkan entri pada blok dependencies . Dalam repositori Maven, seperti yang anda lihat, ia mengatakan disediakan. Sebelum menggunakan kebergantungan, anda mesti menentukan skop. Gradle tidak mempunyai skop bernama "disediakan", tetapi ia mempunyai skop " compile only ". Oleh itu, kami akan menunjukkan: providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
Ugh, semuanya nampaknya baik-baik saja? Gradle Build akan membina projek kami menjadi fail WAR. Dan apa yang perlu kita lakukan seterusnya dengannya? Pertama, kita memerlukan Pelayan Web. Di Google kami menulis " senarai java pelayan web " dan melihat senarai pelayan web. Mari pilih daripada senarai ini, contohnya, TomCat . Pergi ke tapak web Apache Tomcat , muat turun versi terkini (kini versi 9) sebagai arkib zip (jika untuk Windows). Buka bungkusannya ke dalam beberapa direktori. Hore, kami mempunyai pelayan web. Daripada direktori pelayan web dalam subdirektori bin , kami melaksanakan catalina dari baris arahan dan melihat pilihan yang tersedia. Jom buat: catalina start
. Setiap pelayan web mempunyai direktori yang dipantau oleh pelayan web. Jika fail aplikasi web muncul di sana, pelayan web mula memasangnya. Pemasangan ini dipanggil deployment atau deployment . Ya ya, itulah sebabnya " deskriptor penempatan ". Iaitu, cara menggunakan aplikasi dengan betul. Dalam Tomcat direktori ini ialah webapps . Mari salin perang yang kami buat menggunakan gradle build di sana. Selepas ini, dalam log kita akan melihat sesuatu seperti: Deployment of web application archive [tomcat\webapps\webproject.war] has finished in [время] ms
Untuk memahami dengan lebih baik, dalam direktori tomcat kita akan mengedit fail \conf\tomcat-users.xml
, menambah baris berikut:
http://127.0.0.1:8080/manager
Di sini kita akan melihat laluan semua aplikasi. Projek web kami kemungkinan besar diberi laluan /projek web. Apakah laluan ini? Spesifikasi dalam bab " 10.1 Aplikasi Web Dalam Pelayan Web " menyatakan bahawa aplikasi web dikaitkan dengan beberapa laluan dalam aplikasi (dalam kes ini, /webproject). Semua permintaan melalui laluan ini akan dikaitkan dengan ServletContext yang sama. Laluan ini juga dipanggil contextRoot . Dan menurut " 10.2 Hubungan dengan ServletContext " bekas servlet mengaitkan aplikasi web dan ServletContext satu dengan satu. Iaitu, setiap aplikasi web mempunyai ServletContext sendiri. Apakah ServletContext ? Seperti yang dinyatakan dalam spesifikasi, ServletContext ialah objek yang menyediakan servlet dengan "pandangan aplikasi " di mana ia dijalankan. Konteks Servlet diterangkan dengan lebih terperinci dalam Bab 4 spesifikasi API Servlet. Anehnya, Servlet API dalam versi 3.1 tidak lagi memerlukan web.xml untuk hadir. Sebagai contoh, anda boleh menentukan servlet menggunakan anotasi:
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/app2")
public class App2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
response.getWriter().println("app2");
}
}
Juga disyorkan pada topik: " Temuduga EE Java - API Servlet JEE (Soalan dan Jawapan) ". Jadi, kami mempunyai Servlet - ia bertanggungjawab untuk respons yang perlu diberikan kepada pelanggan web. Kami mempunyai ServletContainer yang menerima permintaan daripada pengguna, sepadan dengan laluan yang telah diakses dengan laluan ke servlet, dan jika padanan ditemui, laksanakan Servlet. baik. Apakah tempat yang diduduki Spring dalam gambar dunia ini ?
MVC Web Musim Bunga
Hebat, kami mempunyai aplikasi web. Sekarang kita perlu menyambung Spring. Bagaimana kita boleh melakukan ini? Pertama, anda perlu memikirkan cara menyambung Spring dengan betul ke projek anda. Ternyata sebelum ini adalah mungkin untuk melakukan ini mengikut dokumentasi projek platform Spring , tetapi kini " Platform akan mencapai penghujung hayatnya yang disokong pada 9 April 2019 ", iaitu, tidak digalakkan untuk gunakannya, kerana tidak lama lagi ia tidak akan disokong lagi. Satu-satunya jalan keluar ialah " Pengguna Platform digalakkan untuk mula menggunakan pengurusan pergantungan Spring Boot ". Oleh itu, mari kita beralih kepada dokumentasi Spring Boot . Biar saya jelaskan bahawa kami tidak menggunakan Spring Boot itu sendiri, tetapi hanya Pengurusan Ketergantungan daripada Spring Boot. Iaitu, projek Spring Boot boleh memberikan pengetahuan tentang versi perpustakaan yang hendak digunakan (termasuk Spring MVC). Di sana kita akan dapati 3.2. Menggunakan pengurusan pergantungan Spring Boot secara berasingan . Menurut dokumentasi, tambahkan yang berikut pada skrip binaan:plugins {
id 'org.springframework.boot' version '2.0.4.RELEASE' apply false
}
apply plugin: 'io.spring.dependency-management'
Dan
dependencyManagement {
imports {
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
}
}
Seperti yang anda lihat, kami menunjukkan apply false
, i.e. Kami tidak menggunakan Spring Boot itu sendiri, tetapi kami menggunakan pengurusan pergantungan dari sana. Pengurusan pergantungan ini juga dipanggil BOM - " Bill Of Materials ". Kini kami bersedia untuk menyambung projek Spring Web MVC itu sendiri. Spring Web MVC ialah sebahagian daripada projek Spring Framework dan kami berminat dengan bahagian " Web Servlet ". Mari tambahkan kebergantungan pada skrip binaan: compile 'org.springframework:spring-webmvc'
. Seperti yang dapat kita lihat, kita menetapkan penyusunan skop, kerana pelayan web tidak memberikan kami Spring. Projek kami terpaksa memasukkan perpustakaan Spring di dalam dirinya sendiri. Seterusnya, adalah penting untuk kita membaca bahagian " 1.2. DispatcherServlet ", di mana dikatakan bahawa Spring MVC dibina di sekitar corak " Pengawal hadapan ", di mana terdapat beberapa jenis servlet pusat yang menyediakan konfigurasi dan delegasi kepada komponen lain. . Penghantar boleh diterjemahkan sebagai penghantar. Jadi, pertama sekali, dalam web.xml kami mengisytiharkan:
applicationContext.xml
yang kami tentukan sebelum ini. Mari kita ambil contoh daripada dokumentasi Spring: " 1.10.3. Mengesan kelas secara automatik dan mendaftar definisi kacang ".
-
Konfigurasi web contohnya konfigurasi gaya Java:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp("/WEB-INF/pages/", ".jsp"); } @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
Contoh ini diterangkan dalam dokumentasi Spring Framework: " 1.11. MVC Config ".
Di sini kami mendaftarkan ViewResolver, yang akan membantu menentukan di mana halaman jsp berada. Kaedah kedua memastikan bahawa " Default servlet " didayakan.
Anda boleh membaca lebih lanjut tentang ini di sini: " Apakah keperluan dan penggunaan default-servlet-handler ".
-
Pengawal HelloController untuk menerangkan pemetaan permintaan kepada JSP tertentu
@Controller public class HelloController { @GetMapping("/hello") public String handle(Model model) { return "hello"; } }
Di sini kami telah menggunakan anotasi @Controller yang diterangkan dalam dokumentasi dalam bab " 1.4. Pengawal Beranotasi ".
/webproject/hello
(di mana /webproject ialah akar konteks), DispatcherServlet akan diproses terlebih dahulu. Beliau, sebagai penghantar utama, akan menentukan bahawa kami /* sepadan dengan permintaan semasa, yang bermaksud bahawa DispatcherServlet mesti melakukan sesuatu. Kemudian ia akan melalui semua pemetaan yang ditemuinya. Ia akan melihat bahawa terdapat HelloController dengan kaedah pemegang yang dipetakan ke /hello dan akan melaksanakannya. Kaedah ini akan mengembalikan teks "hello". Teks ini akan diterima oleh ViewResolver, yang akan memberitahu pelayan tempat untuk mencari fail jsp yang perlu dipaparkan kepada klien. Oleh itu, pelanggan akhirnya akan menerima halaman yang sangat dihargai itu.
GO TO FULL VERSION