มาแบ่งปันสถาปัตยกรรมแอปพลิเคชันบนเว็บของ Java กันเถอะ!
มีสถาปัตยกรรมที่แตกต่างกันมากมายสำหรับเว็บแอปพลิเคชันซึ่งจะนำไปใช้งานโดยใช้ Java คำตอบสำหรับคำถามนี้อาจทำหน้าที่เป็นห้องสมุดของการออกแบบเว็บแอปพลิเคชันที่หลากหลายด้วยข้อดีข้อเสีย ในขณะที่ฉันรู้ว่าคำตอบจะเป็นอัตนัยลองเป็นเป้าหมายให้มากที่สุดเท่าที่จะทำได้และกระตุ้นให้เกิดข้อดีและข้อเสียที่เรามี
ใช้ระดับรายละเอียดที่คุณต้องการสำหรับอธิบายสถาปัตยกรรมของคุณ เพื่อให้คำตอบของคุณมีค่าอย่างน้อยที่สุดคุณจะต้องอธิบายเทคโนโลยีและแนวคิดหลักที่ใช้ในสถาปัตยกรรมที่คุณอธิบาย และสุดท้าย แต่ไม่น้อยเมื่อเราควรใช้สถาปัตยกรรมของคุณหรือไม่
ฉันจะเริ่ม ...
ภาพรวมของสถาปัตยกรรม
เราใช้สถาปัตยกรรม 3 ชั้นตามมาตรฐานแบบเปิดจาก Sun เช่น Java EE, Java Persistence API, Servlet และ Java Server Pages
- วิริยะ
- ธุรกิจ
- การเสนอ
การสื่อสารที่เป็นไปได้ระหว่างเลเยอร์ถูกแทนด้วย:
Persistence <-> Business <-> Presentation
ตัวอย่างเช่นหมายความว่าเลเยอร์การนำเสนอไม่เคยโทรหรือทำการดำเนินการติดตามันทำผ่านเลเยอร์ธุรกิจเสมอ สถาปัตยกรรมนี้มีขึ้นเพื่อตอบสนองความต้องการของเว็บแอพพลิเคชันที่มีความพร้อมใช้งานสูง
วิริยะ
ดำเนินการสร้างอ่านอ่านอัปเดตและลบ ( CRUD ) ในกรณีที่เรากำลังใช้ ( Java คงทน API ) JPA และเราใช้ในปัจจุบันHibernateเป็นผู้ให้บริการการคงอยู่ของเราและใช้EntityManager ของมัน
ชั้นนี้จะแบ่งออกเป็นหลายชั้นซึ่งแต่ละชั้นเรียนกับข้อเสนอบางประเภทของหน่วยงาน (หน่วยงานที่เกี่ยวข้องกับการเช่นรถเข็นช็อปปิ้งอาจได้รับการจัดการโดยระดับความคงอยู่คนเดียว) และมีการใช้โดยเพียงหนึ่งเดียวและผู้จัดการ
นอกจากนี้ในชั้นนี้ยังเก็บหน่วยงาน JPAซึ่งเป็นสิ่งที่ชอบAccount
, ShoppingCart
ฯลฯ
ธุรกิจ
ตรรกะทั้งหมดที่เชื่อมโยงกับฟังก์ชันการทำงานของเว็บแอปพลิเคชันอยู่ในเลเยอร์นี้ ฟังก์ชั่นนี้สามารถเริ่มต้นการโอนเงินสำหรับลูกค้าที่ต้องการชำระค่าสินค้าออนไลน์โดยใช้บัตรเครดิตของเขา / เธอ มันอาจจะเป็นการสร้างผู้ใช้ใหม่การลบผู้ใช้หรือการคำนวณผลลัพธ์ของการต่อสู้ในเกมบนเว็บ
เลเยอร์นี้แบ่งออกเป็นหลายคลาสและแต่ละคลาสเหล่านี้มีคำอธิบายประกอบด้วย@Stateless
เพื่อเป็นStateless Session Bean (SLSB) แต่ละ SLSB จะเรียกว่าเป็นผู้จัดการAccountManager
และตัวอย่างเช่นผู้จัดการอาจจะเป็นชั้นเรียนข้อเขียนดังที่ได้กล่าวเรียกว่า
เมื่อAccountManager
ต้องการดำเนินการ CRUD จะทำให้การเรียกที่เหมาะสมไปยังอินสแตนซ์ของAccountManagerPersistence
ซึ่งเป็นชั้นในชั้นคงอยู่ ภาพร่างคร่าวๆของสองวิธีAccountManager
สามารถ:
...
public void makeExpiredAccountsInactive() {
AccountManagerPersistence amp = new AccountManagerPersistence(...)
// Calls persistence layer
List<Account> expiredAccounts = amp.getAllExpiredAccounts();
for(Account account : expiredAccounts) {
this.makeAccountInactive(account)
}
}
public void makeAccountInactive(Account account) {
AccountManagerPersistence amp = new AccountManagerPersistence(...)
account.deactivate();
amp.storeUpdatedAccount(account); // Calls persistence layer
}
เราใช้ธุรกรรมตัวจัดการคอนเทนเนอร์ดังนั้นเราไม่จำเป็นต้องทำธุรกรรมแบ่งเขตของตนเอง สิ่งที่เกิดขึ้นภายใต้ประทุนคือเราเริ่มทำธุรกรรมเมื่อเข้าสู่วิธี SLSB และส่งมอบ (หรือย้อนกลับ) ทันทีก่อนออกจากวิธี มันเป็นตัวอย่างของการประชุมเรื่องการตั้งค่า แต่เรายังไม่ต้องการอะไรนอกจากค่าเริ่มต้นที่จำเป็น
นี่คือวิธีการสอน Java EE 5 จาก Sun อธิบายคุณลักษณะธุรกรรมที่จำเป็นสำหรับ Enterprise JavaBeans (ของ EJB):
หากลูกค้ากำลังทำงานอยู่ภายในธุรกรรมและเรียกใช้วิธีการของ enterprise bean วิธีการดำเนินการภายในการทำธุรกรรมของลูกค้า ถ้าไคลเอนต์ไม่เกี่ยวข้องกับธุรกรรมคอนเทนเนอร์เริ่มต้นธุรกรรมใหม่ก่อนที่จะเรียกใช้วิธีการ
แอททริบิวที่จำเป็นคือแอททริบิวต์การทำธุรกรรมโดยนัยสำหรับวิธี bean ขององค์กรทั้งหมดที่รันด้วยการแบ่งส่วนธุรกรรมที่จัดการคอนเทนเนอร์ โดยทั่วไปแล้วคุณไม่ได้ตั้งค่าแอททริบิวที่จำเป็นเว้นแต่ว่าคุณต้องการแทนที่แอททริบิวการทำธุรกรรมอื่น เนื่องจากแอททริบิวธุรกรรมเป็นรายการคุณสามารถเปลี่ยนได้ในภายหลัง
การเสนอ
เลเยอร์การนำเสนอของเรามีหน้าที่รับผิดชอบ ... การนำเสนอ! รับผิดชอบส่วนต่อประสานผู้ใช้และแสดงข้อมูลต่อผู้ใช้โดยการสร้างหน้า HTML และรับข้อมูลผู้ใช้ผ่านคำขอ GET และ POST ขณะนี้เรากำลังใช้การรวมกันของ + Java Server Pages ( JSP ) ของServlet แบบเก่า
เลเยอร์เรียกเมธอดในผู้จัดการของเลเยอร์ธุรกิจเพื่อดำเนินการตามที่ผู้ใช้ร้องขอและเพื่อรับข้อมูลที่จะแสดงในหน้าเว็บ บางครั้งข้อมูลที่ได้รับจากชั้นธุรกิจเป็นชนิดที่มีความซับซ้อนน้อยลงเช่นString
'และint
egers และในเวลาอื่น ๆหน่วยงาน JPA
ข้อดีและข้อเสียกับสถาปัตยกรรม
ข้อดี
- การมีทุกอย่างที่เกี่ยวข้องกับวิธีเฉพาะในการคงอยู่ในเลเยอร์นี้หมายความว่าเราสามารถสลับจากการใช้ JPA เป็นอย่างอื่นโดยไม่ต้องเขียนอะไรใหม่ในชั้นธุรกิจ
- เป็นเรื่องง่ายสำหรับเราที่จะสลับเลเยอร์การนำเสนอของเราเป็นอย่างอื่นและเป็นไปได้ว่าเราจะทำถ้าเราพบสิ่งที่ดีกว่า
- การปล่อยให้คอนเทนเนอร์ EJB จัดการขอบเขตการทำธุรกรรมนั้นดี
- การใช้ + JPA ของ Servlet นั้นง่าย (เริ่มต้นด้วย) และมีการใช้เทคโนโลยีอย่างกว้างขวางและนำไปใช้ในเซิร์ฟเวอร์จำนวนมาก
- โดยใช้ Java EE ควรจะทำให้มันง่ายขึ้นสำหรับเราที่จะสร้างระบบความพร้อมใช้งานสูงที่มีสมดุลภาระและไม่ผ่าน ทั้งที่เรารู้สึกว่าเราต้องมี
จุดด้อย
- การใช้ JPA คุณอาจเก็บแบบสอบถามที่ใช้บ่อยเป็นแบบสอบถามที่มีชื่อโดยใช้
@NamedQuery
คำอธิบายประกอบในคลาสเอนทิตี JPA หากคุณมีความเกี่ยวข้องกับการคงอยู่ในคลาสการคงอยู่มากที่สุดเท่าที่จะเป็นไปได้เช่นเดียวกับในสถาปัตยกรรมของเราสิ่งนี้จะกระจายตำแหน่งที่ตั้งที่คุณอาจพบข้อความค้นหาเพื่อรวมเอนทิตี JPA ด้วย มันจะยากกว่าที่จะเห็นภาพรวมการดำเนินงานคงอยู่และยากที่จะรักษา - เรามีหน่วยงาน JPA เป็นส่วนหนึ่งของชั้นความเพียรของเรา แต่
Account
และShoppingCart
พวกเขาไม่ใช่วัตถุทางธุรกิจจริง ๆ หรือ มันทำแบบนี้เมื่อคุณต้องสัมผัสคลาสเหล่านี้และเปลี่ยนเป็นเอนทิตีที่ JPA รู้วิธีจัดการ - หน่วยงาน JPA ซึ่งเป็นวัตถุทางธุรกิจของเราถูกสร้างขึ้นเช่น Data Transfer Objects ( DTO ) หรือที่เรียกว่า Value Objects (VO's) ซึ่งส่งผลในรูปแบบโดเมน anemicเป็นวัตถุธุรกิจไม่มีตรรกะของตนเองยกเว้นวิธีการเข้าถึง ตรรกะทั้งหมดทำโดยผู้จัดการของเราในชั้นธุรกิจซึ่งส่งผลให้รูปแบบการเขียนโปรแกรมขั้นตอนมากขึ้น มันไม่ใช่การออกแบบเชิงวัตถุที่ดี แต่อาจไม่ใช่ปัญหาใช่ไหม (หลังจากการวางแนววัตถุทั้งหมดไม่ได้เป็นกระบวนทัศน์การเขียนโปรแกรมเพียงอย่างเดียวที่ส่งผลลัพธ์)
- การใช้ EJB และ Java EE จะทำให้เกิดความซับซ้อนเล็กน้อย และเราไม่สามารถใช้ Tomcat ได้อย่างหมดจด (การเพิ่ม EJB micro-container ไม่ใช่Tomcat ล้วนๆ )
- มีปัญหามากมายเกี่ยวกับการใช้ + JPA ของ Servlet ใช้ Google สำหรับข้อมูลเพิ่มเติมเกี่ยวกับปัญหาเหล่านี้
- เนื่องจากธุรกรรมถูกปิดเมื่อออกจากชั้นธุรกิจเราไม่สามารถโหลดข้อมูลใด ๆ จากเอนทิตี JPA ที่กำหนดค่าให้โหลดจากฐานข้อมูลเมื่อจำเป็น (โดยใช้
fetch=FetchType.LAZY
) จากภายในเลเยอร์การนำเสนอ มันจะทำให้เกิดข้อยกเว้น ก่อนที่จะส่งคืนเอนทิตีที่มีฟิลด์ประเภทนี้เราจะต้องแน่ใจว่าได้โทรหาผู้ที่เกี่ยวข้อง อีกตัวเลือกหนึ่งคือการใช้ Java คงทน Query Language ( JPQL )FETCH JOIN
และทำ อย่างไรก็ตามตัวเลือกทั้งสองนี้ค่อนข้างยุ่งยาก