การแนะนำ
กาลครั้งหนึ่ง Java ได้เสริมความแข็งแกร่งให้กับตำแหน่งของตนเนื่องจากเลือกเว็บแอปพลิเคชันเป็นลำดับความสำคัญ ตั้งแต่วันแรก Java พยายามดิ้นรนเพื่อหาทาง ก่อนอื่นฉันแนะนำแอปเพล็ต นี่เป็นโอกาสมากมายสำหรับนักพัฒนาในการสร้างเนื้อหาแบบไดนามิกบนหน้า HTML แบบคงที่ อย่างไรก็ตาม แอปเพล็ตไม่เป็นไปตามความคาดหวังด้วยเหตุผลหลายประการ เช่น ความปลอดภัย ค่าใช้จ่าย และอื่นๆ จากนั้นนักพัฒนาภาษา Java ได้เสนอทางเลือกอื่น -
Servlet API . และกลายเป็นการตัดสินใจที่ถูกต้อง
Servlet APIเป็นข้อกำหนดที่ใช้สร้างเว็บแอปพลิเคชัน Java ใด ๆ ไม่ว่าจะเป็นแอปพลิเคชันบนเว็บหรือบริการเว็บที่ส่งคืนข้อมูลตามที่ร้องขอ ดังนั้นเส้นทางสู่การทำความเข้าใจวิธีการทำงานของเว็บแอปพลิเคชัน Java จึงเริ่มต้นด้วยการทำความเข้าใจ Servlet API
เซิร์ฟเล็ต API
ดังนั้น
Servlet APIคือสิ่งที่นักพัฒนาภาษาเสนอให้กับนักพัฒนา Java Servlet API เป็นข้อกำหนดที่ควรตอบคำถามหลักของเรา คุณสามารถค้นหาได้ที่นี่: "
JSR-000340 JavaTM Servlet 3.1 Final Release for Evalue " บทที่ "
1.1 Servlet คืออะไร " กล่าวว่า
เซิร์ฟเล็ตเป็นส่วนประกอบของเว็บที่ใช้เทคโนโลยี Java ที่สร้างเนื้อหาแบบไดนามิก (นั่นคือ เนื้อหา) "แบบ Java" หมายความว่า
เซิร์ฟเล็ตเป็นคลาส Java ที่คอมไพล์เป็น bytecode เซิร์ฟเล็ตได้รับการจัดการโดยคอนเทนเนอร์เซิร์ฟเล็ต ซึ่งบางครั้งเรียกว่า Servlet Engine
คอนเทนเนอร์เซิร์ฟเล็ตเป็นส่วนขยายของเว็บเซิร์ฟเวอร์ที่มีฟังก์ชันการทำงานของเซิร์ฟเล็ต ในทางกลับกัน เซิร์ฟเล็ตจัดให้มีการโต้ตอบกับไคลเอนต์ในกระบวนทัศน์คำขอ/ตอบกลับ ซึ่งถูกนำไปใช้โดยคอนเทนเนอร์เซิร์ฟเล็ต ในบท "
1.2 Servlet Container คืออะไร " ว่ากันว่า
คอนเทนเนอร์ servlet เป็นส่วนหนึ่งของเว็บเซิร์ฟเวอร์หรือแอปพลิเคชันเซิร์ฟเวอร์ที่ให้บริการเครือข่ายซึ่งมีการส่งคำขอและการตอบกลับ คำขอและการตอบกลับที่ใช้ MIME จะถูกสร้างและประมวลผล . นอกจากนี้ คอนเทนเนอร์เซิร์ฟเล็ตจะจัดการวงจรชีวิตของเซิร์ฟเล็ต (เช่น ตัดสินใจว่าจะสร้างเมื่อใด ลบออก ฯลฯ) คอนเทนเนอร์เซิร์ฟเล็ตทั้งหมดต้องรองรับโปรโตคอล HTTP เพื่อรับคำขอและส่งคำตอบ ในที่นี้ฉันต้องการเพิ่มเติมว่า MIME เป็นมาตรฐาน ซึ่งเป็นข้อกำหนดที่บอกว่าข้อมูลควรเข้ารหัสอย่างไรและจัดรูปแบบข้อความเพื่อให้สามารถส่งผ่านอินเทอร์เน็ตได้
เว็บเซิร์ฟเวอร์
เว็บเซิร์ฟเวอร์คือเซิร์ฟเวอร์ที่ยอมรับคำขอ HTTP จากไคลเอ็นต์ และจัดเตรียมการตอบกลับ HTTP (โดยปกติจะมาพร้อมกับเพจ HTML รูปภาพ ไฟล์ หรือข้อมูลอื่นๆ) ทรัพยากรที่ร้องขอจะถูกระบุโดย URL หนึ่งในเว็บเซิร์ฟเวอร์ยอดนิยมที่รองรับ Servlet API คือ
Apache Tomcat เว็บเซิร์ฟเวอร์ส่วนใหญ่เป็นเครื่องที่ซับซ้อนซึ่งประกอบด้วยส่วนประกอบต่างๆ ซึ่งแต่ละส่วนทำหน้าที่เฉพาะ ตัวอย่างเช่น:
ขั้วต่อ
— ที่อินพุต เรามีตัวเชื่อมต่อ (เช่น ตัวเชื่อมต่อ) ที่ยอมรับคำขอขาเข้าจากไคลเอนต์ ตัวเชื่อมต่อ HTTP ใน Tomcat ใช้งานโดยใช้ส่วนประกอบ "Coyote" ตัวเชื่อมต่อรับข้อมูลจากไคลเอ็นต์และส่งต่อไปยัง Tomcat Engine
Servlet Container - Tomcat Engine ในทางกลับกันจะประมวลผลคำขอที่ได้รับจากไคลเอนต์โดยใช้ส่วนประกอบ "Catalina" ซึ่งเป็นคอนเทนเนอร์เซิร์ฟเล็ต ดูเอกสารประกอบ Tomcat: "
ภาพรวมสถาปัตยกรรม " สำหรับรายละเอียดเพิ่มเติม มีเว็บเซิร์ฟเวอร์อื่นๆ ที่รองรับข้อกำหนด Servlet API ตัวอย่างเช่น "
Jetty " หรือ "
Undertow " สถาปัตยกรรมของพวกเขาคล้ายกัน ดังนั้น เมื่อเข้าใจหลักการทำงานกับเซิร์ฟเล็ตคอนเทนเนอร์หนึ่ง คุณจึงสามารถสลับไปทำงานกับคอนเทนเนอร์เซิร์ฟเล็ตอื่นได้
แอปพลิเคชันเว็บ
ดังนั้น เพื่อให้เราสามารถรันเว็บแอปพลิเคชันได้ เราจำเป็นต้องมีเว็บเซิร์ฟเวอร์ที่รองรับ Servlet API (นั่นคือ เซิร์ฟเวอร์ที่มีส่วนประกอบส่วนขยายที่ใช้การรองรับ Servlet API สำหรับเว็บเซิร์ฟเวอร์) ดี.
เว็บแอปพลิเคชันคืออะไร? ตามบท "
10 Web Applications " ของข้อกำหนดเฉพาะของ Servlet API
เว็บแอปพลิเคชันคือชุดของเซิร์ฟเล็ต หน้า HTML คลาส และทรัพยากรอื่น ๆ ที่ประกอบขึ้นเป็นแอปพลิเคชันสุดท้ายบนเว็บเซิร์ฟเวอร์ ตามบท "
10.6 Web Application Archive File " เว็บแอปพลิเคชันสามารถบรรจุใน Web ARchive (ไฟล์เก็บถาวรที่มีนามสกุล WAR) ตามที่ระบุไว้ในหน้า "
อภิธานศัพท์-219 ":
นั่นคือ WAR ถูกสร้างขึ้นแทน JAR เพื่อแสดงว่านี่คือเว็บแอปพลิเคชัน ข้อเท็จจริงที่สำคัญถัดไป: เราต้องมีโครงสร้างไดเร็กทอรีที่แน่นอนในไฟล์เก็บถาวร WAR ของเรา ในข้อกำหนด Servlet API ในบท "
10.5 Directory Structure " บทนี้บอกว่ามีไดเร็กทอรีพิเศษชื่อ "WEB-INF" ไดเร็กทอรีนี้มีความพิเศษตรงที่ไคลเอ็นต์ไม่สามารถมองเห็นได้ และไม่ได้แสดงโดยตรง แต่โค้ดเซิร์ฟเล็ตสามารถเข้าถึงได้ นอกจากนี้ยังระบุด้วยว่าไดเร็กทอรี WEB-INF สามารถประกอบด้วยอะไร:
จากรายการทั้งหมดนี้ ตอนนี้เราไม่ทราบและไม่เข้าใจรายการเกี่ยวกับ ไฟล์
web.xml บางไฟล์ ที่เรียกว่าDescriptor
การใช้งาน มันคืออะไร? บทที่ "
14. Deployment Descriptor " เน้นไปที่ Descriptor การนำไปใช้งาน กล่าวโดยสรุป
ตัวอธิบายการปรับใช้คือไฟล์ xml ที่อธิบายวิธีการปรับใช้ (นั่นคือ รัน) เว็บแอปพลิเคชันของเราบนเว็บเซิร์ฟเวอร์ ตัวอย่างเช่น ตัวอธิบายการปรับใช้จะระบุว่าควรใช้ URL ใดในการเข้าถึงแอปพลิเคชันของเรา การตั้งค่าความปลอดภัยที่เกี่ยวข้องกับแอปพลิเคชันของเรา ฯลฯ จะถูกระบุ บท "
14.2 กฎสำหรับการประมวลผลการปรับใช้ " บอกว่า web.xml จะได้รับการตรวจสอบความถูกต้องของสคีมาก่อนที่แอปพลิเคชันของเราจะได้รับการกำหนดค่าและเปิดใช้งาน (นั่นคือ จะมีการตรวจสอบว่าเนื้อหาของ web.xml ถูกเขียนอย่างถูกต้องตามสคีมา) . และในบท "
14.3 Deployment Descriptor " ระบุว่ามีไดอะแกรมอยู่ที่นี่
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd
ถ้าเราดูเนื้อหาของไฟล์ เราจะเห็น:
สคีมาใช้สำหรับไฟล์ XML คืออะไร สคีมาระบุวิธีการกรอกเอกสาร XML อย่างถูกต้อง: องค์ประกอบใดที่สามารถใช้ได้, ประเภทข้อมูลใดที่สามารถระบุในองค์ประกอบ, ลำดับที่องค์ประกอบควรจะไป, องค์ประกอบใดที่จำเป็น ฯลฯ คุณสามารถเปรียบเทียบสคีมาของเอกสาร XML กับอินเทอร์เฟซใน Java ได้ เนื่องจากสคีมาใน Java ยังระบุวิธีการเขียนคลาสที่ตรงตามอินเทอร์เฟซที่กำหนด (นั่นคือ การนำอินเทอร์เฟซที่กำหนดไปใช้) ควรเขียนอย่างไร ดังนั้นเราจึงมีความรู้ที่เป็นความลับและพร้อมที่จะสร้างเว็บแอปพลิเคชันแรกของเรา!
การสร้างเว็บแอปพลิเคชัน
เป็นเรื่องยากที่จะจินตนาการถึงการทำงานกับแอปพลิเคชัน Java สมัยใหม่โดยไม่ต้องใช้ระบบการสร้างโปรเจ็กต์อัตโนมัติ ระบบที่ได้รับความนิยมมากที่สุด ได้แก่
Maven และ Gradle เราจะใช้ Gradle สำหรับการตรวจสอบนี้ การติดตั้ง Gradle อธิบายไว้ใน
เว็บไซต์อย่างเป็นทางการ . ในการสร้างแอปพลิเคชันใหม่ เราจำเป็นต้องมีปลั๊กอินที่สร้างไว้ใน Gradle: "
Build Init Plugin " ในการสร้างแอปพลิเคชัน Java คุณต้องรันคำสั่งต่อไปนี้:
gradle init --type java-application
หลังจากสร้างโปรเจ็กต์ แล้วเราจะต้องแก้ไข ไฟล์
build.gradle นี่คือสิ่งที่เรียกว่า Build Script (สำหรับรายละเอียดเพิ่มเติม โปรดดูเอกสารประกอบของ Gradle: "
การเขียนสคริปต์ Build ") ไฟล์นี้อธิบายวิธีการประกอบโปรเจ็กต์และลักษณะอื่นๆ ของการทำงานกับโปรเจ็กต์ Java บล็อกปลั๊กอินอธิบายว่า "
ปลั๊กอิน Gradle " ใดที่ควรใช้สำหรับโครงการ Gradle ปัจจุบัน ปลั๊กอินขยายขีดความสามารถของโครงการของเรา ตัวอย่างเช่น ปลั๊กอินเริ่มต้นคือ "
java " ปลั๊กอินนี้จะใช้เสมอหากเราต้องการการสนับสนุน Java แต่เราไม่ต้องการ ปลั๊กอิน “
application ” เพราะ... คำอธิบายระบุว่าใช้เพื่อสร้าง "แอปพลิเคชัน JVM ที่ปฏิบัติการได้" เช่น ใช้งานแอปพลิเคชัน JVM เราจำเป็นต้องสร้างเว็บแอปพลิเคชันในรูปแบบของไฟล์เก็บถาวร WAR และหากเรามองหาคำว่า WAR ในเอกสารประกอบของ Gradle เราจะพบ “
War Plugin ” ดังนั้นเราจะระบุปลั๊กอินดังต่อไปนี้:
plugins {
id 'java'
id 'war'
}
นอกจากนี้ใน "
War Plugin Default Settings " ว่ากันว่าไดเร็กทอรีที่มีเนื้อหาทั้งหมดของเว็บแอปพลิเคชันควรเป็น "src/main/webapp" ควรมีไดเร็กทอรี WEB-INF เดียวกันกับที่ web.xml ควรเป็น ตั้งอยู่. มาสร้างไฟล์ดังกล่าวกัน เราจะกรอกข้อมูลในภายหลังเล็กน้อยเพราะ... เรายังไม่มีข้อมูลเพียงพอสำหรับเรื่องนี้ ในบล็อก "การขึ้นต่อกัน" เราระบุการขึ้นต่อกันของโปรเจ็กต์ของเรา นั่นคือ ไลบรารี/เฟรมเวิร์กเหล่านั้น หากปราศจากนั้น แอปพลิเคชันของเราจะไม่สามารถทำงานได้ ในกรณีนี้ เรากำลังเขียนเว็บแอปพลิเคชัน ซึ่งหมายความว่าเราจะไม่สามารถทำงานได้หากไม่มี Servlet API:
dependencies {
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
testCompile 'junit:junit:4.12'
}
ProvideCompile หมายความว่าไม่จำเป็นต้องรวมการขึ้นต่อกันในไฟล์เก็บถาวร WAR ของเว็บแอปพลิเคชันของเรา: จำเป็นสำหรับการคอมไพล์เท่านั้น และเมื่อดำเนินการแล้ว บุคคลอื่นจะเป็นผู้จัดหาการพึ่งพานี้ (นั่นคือ เว็บเซิร์ฟเวอร์) เราทิ้งข้อมูลสคริปต์การสร้างเกี่ยวกับที่เก็บการพึ่งพาที่เราต้องการใช้ - การขึ้นต่อกันที่ระบุทั้งหมดจะถูกดาวน์โหลดจากมัน:
repositories {
jcenter()
}
เราลบทุกอย่างออกจากไฟล์สคริปต์บิลด์ ตอนนี้เรามาแก้ไขคลาส src\main\java\App.java กันดีกว่า มาสร้างเซิร์ฟเล็ตกันดีกว่า ข้อกำหนดของ Servlet API ในบท "
บทที่ 2 Servlet Interface " ระบุว่า Servlet Interface มีการใช้งานพื้นฐาน
ของ HttpServletซึ่งควรจะเพียงพอในกรณีส่วนใหญ่ และนักพัฒนาเพียงแค่ต้องสืบทอดจากมัน และในบท "
2.1.1 วิธีการจัดการคำขอเฉพาะ HTTP " วิธีการหลักที่ประมวลผลคำขอขาเข้าจะถูกระบุ ดังนั้น เรามาเขียนคลาส App.java ใหม่กัน:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.IOException;
public class App extends HttpServlet {
public String getGreeting() {
return "Hello world.";
}
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter out = resp.getWriter();
out.println(this.getGreeting());
out.close();
}
}
ดูเหมือนว่าเราจะมีทุกอย่างพร้อมแล้ว สิ่งที่เหลืออยู่คือการเขียนตัวอธิบายการใช้งานอย่างถูกต้อง จากแผนภาพ ให้คัดลอกข้อความต่อไปนี้ลงใน web.xml:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="..."
version="3.1">
...
</web-app>
และเส้นทางไปยังสคีมาที่ระบุไว้ด้วย:
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd
ตอนนี้เรามาดูตัวอย่างว่า web.xml ควรมีลักษณะอย่างไรในข้อกำหนด Servlet API ตัวอย่างนี้มีให้ในบท "
14.5.1 ตัวอย่างพื้นฐาน " ลองรวมสิ่งที่ระบุไว้ในแผนภาพกับตัวอย่างที่ระบุในข้อกำหนด เราได้รับสิ่งต่อไปนี้:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>A Simple Web Application</display-name>
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>App</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app</url-pattern>
</servlet-mapping>
</web-app>
อย่างที่คุณเห็น เราใช้สคีมาและ schemaLocation ที่ระบุไว้ก่อนหน้านี้ และคำอธิบายขององค์ประกอบเองก็นำมาจากตัวอย่างจากบทที่ 14.5.1 หากเราทำทุกอย่างถูกต้อง เราจะรันงาน gradle war โดยไม่มีข้อผิดพลาด:
การเปิดตัวแอปพลิเคชันเว็บ
เว็บแอปพลิเคชั่นเปิดตัวอย่างไร? มาจัดการกับตัวเลือกที่ซับซ้อนกว่านี้ก่อน ก่อนหน้านี้เราบอกว่ามีเว็บเซิร์ฟเวอร์ Apache Tomcat ที่รองรับ Servlet API ซึ่งหมายความว่าเราสามารถปรับใช้คลังข้อมูลสงครามที่รวบรวมไว้ของเราได้ (พวกเขายังพูดว่า "ปรับใช้") บนเซิร์ฟเวอร์นี้ ในหน้า "
ดาวน์โหลด Tomcat " ให้ดาวน์โหลดจากส่วน "Binary Distributions" ประเภทการจัดส่ง "Core" ในรูปแบบ zip และคลายไฟล์ที่ดาวน์โหลดมาลงในไดเร็กทอรีบางตัว เช่น ใน C:\apache-tomcat-9.0.14 ก่อนที่จะเริ่มเซิร์ฟเวอร์ เรามาเปิดไฟล์เพื่อแก้ไข
conf\tomcat-users.xml
และเพิ่มบรรทัดต่อไปนี้:
<user username="tomcat" password="tomcat" roles="tomcat,manager-gui,admin-gui"/>
ตอนนี้บนบรรทัดคำสั่ง ไปที่ไดเร็กทอรี bin และดำเนินการ
catalina.bat start
. ตามค่าเริ่มต้น คอนโซลเซิร์ฟเวอร์จะพร้อมใช้งาน
http://localhost:8080/manager
ที่ ข้อมูลเข้าสู่ระบบและรหัสผ่านเหมือนกันกับที่เราระบุไว้ใน tomcat-users.xml Tomcat มีไดเรกทอรี "webapps" ซึ่งมีเว็บแอปพลิเคชัน หากเราต้องการวางกำลังของเราเอง เราต้องคัดลอกเอกสารสงครามของเราที่นั่น เมื่อก่อนหน้านี้เรารันคำสั่ง gradle war
\build\libs\
ไฟล์เก็บถาวร war จะถูกสร้างขึ้นในไดเร็กทอรี นี่คือสิ่งที่เราต้องคัดลอก หลังจากคัดลอกแล้ว ให้รีเฟรชหน้า
http://localhost:8080/manager
และดู:
เมื่อเสร็จแล้ว
http://localhost:8080/javaweb/app
เราจะหันมาใช้เซิร์ฟเล็ตของเราเพราะ ก่อนหน้านี้เรา "แมป" (นั่นคือ แมป) คำขอ /app ไปยัง App servlet มีวิธีที่เร็วกว่าในการตรวจสอบว่าแอปพลิเคชันทำงานอย่างไร และระบบการประกอบก็ช่วยเราในเรื่องนี้อีกครั้ง ในสคริปต์การสร้างของโปรเจ็กต์ Gradle ของเรา เราสามารถเพิ่มปลั๊กอินใหม่ "
Gretty " ลงในส่วนปลั๊กอินได้
id "org.gretty" version "2.3.1"
และตอนนี้เราสามารถดำเนินการ gradle เพื่อรันแอปพลิเคชันของเราได้:
gradle appRun
ดู "
เพิ่มปลั๊กอิน gretty และเรียกใช้แอป " เพื่อดูรายละเอียด
Spring และ Servlet API
เซิร์ฟเล็ตเป็นพื้นฐานของทุกสิ่ง และแม้แต่ Spring Framework ที่ได้รับความนิยมในขณะนี้ก็ไม่มีอะไรมากไปกว่าส่วนเสริมของ Servlet API เริ่มต้นด้วย
Spring Frameworkเป็นการพึ่งพาใหม่สำหรับโครงการของเรา ดังนั้น มาเพิ่มลงในสคริปต์การสร้างในบล็อกการอ้างอิง:
compile 'org.springframework:spring-webmvc:5.1.3.RELEASE'
ในเอกสาร Spring Framework มีบท "
1.1. DispatcherServlet " มันบอกว่า Spring Framework ถูกสร้างขึ้นบนรูปแบบ "ตัวควบคุมด้านหน้า" - นี่คือเมื่อมีเซิร์ฟเล็ตกลางที่เรียกว่า "
DispatcherServlet " คำขอทั้งหมดมาที่เซิร์ฟเล็ตนี้ และจะมอบหมายการโทรไปยังส่วนประกอบที่จำเป็น คุณเห็นไหมว่าที่นี่ยังมีเซิร์ฟเล็ตอยู่ คุณต้องเพิ่ม Listener ให้กับ Descriptor การนำไปใช้งาน:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
นี่คือ Listener เหตุการณ์บริบทเซิร์ฟเล็ต นั่นคือเมื่อ Servlet Context เริ่มต้น บริบท Spring (WebApplicationContext) ก็เริ่มทำงานเช่นกัน
บริบทของเซิร์ฟเล็ตคืออะไร? มีการอธิบายไว้ในข้อกำหนด Servle API ในบท "
บทที่ 4 บริบทของ Servlet " บริบทเซิร์ฟเล็ตคือ "มุมมอง" ของเซิร์ฟเล็ตของเว็บแอปพลิเคชันที่เซิร์ฟเล็ตกำลังทำงานอยู่ แต่ละเว็บแอปพลิเคชันมีบริบท Servlet ของตัวเอง ถัดไป เพื่อเปิดใช้งาน Spring Framework คุณต้องระบุ context-param - พารามิเตอร์การเริ่มต้นสำหรับบริบทเซิร์ฟเล็ต
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-context.xml</param-value>
</context-param>
และ คำจำกัดความ
DispatcherServlet จะทำให้การกำหนดค่าเสร็จสมบูรณ์ :
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
และตอนนี้เราเพียงแค่ต้องกรอกไฟล์ที่ระบุใน contextConfigLocation วิธีการทำเช่นนี้ได้อธิบายไว้ในเอกสาร Spring Framework ในบท "1.3.1. Declaration":
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="ru.javarush.javaweb"/>
<mvc:annotation-driven/>
</beans>
สิ่งสำคัญที่นี่ไม่เพียงแต่เพื่อระบุว่าแพ็คเกจใดที่จะสแกนเท่านั้น แต่ยังต้องการให้เราต้องการคำอธิบายประกอบด้วย นั่นคือเพื่อควบคุมคำอธิบายประกอบว่า Spring จะทำงานอย่างไร สิ่งที่เหลืออยู่คือการสร้างแพ็คเกจ ru.javarush.javaweb และวางคลาส Spring controller ลงไป:
package ru.javarush.javaweb;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class SpringController {
@GetMapping("/app")
@ResponseBody
public String getGreeting() {
return "Hello world.";
}
}
ตอนนี้รัน gradle appRun และไปที่ที่อยู่
http://127.0.0.1:8080/javaweb/app
เราก็จะได้ Hello World เหมือนเดิม อย่างที่คุณเห็น Spring Framework มีความเชื่อมโยงอย่างใกล้ชิดกับ Servlet API และใช้เพื่อทำงานด้านบน
คำอธิบายประกอบ
ดังที่เราได้เห็นแล้วว่าคำอธิบายประกอบมีความสะดวก และเราไม่ใช่คนเดียวที่คิดเช่นนั้น ดังนั้นในข้อกำหนด Servlet API เริ่มต้นด้วยเวอร์ชัน 3.0 บท “
บทที่ 8 คำอธิบายประกอบและความสามารถในการเสียบปลั๊ก ” จึงปรากฏขึ้น ซึ่งระบุว่าคอนเทนเนอร์เซิร์ฟเล็ตต้องรองรับความสามารถในการระบุสิ่งที่ระบุไว้ก่อนหน้านี้ใน Deployment Descriptor ผ่านคำอธิบายประกอบ ดังนั้น web.xml จึงสามารถลบออกจากโปรเจ็กต์ได้อย่างสมบูรณ์ และเหนือคลาสเซิร์ฟเล็ต คุณสามารถระบุ คำอธิบายประกอบ
@WebServletและระบุพาธที่จะแมปเซิร์ฟเล็ตไป ทุกอย่างดูเหมือนชัดเจนที่นี่ แต่ถ้าเราเชื่อมต่อ Spring เข้ากับโปรเจ็กต์ซึ่งต้องการการตั้งค่าที่ซับซ้อนกว่านี้ล่ะ ที่นี่ทุกอย่างซับซ้อนขึ้นเล็กน้อย อันดับแรก เอกสารประกอบของ Spring บอกว่าในการกำหนดค่า Spring โดยไม่มี web.xml คุณต้องใช้คลาสของคุณเองที่จะใช้ WebApplicationInitializer สำหรับรายละเอียดเพิ่มเติม ดูบท "
1.1. DispatcherServlet " ปรากฎว่านี่คือคลาส Spring Servlet API ใช้ที่นี่อย่างไร ที่จริงแล้ว
ServletContainerInitializer ถูกเพิ่มใน Servlet API 3.0 การใช้กลไกพิเศษใน Java (เรียกว่า
SPI ) Spring จะระบุตัวเริ่มต้นคอนเทนเนอร์เซิร์ฟเล็ตที่เรียก
SpringServletContainerInitializer
ว่า ในทางกลับกัน จะค้นหาการใช้งาน WebApplicationInitializer และเรียกวิธีการที่จำเป็นและดำเนินการตั้งค่าที่จำเป็น ดู "
วิธีที่คอนเทนเนอร์เซิร์ฟเล็ตค้นหาการใช้งาน WebApplicationInitializer " สำหรับรายละเอียดเพิ่มเติม การตั้งค่าข้างต้นสามารถทำได้ดังนี้:
package ru.javarush.javaweb.config;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
public class AppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
servletContext.addListener(new ContextLoaderListener(ctx));
ctx.setServletContext(servletContext);
ServletRegistration.Dynamic servlet =
servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
}
}
ตอนนี้ เมื่อใช้ "
การกำหนดค่าตาม Java " เราจะระบุว่าแพ็คเกจใดที่จะสแกน + เปิดใช้งานคำอธิบายประกอบ:
package ru.javarush.javaweb.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "ru.javarush.javaweb.controllers")
public class AppConfig {
}
และ SpringController เองก็ถูกย้ายไปที่
ru.javarush.javaweb.controllers
ดังนั้นเมื่อทำการสแกน การกำหนดค่าจะไม่พบตัวเอง แต่จะมองหาเฉพาะตัวควบคุมเท่านั้น
สรุป
ฉันหวังว่าภาพรวมนี้จะช่วยให้กระจ่างเกี่ยวกับวิธีการทำงานของเว็บแอปพลิเคชันใน Java นี่เป็นเพียงส่วนเล็กๆ ของภูเขาน้ำแข็ง แต่ถ้าไม่เข้าใจพื้นฐาน ก็เป็นเรื่องยากที่จะเข้าใจว่าเทคโนโลยีที่ใช้รากฐานนี้ทำงานอย่างไร Servlet API เป็นส่วนสำคัญของเว็บแอปพลิเคชัน Java และเราได้ดูว่าเฟรมเวิร์กอื่นๆ เข้ากับมันอย่างไร หากต้องการดำเนินการต่อ คุณสามารถดูเอกสารต่อไปนี้:
#เวียเชสลาฟ
GO TO FULL VERSION