โครงสร้างของ struts2
1. ทำไมต้องใช้เฟรมเวิร์ก?
(1) เฟรมเวิร์กเสร็จสิ้นงานเล็กน้อยโดยอัตโนมัติ
สำหรับ struts2 ช่วยให้เราเสร็จสิ้นการแปลงประเภทข้อมูลการตรวจสอบข้อมูลความเป็นสากล ฯลฯ
งานทั่วไปในการพัฒนาเว็บ นอกจากนี้ยังมีโหมดเทมเพลตที่ใช้กันอย่างแพร่หลายในฤดูใบไม้ผลิซึ่งทำให้กระบวนการพัฒนาของเราเป็นไปโดยอัตโนมัติและอัจฉริยะมากขึ้น การใช้เฟรมเวิร์กคือการหลีกเลี่ยงการสร้างวงล้อใหม่และคัดลอกรหัสเทมเพลตเหล่านี้อีกครั้ง
Framework ช่วยให้เราสามารถมุ่งเน้นไปที่ปัญหาระดับสูงกว่าเวิร์กโฟลว์ทั่วไปและงานพื้นฐาน
(2) การใช้เฟรมเวิร์กหมายถึงการสืบทอดสถาปัตยกรรมที่อยู่เบื้องหลังเฟรมเวิร์กอย่างสง่างาม
สถาปัตยกรรมที่อยู่เบื้องหลังกรอบงานมักจะกำหนดชุดของเวิร์กโฟลว์ สิ่งที่เราต้องทำคือการแนบรหัสของแอปพลิเคชันเฉพาะเข้ากับกระบวนการนี้เพื่อให้เราสามารถเพลิดเพลินไปกับผลประโยชน์ต่าง ๆ ที่นำโดยกรอบ บางครั้งเรายังสามารถต้านทานกฎสถาปัตยกรรมของกรอบงานได้ แต่กรอบการทำงานมักจะให้สถาปัตยกรรมในแบบที่ยากที่จะปฏิเสธ มันง่ายมากที่คุณสามารถสืบทอดสถาปัตยกรรมที่ยอดเยี่ยมได้อย่างสง่างามและฟรีดังนั้นทำไมไม่ทำ
(3) มันง่ายกว่าที่จะหาคนที่ได้รับการฝึกฝนมาเป็นอย่างดีโดยใช้เฟรมเวิร์ก
ฉันแทบไม่เคยใช้เฟรมเวิร์กใด ๆ ในโครงการทั้งหมดของ บริษัท ของฉันมาก่อนและค้นหาบริการบริการ (คล้ายกับ JNDI)
ในการบันทึกการพิมพ์ (คล้ายกับ log4j) จากนั้นไปยังพูลการเชื่อมต่อฐานข้อมูล (คล้ายกับ DBCP) พวกเขาทั้งหมดจะถูกนำไปใช้โดยบุคลากรภายในเอง ประการแรกเป็นเพราะโครงการค่อนข้างเก่าและอาจไม่มีเฟรมเวิร์กโอเพ่นซอร์สใด ๆ สำหรับใช้ในเวลานั้น ประการที่สองเป็นเพราะกลยุทธ์อนุรักษ์นิยมของ บริษัท และเป็นกังวลว่าการใช้กรอบโอเพนซอร์สที่ไม่แน่นอนอาจนำความเสี่ยงมาสู่โครงการ สิ่งนี้อาจเป็นจริงในสภาพแวดล้อมในเวลานั้นและผู้บริหารระดับสูงของ บริษัท จะพิจารณาโครงการทั้งหมดจากมุมมองที่ใหญ่กว่า
อย่างไรก็ตามเมื่อโครงการค่อยๆมีขนาดใหญ่ขึ้นและมีกรอบโอเพนซอร์สที่ยอดเยี่ยมมากขึ้นเรื่อย ๆ ในโลกหากเฟรมเวิร์กโอเพ่นซอร์สที่ครบกำหนดไม่สามารถ refactored ในเวลาและแนะนำผลลัพธ์สุดท้ายอาจเป็นไปได้ว่านักพัฒนาที่ได้รับคัดเลือกใหม่จะต้องเรียนรู้ระบบที่ซับซ้อนนี้
ค่าใช้จ่ายสูงเกินไปจริงๆ
(4) กรอบภายในไม่สามารถติดตามการพัฒนาของอุตสาหกรรมได้
ข้อผิดพลาดในกรอบภายในที่กล่าวถึงก่อนหน้านี้ สำหรับเฟรมเวิร์กโอเพ่นซอร์สอาจมีทีมงานผู้ก่อตั้ง Framework ผู้ที่ชื่นชอบโอเพนซอร์สจำนวนมาก
ชุมชนโอเพ่นซอร์สเพื่อสนับสนุน พลังของผู้คนนั้นไม่มีที่สิ้นสุดและความเร็วในการซ่อมแซมข้อผิดพลาดสามารถจินตนาการได้ นี่คือจากโอเพ่นซอร์สล่าสุด
สามารถมองเห็นกระบวนการแก้ไขข้อผิดพลาดของ TextMate ได้ แมลงจำนวนมากที่ได้รับการเก็บรักษามาเป็นเวลานานได้รับการแก้ไขอย่างรวดเร็วโดยผู้ที่ชื่นชอบหลังจากที่พวกเขาเป็นโอเพนซอร์ส แต่แล้วกรอบภายในล่ะ? หลังจากคนที่พัฒนาเขาออกจาก บริษัท ไม่มีใครจะอ่านซอร์สโค้ดของเขาโดยไม่มีข้อบกพร่องที่สำคัญ ช่องว่างเห็นได้ชัด!
(5) แน่นอนว่าการใช้เฟรมเวิร์กไม่ใช่ผลกำไรมหาศาล
ดังที่ได้กล่าวไว้ก่อนหน้านี้การใช้กรอบการทำงานที่ยังไม่บรรลุนิติภาวะมีความเสี่ยงและเป็นการดีกว่าที่จะอนุรักษ์สำหรับโครงการที่ไม่รุนแรง
(เว้นแต่ว่านี่เป็นกลุ่มของผู้คลั่งไคล้เทคโนโลยีฟรีและไม่ถูก จำกัด ซึ่งสามารถตัดสินใจได้ว่ากรอบการใช้งานใดที่ใช้ตามดุลยพินิจของตนเอง
เช่นเดียวกับ Sequioa บริการความพร้อมใช้งาน Java HA สูงที่ฉันเคยใช้มาก่อนกรอบนี้ไม่ได้รับการสนับสนุนจาก บริษัท พัฒนาอีกต่อไปและความเสี่ยงนั้นยิ่งใหญ่กว่า
นอกจากนี้เมื่อใช้เฟรมเวิร์กที่ผิดปกติคุณควรให้ความสนใจกับโปรโตคอลการใช้รหัสซอร์สโค้ด Framework และไม่อ้างอิงตามที่ต้องการในโครงการ
ปรับเปลี่ยนซอร์สโค้ดของเฟรมเวิร์กเพื่อหลีกเลี่ยงข้อพิพาททางกฎหมายที่ไม่จำเป็น
2. สถาปัตยกรรมที่อยู่เบื้องหลัง struts2
เนื่องจากเราได้วิเคราะห์ประโยชน์มากมายของกรอบก่อนหน้านี้เราจะเริ่มเรียนรู้ที่จะใช้ struts2 แต่ใช้ struts2
สถาปัตยกรรมที่สง่างามแบบไหนจะได้รับมรดก? ในความเป็นจริงจากระดับที่สูงขึ้นของสิ่งที่เป็นนามธรรมมันยังคงเป็นรุ่น MVC ที่เราคุ้นเคย
ตามตัวอย่าง HelloWorld ก่อนหน้านี้คอนโทรลเลอร์ C (FilterDispatcher) คือสิ่งที่เราประกาศใน web.xml
Struts2 core class และ Model M เป็นคลาสแอ็คชั่นข่าวของเรา และ View V เป็นข่าวตามธรรมชาติ jsp แนวคิดของโมเดลดูเหมือนจะคลุมเครือเล็กน้อย โมเดลคืออะไร? ในความเป็นจริงแนวคิดนี้ที่ฟังดูมีคำนามมากมีข้อมูลทางธุรกิจทั้งที่ถ่ายทอดจากเว็บ front-end และการใช้ตรรกะทางธุรกิจ
บางคนอาจบอกว่าสถาปัตยกรรมนี้ไม่ใช่เรื่องใหม่มีกรอบ MVC มากมายความแตกต่างระหว่างสิ่งนี้กับเฟรมเวิร์กอื่น ๆ คืออะไร? ลองแยก struts2 ในระดับที่ต่ำกว่าของสิ่งที่เป็นนามธรรมและดูว่าอะไรทำให้มันไม่เหมือนใคร
เมื่อมองแวบแรกมันดูซับซ้อนมาก หากเราดูจากมุมมองของผู้ใช้เท่านั้นเราจะต้องใช้ส่วนสีเหลืองในระหว่างการพัฒนานั่นคือเรา
struts.xml, newsaction และ news.jsp ในอินสแตนซ์ HelloWorld นี่คือทั้งหมดที่เราต้องทำตามที่กล่าวไว้ก่อนหน้านี้เราเพียงแค่ต้องทำสิ่งเล็ก ๆ น้อย ๆ และเรากลายเป็นส่วนหนึ่งของสถาปัตยกรรมที่ยอดเยี่ยมนี้
ตอนนี้ดูส่วนอื่น ๆ FilterDispatcher เป็นตัวกรอง servlet ที่เรากำหนดค่าใน web.xml ซึ่งเป็น struts2
แอปพลิเคชันเว็บ Struts2 ทั้งหมดจะต้องกำหนดค่าด้วยวิธีนี้ ถัดไปชิ้นส่วนสีน้ำเงินและสีเขียวเป็นแกนกลางของ struts2 อาจกล่าวได้ว่าชั้นเรียนเหล่านี้ได้รับการออกแบบอย่างระมัดระวังโดยนักพัฒนาของ Struts2
(1) ไคลเอนต์ส่งคำขอและ J2EE คอนเทนเนอร์จะวิเคราะห์แพ็คเก็ต HTTP และห่อหุ้มไว้ใน HTTPSERVLETREQUEST
(2) FilterDispatcher สกัดกั้นคำขอนี้และค้นหา ActionMapper ตามเส้นทางคำขอเพื่อพิจารณาว่าการเรียกใช้การโทรใด
(3) ตามผลการส่งคืนของ ActionMapper FilterDispatcher มอบหมาย ActionProxy เพื่อค้นหาการกระทำนี้ใน struts.xml
(4) ActionProxy สร้าง ActionInvocation และเริ่มเรียกใช้การเรียกซ้ำไปยัง interceptor และการกระทำ
(5) แต่ละ interceptor เสร็จงานของตัวเอง
(6) การเรียกร้องให้ดำเนินการจริงส่งคืนเส้นทางผลลัพธ์
(7) วัตถุผลลัพธ์จะส่งออกข้อมูลการส่งคืนไปยังสตรีม
(8) ส่งคืน httpservletResponse ไปยังคอนเทนเนอร์ J2EE และคอนเทนเนอร์ส่งแพ็กเก็ต HTTP ไปยังไคลเอนต์
นี่คือกระบวนการดำเนินการของ struts2 วัตถุหลักคือ ActionInvocation และ Interceptor รวมถึง ActionContext ที่ยังไม่ได้รับการแนะนำ
ActionInvocation คือการกำหนดเวลาทั้งหมดของกระบวนการทั้งหมดซึ่งคล้ายกับวัตถุการเรียกร้องในฤดูใบไม้ผลิ AOP Interceptors จำนวนมากถูกสร้างขึ้นใน struts2 สิ่งที่สำคัญที่สุดคือการบันทึกพารามิเตอร์การร้องขอและส่งผ่านข้อมูลเบื้องหน้าไปยังตัวแปรสมาชิกแอ็คชั่น
ActionContext เป็นวัตถุบริบททั่วโลกที่บันทึกข้อมูลเหล่านี้และสิ่งที่สำคัญที่สุดคือการประเมินค่าที่ใช้ในการบันทึกอินสแตนซ์การกระทำ
สิ่งที่เรียกว่า Global หมายความว่า ActionContext สามารถเข้าถึงได้ทั้งในการดำเนินการและผลลัพธ์ แต่เป็นประเภท ThreadLocal แต่ละเธรดคำขอจะมีอินสแตนซ์ของการกระทำและ ActionContext
อาจกล่าวได้ว่าการเรียนรู้ struts2 ส่วนใหญ่เกี่ยวกับการเรียนรู้:
(1) ให้ Interceptor และ Action ร่วมมือกันทำงานให้เสร็จสมบูรณ์
(2) บันทึกข้อมูลเบื้องหน้าลงในการกระทำ
(3) ผลลัพธ์ได้รับข้อมูลการส่งคืนจากการกระทำผ่าน Valuestack
3. ความแตกต่างระหว่าง struts2 และ struts1
จากกระบวนการดำเนินการข้างต้นเราสามารถเห็นความแตกต่างอย่างมากระหว่าง struts1 และ 2
(1) ActionForm ไปไหน? การกระทำยังคงเป็นการกระทำเดียวกันหรือไม่?
สิ่งที่ชัดเจนที่สุดคือเราไม่สามารถเห็นวัตถุ ActionForm ในกระบวนการทั้งหมดและแม้ว่าการกระทำจะยังคงเรียกว่าชื่อนี้ดูเหมือนว่าจะแตกต่างอย่างสิ้นเชิงจากการกระทำใน struts1
ก่อนอื่น Actionform ถูกทอดทิ้งและข้อมูลที่ส่งจากแผนกต้อนรับสามารถบันทึกไปยัง Pojo ใด ๆ วันแห่งการออมใน ActionForm ก่อนจากนั้นคัดลอกไปยังวัตถุ DTO สิ้นสุดลง ประการที่สอง Pojo นี้เป็นตัวแปรสมาชิกในวัตถุแอ็คชั่น นี่คือ struts1
เป็นไปไม่ได้ที่จะแบ่งปันอินสแตนซ์การดำเนินการสำหรับคำขอทั้งหมดในกรณีนี้ ตอนนี้ struts2 จะสร้างอินสแตนซ์การดำเนินการสำหรับแต่ละคำขอดังนั้นสิ่งนี้ใช้งานได้ ประการที่สามถึงแม้ว่าสิ่งนี้จะเป็นไปได้ แต่ดูเหมือนว่าการกระทำในฐานะโมเดล M ใน MVC จะบันทึกข้อมูลและมีตรรกะทางธุรกิจ นี่เป็นการออกแบบที่ไม่ดีหรือไม่? ที่จริงแล้วถ้าคุณคิดอย่างรอบคอบการออกแบบนี้สะดวกมากเราได้รับข้อมูลแล้ว
คุณสามารถใช้งานเลเยอร์บริการโดยตรง การกระทำดูเหมือนจะมีความรับผิดชอบมากเกินไป แต่ไม่มากนัก
(2) servlet ส่วนหน้ากลายเป็นตัวกรองได้อย่างไร?
เรารู้ว่า struts1 และสปริง MVC ใช้เป็นทางเข้าผ่าน servlets ส่วนหน้า ทำไม struts2 ใช้ตัวกรอง servlet?
เนื่องจาก struts2 ขึ้นอยู่กับแกนเว็บหลักจึงแตกต่างอย่างสิ้นเชิงจาก struts1 การทำงานเว็บสามารถกล่าวได้ว่าจะลดแอปพลิเคชันและ J2EE
การมีเพศสัมพันธ์ API เช่นการเปลี่ยน ActionServlet เป็นตัวกรองของ Servlet และการเข้าถึงโดยตรงไปยัง HttpservletRequest/การตอบสนอง
ตัวอย่างเช่น pojo ใด ๆ สามารถทำหน้าที่เป็น actionform คลาสใดก็ได้สามารถใช้เป็นการกระทำโดยไม่ต้องใช้อินเทอร์เฟซการกระทำ ฯลฯ
ดังนั้น Struts2 จึงสืบทอดการออกแบบที่ไม่รุกรานที่ยอดเยี่ยมนี้
นี่ค่อนข้างคล้ายกับแนวคิดการออกแบบของฤดูใบไม้ผลิ ตัวอย่างเช่นอินเทอร์เฟซเครื่องเหล่านั้นไม่จำเป็นต้องใช้งานเลยเพื่อลดการมีเพศสัมพันธ์ระหว่างรหัสแอปพลิเคชันและเฟรมเวิร์ก การรุกรานเป็นปัจจัยสำคัญที่ต้องพิจารณาเมื่อออกแบบกรอบ
(3) OGNL ระหว่างตัวกรองการกระทำและผลลัพธ์
รูปต่อไปนี้สามารถแสดงให้เห็นอย่างชัดเจนว่า OGNL ถูกรวมเข้ากับเฟรมเวิร์ก Struts2 ได้อย่างไร
มันสะดวกในการเข้าถึงข้อมูลที่ใช้งานโดยใช้แท็ก struts2 ในหน้าอินพุต inputform.html และกลับไปที่หน้าผลลัพธ์หน้า
OGNL สามารถเข้าถึงคุณสมบัติของการกระทำที่บันทึกไว้ใน Valuestack ได้อย่างสะดวกสบายในการเข้าถึงคุณสมบัติของ Valuestack
การใช้ OGNL อย่างกว้างขวางเป็นคุณสมบัติสำคัญของ struts2 รวมถึงค่าแท็กเบื้องหน้าที่ส่งผ่านค่าการดำเนินการผลลัพธ์ที่ได้ผลลัพธ์จากการกระทำ ฯลฯ จะใช้ OGNL ในปริมาณมาก อย่างไรก็ตามการสะท้อนถูกใช้มากใน OGNL ฉันคิดว่านี่เป็นหนึ่งในเหตุผลที่ Struts2 ไม่ดีเท่า struts1 ท้ายที่สุดมันต้องใช้ราคาที่แน่นอนเพื่อให้ได้สถาปัตยกรรมที่ยืดหยุ่นและมีคู่ต่ำ
(4) ความแข็งแกร่งของ interceptor นั้นอยู่ยงคงกระพัน
คุณสมบัติที่ทรงพลังอีกอย่างหนึ่งใน struts2 คือตัวดักจับ Struts2 มีตัวดักจับจำนวนมากในตัวซึ่งช่วยให้รหัสจำนวนมากถูกนำกลับมาใช้ใหม่โดยอัตโนมัติสิ่งที่เราเรียกว่างานเล็ก ๆ น้อย ๆ ก่อนหน้านี้จึงทำให้ Struts2 สามารถแยกความสนใจในระดับสูงได้ นี่เป็นแบบจำลองสำหรับการประยุกต์ใช้ไอเดีย AOP ในกรอบ!
struts2 วิธีการถ่ายโอนข้อมูลสามวิธี
Struts2 ให้สามวิธีในการบันทึกพารามิเตอร์ในคำขอ HTTP: แอตทริบิวต์ Javabean, วัตถุ Javabean และวัตถุที่ได้รับการปรับปรุง ลองมาดูวิธีการถ่ายโอนข้อมูลทั้งสามนี้ผ่านตัวอย่างการเข้าสู่ระบบที่พบบ่อยที่สุด รหัสหน้านั้นง่ายมาก แบบฟอร์มการส่งมีชื่อผู้ใช้และรหัสผ่าน คุณสามารถรับพารามิเตอร์ทั้งสองนี้ในการดำเนินการเพื่อตรวจสอบว่าผู้ใช้เข้าสู่ระบบได้สำเร็จหรือไม่
1. คุณสมบัติ Javabean
< %@ page contentType = "text/html; charset = utf-8" %> <html> <head> </head> <body> <h1> หน้าเข้าสู่ระบบ </h1> <form action = "/cdai/login" method = "post"> <div> <label for = "username" </div> <div> <label for = "password"> รหัสผ่าน: </label> <อินพุต id = "รหัสผ่าน" ชื่อ = "รหัสผ่าน" type = "รหัสผ่าน"/> </div> <div> <label for = "remageme"> <อินพุต id = "memageme" name = "memageme" </html>
แพ็คเกจ com.cdai.web.ssh.action; นำเข้า com.cdai.web.ssh.request.loginrequest; นำเข้า com.cdai.web.ssh.service.userservice; นำเข้า com.opensymphony.xwork2.action; นำเข้า com.opensymphony.xwork2.modeldriven; การเข้าสู่ระบบคลาสสาธารณะใช้การกระทำ {ชื่อผู้ใช้สตริงส่วนตัว; รหัสผ่านสตริงส่วนตัว ผู้ใช้ส่วนตัวผู้ใช้บริการ; @Override Public String execute () {system.out.println ("การดำเนินการเข้าสู่ระบบ -" + คำขอ); กลับมาประสบความสำเร็จ } สตริงสาธารณะ getUserName () {คำขอส่งคืน; } โมฆะสาธารณะ setUserName (ชื่อผู้ใช้สตริง) {this.userName = ชื่อผู้ใช้; } สตริงสาธารณะ getPassword () {คำขอส่งคืน; } โมฆะสาธารณะ setPassword (รหัสผ่านสตริง) {this.password = รหัสผ่าน; -วิธีนี้ค่อนข้างง่ายบันทึกพารามิเตอร์โดยตรงในรูปแบบไปยังคุณสมบัติในการดำเนินการ เมื่อตรวจสอบการกระทำอาจต้องห่อหุ้มชื่อผู้ใช้และรหัสผ่านลงใน DTO เพื่อส่งผ่านไปยังเลเยอร์บริการเพื่อตรวจสอบ ดังนั้นทำไมไม่ก้าวไปอีกขั้นหนึ่งและบันทึกชื่อผู้ใช้และรหัสผ่านลงใน DTO โดยตรง
2. วัตถุ Javabean
< %@ page contentType = "text/html; charset = utf-8" %> <html> <head> </head> <body> <h1> หน้าเข้าสู่ระบบ </h1> <form action = "/cdai/login" method "post"> <div> <label for = "username"> </div> <div> <label for = "password"> รหัสผ่าน: </label> <อินพุต id = "รหัสผ่าน" name = "request.password" type = "รหัสผ่าน"/> </div> <div> <label for = "RememberMe"> <อินพุต id = "memageme" name = "memageme </body> </html>
แพ็คเกจ com.cdai.web.ssh.action; นำเข้า com.cdai.web.ssh.request.loginrequest; นำเข้า com.cdai.web.ssh.service.userservice; นำเข้า com.opensymphony.xwork2.action; นำเข้า com.opensymphony.xwork2.modeldriven; การเข้าสู่ระบบระดับสาธารณะใช้การดำเนินการ {คำขอล็อกอินส่วนตัว ผู้ใช้ส่วนตัวผู้ใช้บริการ; @Override Public String execute () {system.out.println ("การดำเนินการเข้าสู่ระบบ -" + คำขอ); กลับมาประสบความสำเร็จ } Public LoginRequest GetRequest () {คำขอส่งคืน; } โมฆะสาธารณะ setRequest (คำขอเข้าสู่ระบบ) {this.request = คำขอ; - ทำให้ง่ายต่อการโทรหาเลเยอร์บริการโดยตรง แต่มีข้อเสียเล็กน้อยว่าสิ่งนี้จะทำให้ความลึกของชื่อพารามิเตอร์หน้าลึกขึ้นเพียงเพิ่มคำขอลงในชื่อพารามิเตอร์
คำนำหน้า (ชื่อแอตทริบิวต์ในการดำเนินการ) ช่วยให้ struts2 สามารถบันทึกพารามิเตอร์ได้อย่างถูกต้องในแบบฟอร์มไปยังวัตถุคำขอผ่าน OGNL
3. วัตถุ Modeldriven
< %@ page contentType = "text/html; charset = utf-8" %> <html> <head> </head> <body> <h1> หน้าเข้าสู่ระบบ </h1> <form action = "/cdai/login" method = "post"> <div> <label for = "username" </div> <div> <label for = "password"> รหัสผ่าน: </label> <อินพุต id = "รหัสผ่าน" ชื่อ = "รหัสผ่าน" type = "รหัสผ่าน"/> </div> <div> <label for = "remageme"> <อินพุต id = "memageme" name = "memageme" </html>
แพ็คเกจ com.cdai.web.ssh.action; นำเข้า com.cdai.web.ssh.request.loginrequest; นำเข้า com.cdai.web.ssh.service.userservice; นำเข้า com.opensymphony.xwork2.action; นำเข้า com.opensymphony.xwork2.modeldriven; การเข้าสู่ระบบคลาสสาธารณะใช้การดำเนินการ, ModelDriven <loginRequest> {คำขอล็อกอินส่วนตัว = ใหม่ LoginRequest (); ผู้ใช้ส่วนตัวผู้ใช้บริการ; @Override Public String execute () {system.out.println ("การดำเนินการเข้าสู่ระบบ -" + คำขอ); กลับมาประสบความสำเร็จ } @Override Public LoginRequest GetModel () {คำขอส่งคืน; - ด้วยวิธีนี้จำเป็นต้องใช้อินเทอร์เฟซ ModelDriven อีกหนึ่งรายการและวัตถุที่จัดทำโดย ModelDriven จะถูกบันทึกไว้ใน Valuestack เพื่อให้สามารถส่งผ่านหน้าเบื้องหน้าโดยตรงได้โดยตรง
ชื่อแอตทริบิวต์ชื่อผู้ใช้และรหัสผ่านกำหนดชื่อพารามิเตอร์ของแบบฟอร์ม
ไม่ควรใช้วิธีใดในสามวิธี ขึ้นอยู่กับความต้องการเฉพาะของโครงการแล้วตัดสินใจด้วยตัวเอง!