ขอให้เป็นวันที่ดีผู้อ่านที่รัก! และยินดีที่ได้พบคุณแม้ว่าชื่อที่โอ่อ่าจะเป็นเหตุผลหลักในการดูหัวข้อที่เรียบง่ายเกี่ยวกับความใกล้ชิดครั้งแรกกับการพัฒนา Spring Boot ฉันต้องการแบ่งปันประสบการณ์ของฉันในการทำภารกิจเบื้องต้นสำหรับการฝึกงานในพอร์ทัล JavaRush โดยนำเสนอภาพรวมจากด้านข้างของนักศึกษามหาวิทยาลัยด้านเทคนิคธรรมดา ๆ ที่ต้องการทดสอบความแข็งแกร่งของความรู้ที่สั่งสมมา
ฉันจะไม่ปฏิเสธความหยาบคายที่เป็นไปได้ในโค้ดหรือวิธีการคิดที่แนบมา และฉันยินดีรับคำวิจารณ์ที่สร้างสรรค์ เพราะต้องขอบคุณ "การกระแทกและรอยฟกช้ำ" ที่ทำให้สามารถพัฒนาไปในทิศทางที่เป็นมืออาชีพได้ ยิ่งไปกว่านั้น ฉันไม่ได้แสร้งทำเป็น "ยาครอบจักรวาล" เลยในการแก้ไขเงื่อนไขที่กำหนดและจงใจละเว้นส่วนย่อยของโปรแกรมโดยทิ้งความสำคัญที่สำคัญของการเข้าสู่หัวข้อที่ค่อนข้างซับซ้อนโดยไม่มีผลกระทบต่อระบบประสาทแม้แต่น้อย เป็นความจริง มันไม่ประมาทที่จะปฏิเสธสิ่งที่ชัดเจน: มันยากสำหรับฉันและไม่มีอะไรชัดเจนเลยจนกระทั่งถึงช่วงเวลาหนึ่ง และหากคุณมีความรู้สึกคล้าย ๆ กันตั้งแต่ครั้งแรกที่พบกับงานนี้ ก็ให้ “ยินดีต้อนรับ!” มาเขียนเว็บแอปพลิเคชันใน Spring Boot โดยใช้การเปรียบเทียบแบบง่ายของการทดสอบเข้าฝึกงานโดยใช้เครื่องมือเทมเพลต
ตามข้อกำหนดทางเทคนิคที่นำเสนอ เราจะใช้ชุดสุภาพบุรุษ ซึ่งเป็นมาตรฐานสำหรับการสร้างเว็บแอปพลิเคชันอย่างง่ายโดยใช้ ฐานข้อมูล MySQL :
ต่อไป ทำตามคำแนะนำของสภาพแวดล้อมหลังจากคลิกที่ไอคอนเซิร์ฟเวอร์ท้องถิ่นปัจจุบันในหน้าต่างหลัก เราจะสร้างไดอะแกรมตารางตามฟิลด์ของเอนทิตีของเรา (หมายเหตุ) และกรอกข้อมูลด้วยข้อมูลที่เหมาะสม มีความจำเป็นต้องชี้แจงรายละเอียดปลีกย่อยของภาษา MySQL แยกต่างหากซึ่งต้องการความสนใจอย่างเร่งด่วนเพื่อให้บรรลุผลตามที่ต้องการ:
หลังจากเสร็จสิ้นขั้นตอนการเตรียมการขั้นสุดท้าย เราจะระบุ "MySQL Workbench" เพื่อส่งข้อมูลไปยังเซิร์ฟเวอร์ภายในเครื่องโดยคลิกที่ไอคอน "Lightning" บนแถบเครื่องมือ ตอนนี้ หากการเพิ่มข้อมูลเสร็จสมบูรณ์อย่างถูกต้อง เราก็สามารถกลับไปยัง IDE ดั้งเดิมของเราได้อย่างมั่นใจเพื่อดำเนินการพัฒนาต่อไปโดยการเพิ่มการกำหนดค่าฐานข้อมูลปัจจุบันให้กับ application.properties (โดยปกติจะอยู่ในไดเร็กทอรี “ทรัพยากร”):
และแน่นอน พัฒนาวิธีการเพื่อตอบสนองความต้องการทางธุรกิจอื่นๆ ศักยภาพของแอปพลิเคชันถูกจำกัดด้วยความพยายาม ความรอบรู้ และจินตนาการของนักพัฒนา
ด้วยความตรงไปตรงมาและใส่ใจกับเส้นทางที่เดินทาง ฉันมั่นใจครั้งแล้วครั้งเล่าถึงความถูกต้องของทิศทางที่เลือก และตระหนักถึงประโยชน์ของการศึกษาบนพอร์ทัลการศึกษา JavaRush ด้วยงานภาคปฏิบัติที่หลากหลาย จึงเป็นไปได้ที่จะคืนความสนใจอันน่าดึงดูดใจในการเรียนรู้การเขียนโปรแกรม ซึ่งถูกระงับโดยสิ้นเชิงในโปรแกรมที่ล้าสมัยและน่าเบื่ออย่างน่าประหลาดใจของสถาบันการศึกษาระดับสูงในทิศทางเดียวกัน สี่เดือนของการศึกษาเนื้อหาในกลุ่มเทคโนโลยีแบ็คเอนด์อย่างกระตือรือร้นได้ลงทุนความรู้มากขึ้นมากเมื่อเทียบกับการเข้าร่วมการบรรยายและชั้นเรียนในห้องปฏิบัติการตลอดทั้งปี เชื่อหรือไม่. ฉันหวังว่าคุณจะไม่ยอมแพ้ต่อความยากลำบากในการเข้าสู่เนื้อหาที่ซับซ้อน เพราะว่าการเอาชนะอุปสรรคทำให้เราดีขึ้นและพัฒนาทั้งในด้านอาชีพและส่วนตัว ฉันหวังว่าเรื่องราวเล็กๆ นี้จะช่วยให้ฉันค้นพบไอเดียใหม่ๆ ในการใช้เครื่องมือที่น่าทึ่งที่เรียกว่า SpringBoot ป.ล. Github _
Thymeleaf
และquery
สืบค้นไปยังเซิร์ฟเวอร์ MySQL ในเครื่องเพื่อกรองอาร์เรย์ข้อมูลที่เข้ามา มาเริ่มกันเลย!
รองเท้าบูทสปริง มันเป็นสัตว์ชนิดใดและทำอย่างไร?
กล่าวโดยสรุปและกระชับ มันเป็นเครื่องมือที่ยอดเยี่ยมจากPivotelสำหรับการประหยัดเวลาอันมีค่าในกระบวนการสร้างแอปพลิเคชัน โดยไม่จำเป็นต้องเชื่อมต่อไลบรารีของบุคคลที่สามโดยตรง เขียนผืนผ้าใบการทำแผนที่และเซิร์ฟเล็ตที่น่าประทับใจ ก็เพียงพอแล้วที่จะใช้ Spring Initializr builder ซึ่งรวมเข้ากับIntelliJ IDEA Ultimate Edition (ไฟล์ - ใหม่ - โครงการ... - Spring Initializr) หรือตั้งอยู่บน บริการเว็บstart.spring.ioโดยระบุแพ็คเกจที่จะรวมจากหลากหลาย ข้อเสนอ
- WEBเป็นองค์ประกอบหลักสำหรับการพัฒนาเว็บแอปพลิเคชัน รวมถึงเซิร์ฟเวอร์ Apache Tomcat ในเครื่องที่ที่อยู่มาตรฐาน localhost:8080 และเฟรม เวิร์ก Spring MVC สากล
- DevTools - ใช้เพื่อรีสตาร์ทแอปพลิเคชันอย่างรวดเร็วใน JVM ที่ร้อนแรงเมื่อตรวจพบการเปลี่ยนแปลงในโค้ดหรือเทมเพลตที่คอมไพล์แล้ว ยิ่งไปกว่านั้น ยังช่วยให้ Thymeleaf ว่างจากการล้างแคชหากเอ็นจิ้นที่เลือกรวมอยู่ในโปรเจ็กต์
- JPAเป็นเทคโนโลยีที่จำเป็นสำหรับการทำงานกับฐานข้อมูล และจัดให้มีการแมปเชิงวัตถุเชิงสัมพันธ์ของวัตถุ Java มี API ( ไฮเบอร์เนตในกรณีของเรา) สำหรับการจัดการ บันทึก และเรียกค้นเอนทิตี
- Thymeleaf (Mustache, AngularJS, Vaadin และอื่นๆ) - เอ็นจิ้นเทมเพลตสำหรับการแสดงภาพแอปพลิเคชัน ด้วยความคุ้นเคยกับหลักการของ html ฉันจึงเลือก Thymeleaf ซึ่งผลักดันภาษาให้เป็นรากฐานที่สำคัญของโลก
- MySQL - เชื่อมต่อไดรเวอร์การเชื่อมต่อฐานข้อมูล Java เพื่อดำเนินการสืบค้น SQL กับฐานข้อมูล
<dependencies></dependencies>
ตามวิธีการที่คล้ายกัน

ก้าวแรกสู่อนาคตอันยิ่งใหญ่
ต่อไปมีคำถามที่ค่อนข้างน่าสนใจและสมเหตุสมผลเกิดขึ้น:“ จะทำอย่างไรตอนนี้? วิธีนี้จะทำงานอย่างไร? โปรแกรมนี้สร้างขึ้นบนหลักการของ Model-View-Controller: มันจัดระเบียบการอ่านเอนทิตีจากฐานข้อมูลที่เชื่อมต่อ (Model) และแสดงในส่วนต่อประสานผู้ใช้พร้อมการควบคุม (ดู) การสื่อสารระหว่างส่วนประกอบและการดำเนินการตามคำขอที่ส่งนั้นดำเนินการโดยผู้ควบคุม เป็นการสร้างองค์ประกอบสำคัญที่ทำหน้าที่เป็นจุดอ้างอิงในการพัฒนาอย่างต่อเนื่อง เพื่อหลีกเลี่ยงความลาดชันและรักษาความเคารพต่อสหายของคุณในสาขางาน คุณควรวางส่วนประกอบไว้ในไดเร็กทอรีที่เหมาะสม (เช่น วางไฟล์คอนโทรลเลอร์ในโฟลเดอร์คอนโทรลเลอร์ในสาขา "java") และเก็บอย่างระมัดระวัง การสั่งซื้อในที่ทำงานเอสเซ้นส์เป็นเพียงส่วนเล็ก ๆ ในกลไกอันยิ่งใหญ่
หรืออีกนัยหนึ่งคือ Model ของเราตามเงื่อนไขที่กำหนดในปัญหา ออกจากหัวข้อการอภิปรายและกลับไปที่โครงการเบื้องต้น เราสามารถยืนยันได้อย่างมั่นใจว่ามีความแตกต่างกันเล็กน้อยระหว่างงานและปฏิบัติตามแนวคิดโดยเฉลี่ยในการทบทวนเพิ่มเติม สมมติว่าบันทึกย่อในสมุดบันทึก ได้แก่ :- หมายเลขประจำตัวเพื่อกำหนดตำแหน่งในการไหลทั่วไป
- ข้อความตัวอักษรจำนวนหนึ่ง
- วันที่ที่ผู้ใช้เพิ่มลงในรายการทั่วไป
- ตัวแปรบูลีนเพื่อกำหนด “เสร็จสิ้นหรือไม่เสร็จสิ้น” (“อ่านหรือไม่อ่าน”)
@Entity
public class Note {
@Id
@GeneratedValue
private int id;
private String message;
private Date date;
private boolean done;
public Note() {
}
public Note(String message) {
this.message = message;
this.date = new Date();
this.done = false;
}
}
การเบี่ยงเบนไปจากหัวข้อการสนทนาเพื่อความเข้าใจที่มากขึ้นเกี่ยวกับสิ่งที่เกิดขึ้นจากตำแหน่งทางทฤษฎี การเชื่อมต่อระหว่างส่วนประกอบใน Spring ถูกกำหนดโดยคำอธิบายประกอบ - ตัวชี้พิเศษที่ด้านหน้าของวัตถุ ซึ่งแต่ละส่วนมีบทบาทเฉพาะในกลไกและเริ่มต้นด้วยสัญลักษณ์ “@” คำอธิบายประกอบ @Entity ระบุให้ Spring Boot ว่าข้อมูลคลาสที่ตามมาเป็นของ “Entity” และ @Id และ @GeneratedValue ระบุฟิลด์ที่เลือกเป็นตัวระบุพร้อมการสร้างตัววนซ้ำอัตโนมัติเมื่อประมวลผลอาร์เรย์ของข้อมูล ฉันตั้งใจละเว้นการเพิ่ม Getter และ Setter มาตรฐานเพื่อเพิ่มความกะทัดรัดของรูปแบบภาพ ต่อไป เมื่อคำนึงถึงการใช้ฐานข้อมูลในการจัดเก็บบันทึก เราไปยังขั้นตอนต่อไปในการพัฒนาแอปพลิเคชัน: เราจะสร้างอินเทอร์เฟซ NoteRepository ในไดเร็กทอรี "พื้นที่เก็บข้อมูล" ซึ่งเป็นองค์ประกอบที่เชื่อมต่อในห่วงโซ่การแลกเปลี่ยน และรับช่วงส่วนใหญ่ พื้นที่เก็บข้อมูลที่เหมาะสมสำหรับการทำงานต่อไป โดยระบุเอนทิตีที่เก็บไว้และตัววนซ้ำจำนวนเต็มเพื่อเข้าถึง
public interface NoteRepository extends JpaRepository<Note, Integer> {
}
จริงๆแล้วนั่นคือทั้งหมดที่ สั้นและกระชับ. ตอนนี้ Spring Boot จะใช้ส่วนประกอบที่สร้างขึ้นเพื่อจัดระเบียบการโต้ตอบกับฐานข้อมูล มีที่เก็บแบบเดิมหลายประเภทซึ่งมีศักยภาพในการดำเนินการที่แตกต่างกันออกไป JpaRepository อยู่ที่ด้านบนสุดของบันไดและมีศักยภาพสูงสุด รวมถึง CrudRepository และ PageAndSortingRepository ด้านล่าง เราจะไม่ไปไกลกว่านี้และเบี่ยงเบนไปจากหัวข้อนี้ เนื่องจากรายละเอียดปลีกย่อยบางส่วนสามารถพบได้บนเว็บไซต์ Pivotel ในเอกสารทางเทคนิค ตอนนี้ หลังจากใช้อิมเมจข้อมูลและระบุวิธีการสื่อสารในด้านแอปพลิเคชันแล้ว คุณต้องใส่ใจกับการสร้างฐานข้อมูล MySQL ในสภาพแวดล้อมภายนอกที่เหมาะสม “MySQL Workbench” ซึ่งติดตั้งไว้ล่วงหน้าบนแพลตฟอร์มเดสก์ท็อปในแอสเซมบลีจากนักพัฒนาอย่างเป็นทางการ พร้อมแพ็คเกจเพิ่มเติมสำหรับการสร้างเซิร์ฟเวอร์ภายในเครื่อง:

- ไม่มีประเภทบูลีนแยกจากกันเช่นนี้ การดำเนินการประมวลผลคำขอใด ๆ จะแปลง "จริง" หรือ "เท็จ" เป็นค่าบิต "1" หรือ "0" ตามลำดับ
- วันที่จะถูกจัดเก็บในรูปแบบการประทับเวลาทั้งหมด หากคุณใช้วันที่ซึ่งเป็นแกนหลักที่คุ้นเคย คุณจะต้องจำกัดตัวเองให้อยู่เฉพาะตำแหน่งในปฏิทินเท่านั้น

spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
และในที่สุดก็เชื่อมโยงเอนทิตี Note กับ MySQL โดยใช้คำอธิบายประกอบ @Table บ่งชี้ถึงการใช้ตารางที่มีชื่อและสคีมาที่เลือก และ @Column บ่งชี้ว่าตัวแปรอยู่ในเขตข้อมูลเฉพาะ
@Entity
@Table(name = "test", schema = "test", catalog = "")
public class Note {
@Id
@GeneratedValue
private int id;
@Column(name = "message")
private String message;
@Column(name = "date")
private Date date;
@Column(name = "done")
private boolean done;
public Note() {
}
public Note(String message) {
this.message = message;
this.date = new Date();
this.done = false;
}
}
มุมมองหรืออินเทอร์เฟซผู้ใช้
อนิจจาเราสามารถพูดได้อย่างปลอดภัยดังนี้: “การแสดงภาพแอปพลิเคชันจะกลายเป็นอุปสรรคสำคัญโดยปราศจากความรู้ทางทฤษฎีหรือปฏิบัติแม้แต่น้อย” พูดตามตรง ส่วนประกอบส่วนหน้าใช้เวลาทำงานจำนวนมหาศาลและทำให้ความกังวลของฉันหลุดลุ่ยอย่างมั่นใจในระยะเวลาอันยาวนาน แต่ด้วยความเรียบง่ายที่น่าทึ่งของ Thymeleaf มันจึงเป็นไปได้ที่จะพบการประนีประนอมที่เหมาะสมหลังจากความพ่ายแพ้ที่น่าหลงใหลมาหลายครั้ง การอภิปรายเพิ่มเติมจะเกี่ยวกับความซับซ้อนของการใช้เครื่องยนต์ที่เลือก แม้ว่าแนวคิดทั่วไปจะยึดติดกับตำแหน่งที่คล้ายกันก็ตาม เทคนิคหลักคือความสามารถในการใช้ HTML ที่บริสุทธิ์ที่สุดและประกอบการแสดงผลสุดท้ายจากแต่ละส่วนเพื่อหลีกเลี่ยงไม่ให้ส่วนที่เหมือนกันซ้ำกัน สมมติว่าสถาปัตยกรรม UI ประกอบด้วยหน้าหลักที่ประกอบด้วยแถบนำทางพร้อมตัวควบคุม (เพิ่มรายการใหม่ กลับไปยังหน้าหลัก) และตารางไดนามิกสำหรับการแสดงเอนทิตีโดยเรียงลำดับตามเวลาที่มีการเพิ่มบันทึกย่อจากน้อยไปมาก (ASC) หรือลดลง ( DESC) ทิศทาง ความหมาย ให้เราใช้เป็นตำแหน่งมาตรฐานในการแสดงบันทึกทั้งหมดตามลำดับจากน้อยไปหามาก ตามนโยบายลำดับชั้นของกลไกเทมเพลตที่เลือก องค์ประกอบการแสดงภาพส่วนประกอบควรอยู่ในสาขา "เทมเพลต" ในไดเร็กทอรี "ทรัพยากร" ดังนั้นการปรับเปลี่ยนส่วนประกอบเพิ่มเติมจะคำนึงถึงเงื่อนไขที่หยิบยกมาด้วย มาสร้างหน้าหลักด้วยชื่อ “index” (หรือชื่ออื่นตามความชอบส่วนบุคคล) บนเทมเพลต html5 กันดีกว่า ตัวอย่างเช่น:<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/head :: head"></head>
<body>
<div class="container">
<div th:replace="fragments/header :: header"></div>
<div th:if="${not #lists.isEmpty(notes)}">
<div th:replace="operations/list :: notebook"></div>
</div>
<div th:replace="fragments/footer :: footer"></div>
</div>
</body>
</html>
เรามาดูรายละเอียดส่วนประกอบสำคัญของการใช้งานขั้นสุดท้ายกันดีกว่า Thymeleaf ใช้ไวยากรณ์แยกต่างหากเพื่อระบุการใช้ขั้นตอนต่างๆ และเริ่มต้นด้วยคีย์เวิร์ด “th:” ซึ่งเป็นลิงก์ไปยังไลบรารีซึ่งจำเป็นต้องรวมอยู่ในแท็กเปิด <html>
<div th:if="${not #lists.isEmpty(notes)}">
การดำเนินการ "if" ไม่แตกต่างจากวิธีปกติในการทำสิ่งต่าง ๆ โดยสิ้นเชิงและจะตรวจสอบแอตทริบิวต์ "บันทึกย่อ" ที่เข้ามาเพื่อดูว่ามีวัตถุอยู่เพื่อแสดงต่อไปหรือไม่ เป็นเรื่องที่ควรกล่าวถึงการแยกหัวข้อที่ทับซ้อนกันด้วยการใช้คอนโทรลเลอร์โดยคำนึงถึงการใช้งานเพื่อจัดระเบียบการโต้ตอบของโมเดลและการแสดงภาพ ช่วงเวลาที่คลุมเครือมากมายเป็นรูปเป็นร่างในอนาคต เพียงย้อนกลับไปถ้าคุณต้องการ
<head th:replace="operations/list :: notebook"></head>
การดำเนินการ "แทนที่" บ่งชี้ถึงการแทนที่ "stub" หรือบล็อกที่ใช้งานอยู่ด้วยส่วนที่เลือกจากหน้าปัจจุบันหรือหน้าแยก - กรณีหลังนี้สังเกตได้อย่างชัดเจนในตัวอย่าง เราคัดลอกส่วนที่เรียกว่า "notebook" จาก "list.html" ของไดเร็กทอรี "operations" ไปยัง <div></div> ของไฟล์ "index" โดยแทนที่เนื้อหาในปลายทางสุดท้ายโดยสมบูรณ์ อันที่ส่งออกมีเนื้อหาดังต่อไปนี้:
<!DOCTYPE html>
<!--suppress ALL -->
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<div th:fragment="notebook">
<table class="table table-bordered table-hover horizontal-align">
<thead>
<tr>
<th style="width: 5%">#</th>
<th style="width: 60%">Message</th>
<th class="dropdown" style="width: 20%">Date
<a th:href="@{'/sort/{sortDate}' (sortDate = 'ASC')}"><i class="fa fa-chevron-circle-up"></i></a>
<a th:href="@{'/sort/{sortDate}' (sortDate = 'DESC')}"><i class="fa fa-chevron-circle-down"></i></a>
</th>
<th style="width: 5%">Done</th>
<th style="width: 5%">Edit</th>
<th style="width: 5%">Delete</th>
</tr>
</thead>
<tbody>
<tr th:each="note : ${notes}">
<td th:text="${note.id}" style="text-align: center">#</td>
<td th:text="${note.message}">Message</td>
<td th:text="${#dates.format(note.date, 'EEE, d MMM yyyy HH:mm')}" style="text-align: center">Date</td>
<td style="text-align: center">
<i th:if="${note.done} == true" class="fa fa-plus-square-o" style="font-size:20px;color:#337ab7"></i>
<i th:if="${note.done} == false" class="fa fa-minus-square-o" style="font-size:20px;color:#337ab7"></i>
</td>
<td style="text-align: center"><a th:href="@{'/edit/{id}'(id=${note.id})}"><i class="fa fa-edit" style="font-size:20px"></i></a></td>
<td style="text-align: center"><a th:href="@{'/delete/{id}'(id=${note.id})}"><i class="fa fa-trash" style="font-size:20px"></i></a></td>
</tr>
</tbody>
</table>
</div>
</html>
กลับไปที่ภาพรวมเชิงสร้างสรรค์และพิจารณาฟังก์ชัน Thymeleaf ที่ใช้ตามลำดับ โดยละเว้นไวยากรณ์ HTML มาตรฐานหรือสไตล์กราฟิกที่ใช้ และเน้นไปที่การทำความเข้าใจกลไกของกลไกเทมเพลตโดยเฉพาะ
<div th:fragment="notebook">
การดำเนินการ "แฟรกเมนต์" ระบุชื่อของแฟรกเมนต์และทำให้สามารถใช้เนื้อหาของบล็อกสำหรับคำสั่ง "แทนที่" ได้ นอกจากนี้! การใช้งานหลายรายการภายในหน้าเดียวจะไม่ได้รับการยกเว้น ทำให้เกิดความคล้ายคลึงกับขั้นตอนหรือฟังก์ชันในภาษาการเขียนโปรแกรมอีกครั้ง
<a th:href="@{'/sort/{sortDate}' (sortDate = 'ASC')}">
การเรียกคำอธิบายประกอบ @PostMapping ถูกใช้ในคอนโทรลเลอร์ด้วยการแมป “/sort/{sortDate}” โดยที่ {sortDate} เป็นแอตทริบิวต์ทิศทางการเรียงลำดับขาออก สิ่งที่คล้ายกันสามารถเห็นได้ในบล็อกต่อไปนี้ ซึ่งเพิ่มการเปลี่ยนแปลงแบบไดนามิก ขึ้นอยู่กับตำแหน่งขององค์ประกอบที่ผู้ใช้เลือกในการวนซ้ำ:
<a th:href="@{'/edit/{id}'(id=${note.id})}">
<tr th:each="note : ${notes}">
การแจกแจงค่านั้นคล้ายกันมากกับการใช้ for block ที่คุ้นเคยในไวยากรณ์ Java: ตัวแปร "note" รับองค์ประกอบปัจจุบันจากอาร์เรย์แอตทริบิวต์อินพุต ${notes} ซึ่งเป็นอาร์เรย์ของเอนทิตี และใช้เพื่อเปลี่ยนค่า ในภายหลัง พูดตามตรง เราสามารถอุทิศบทความแยกต่างหากเพื่อแสดงความสามารถที่หลากหลายของ Thymeleaf พร้อมตัวอย่างการใช้งานจริง - เครื่องมือเทมเพลตนั้นง่ายมากและไม่จำเป็นต้องเรียนรู้ไวยากรณ์เพิ่มเติมที่น่าประทับใจเลย ฟังก์ชั่นที่อธิบายไว้ข้างต้นมีการระบุไว้ในเอกสารทางเทคนิคบนเว็บไซต์อย่างเป็นทางการของนักพัฒนา และมีบทบาทสำคัญในการจัดการสื่อสารกับส่วนหลัง ดังนั้นคุณจึงสามารถก้าวไปสู่ส่วนถัดไปและส่วนสุดท้ายได้อย่างมั่นใจ แน่นอนโดยการแนบส่วนประกอบที่เหลือของการแสดงภาพในลิงก์ไปยังแอปพลิเคชันที่เสร็จสมบูรณ์ในตอนท้ายของบทความ
ผู้ควบคุม ผู้ดูแลระบบในบริษัทเล็กๆ
“รากฐานที่สำคัญในสถาปัตยกรรมของเว็บแอปพลิเคชัน” - อาจไม่มีทางหาคำอธิบายที่แม่นยำยิ่งขึ้นเกี่ยวกับความสำคัญของส่วนประกอบตัวควบคุมในการจัดระเบียบการทำงานของโปรแกรม: การดำเนินการส่วนใหญ่ดำเนินการอย่างแม่นยำโดยองค์ประกอบเชื่อมต่อระหว่าง โมเดลและมุมมอง ด้วยกลไกการทำงานของ Spring Boot คุณจึงสามารถใช้การแมปและวิธีการร้องขอ GET/POST ได้อย่างมั่นใจโดยไม่มีปัญหาแม้แต่น้อย และเชื่อมต่อที่เก็บข้อมูลโดยอัตโนมัติ มาสร้างคลาส NoteController ในไฟล์แยกต่างหากในไดเร็กทอรี “controllers” โดยอ้างอิงถึงการใช้คำอธิบายประกอบที่เหมาะสมอีกครั้ง:@Controller
public class NoteController {
private NoteService service;
@Autowired
public void setNoteService(NoteService service) {
this.service = service;
}
@GetMapping("/")
public String list(Model model) {
return "index";
}
}
การสังเกตอย่างระมัดระวังอาจสังเกตเห็นการเปลี่ยนแปลงที่สำคัญในการออกแบบสถาปัตยกรรมแอปพลิเคชันที่เกี่ยวข้องกับการเพิ่มบริการเพื่อแยกตรรกะทางธุรกิจจากการทำงานกับบริการการจัดการฐานข้อมูล การดำเนินการที่เสร็จสมบูรณ์นั้นจำเป็นต้องเพิ่มความคล่องตัวของผลิตภัณฑ์สำเร็จรูปและให้ขอบเขตที่กว้างสำหรับการเปลี่ยนแปลงการทำงานของส่วนต่อประสานผู้ใช้โดยไม่จำเป็นต้องเปลี่ยนวิธีการสื่อสารกับฐานข้อมูล การแสดงมาตรฐานไม่โดดเด่นจากกลุ่มที่คล้ายกัน: อินเทอร์เฟซอยู่ในไดเร็กทอรีแยกต่างหากและใช้งานโดยคลาสที่มีคำอธิบายประกอบ @Service สำหรับการตรวจจับ Spring Boot:
public interface NoteService {
Note getNoteById(Integer id);
void saveNote(Note note);
void updateNote(Integer id, String message, boolean done);
void deleteNote(Integer id);
List<Note> findAll();
}
@Service
public class NoteServiceImpl implements NoteService{
private NoteRepository repository;
@Autowired
public void setProductRepository(NoteRepository repository) {
this.repository = repository;
}
@Override
public Note getNoteById(Integer id) {
return repository.findOne(id);
}
@Override
public void saveNote(Note note) {
repository.save(note);
}
@Override
public void updateNote(Integer id, String message, boolean done) {
Note updated = repository.findOne(id);
updated.setDone(done);
updated.setMessage(message);
repository.save(updated);
}
@Override
public void deleteNote(Integer id) {
repository.delete(id);
}
@Override
public List<Note> findAll() {
return repository.findAll();
}
}
กลับไปที่การตรวจสอบคอนโทรลเลอร์และดูความซับซ้อนของการจัดระเบียบงานโดยใช้วิธี Spring Boot คำอธิบายประกอบ @Autowired บ่งชี้ถึงความจำเป็นในการผูกบริการกับตัวแปรที่ระบุประเภทที่เหมาะสมโดยอัตโนมัติ และสร้างการเชื่อมต่อกับฐานข้อมูล ควรให้ความสนใจมากขึ้นกับวิธีการสื่อสารของมุมมอง ซึ่งระบุโดยคำอธิบายประกอบ @GetMapping("/") ซึ่งจะส่งคืนเพจชื่อ "index" เมื่อได้รับการเรียกไปยัง localhost:8080 คุณสามารถใช้แนวทางอื่น โดยระบุคำอธิบายเพิ่มเติม @RequestMapping(value = "/", method = RequestMethod.GET) หรือแทนที่ประเภทการส่งคืนด้วย ModelAndView สำเร็จรูป อย่างไรก็ตาม ตามสถานะปัจจุบันของประสบการณ์ในการใช้งานจริง ฉันไม่สังเกตเห็นความแตกต่างพื้นฐานในผลลัพธ์สุดท้ายและใช้ตัวเลือกปกติ มาขยายคอนโทรลเลอร์ด้วยการเพิ่มองค์ประกอบใหม่โดยใช้แท็บเพิ่มเติม หลังจากที่ผู้ใช้คลิกที่องค์ประกอบแถบนำทาง @GetMapping("/new") จะถูกเรียกและเปลี่ยนเส้นทางไปยังหน้า "ใหม่" จากไดเร็กทอรี "การดำเนินการ" โดยส่งคืนพารามิเตอร์ชื่อ "ข้อความ" เมื่อยืนยันข้อมูลที่ป้อนโดยใช้ปุ่ม และเปลี่ยนเส้นทางไปยังบล็อกหลัก จำเป็นต้องกล่าวถึงเป็นพิเศษสำหรับความจำเป็นในการจับคู่ชื่อของตัวแปรในหน้าต่างอินพุตกับชื่อของค่าที่ถ่ายโอนโดยสมบูรณ์
<input type="text" class="form-control" id="message" th:name="message" placeholder="Enter your note." maxlength="100"/>
@GetMapping("/new")
public String newNote() {
return "operations/new";
}
@PostMapping("/save")
public String updateNote(@RequestParam String message) {
service.saveNote(new Note(message));
return "redirect:/";
}
เทคนิคที่คล้ายกันนี้ใช้ในการอัพเดตเรกคอร์ด หลังจากคลิกที่ตัวควบคุม ระบบจะเรียกการแมป @GetMapping("/edit/{id}") และตัวระบุจากสตริง URL จะถูกโอนย้าย คุณลักษณะ “note” จะถูกเพิ่มพร้อมกับรายการสำหรับการแก้ไขเพิ่มเติม @RequestParam(value = "done", required = false) boolean done) การระบุค่าเฉพาะมีบทบาทสำคัญในการใช้ช่องทำเครื่องหมายเมื่อใช้กลไกจัดการเทมเพลต Thymeleaf และตั้งค่าเป็น "false" ตามค่าเริ่มต้น
@GetMapping("/edit/{id}")
public String edit(@PathVariable Integer id, Model model) {
Note note = service.getNoteById(id);
model.addAttribute("note", note);
return "operations/edit";
}
@PostMapping("/update")
public String saveNote(@RequestParam Integer id, @RequestParam String message,
@RequestParam(value = "done", required = false) boolean done) {
service.updateNote(id, message, done);
return "redirect:/";
}
การลบรายการออกจากฐานข้อมูลทำได้ง่ายมาก และไม่ต้องการการจัดการที่สำคัญใดๆ โดยการเรียกใช้ฟังก์ชันบริการที่เหมาะสมโดยใช้ค่าที่ส่งผ่าน:
@GetMapping("/delete/{id}")
public String delete(@PathVariable Integer id) {
service.deleteNote(id);
return "redirect:/";
}
ตอนนี้เรามาปรับเปลี่ยนส่วนย่อยที่เสร็จแล้วกันเล็กน้อยแล้วก้าวไปสู่การสื่อสารที่น่าตื่นเต้นกับ MySQL โดยใช้การสืบค้นใน Spring Data JPA โดยเพิ่มฟังก์ชันสำหรับจัดการการกรองอย่างง่ายแยกกันก่อนที่จะปิดคอนโทรลเลอร์
@Controller
public class NoteController {
private String sortDateMethod = "ASC";
@GetMapping("/")
public String list(Model model) {
List<Note> notebook = filterAndSort();
model.addAttribute("notes", notebook);
model.addAttribute("sort", sortDateMethod);
return "index";
}
private List<Note> filterAndSort() {
List<Note> notebook = null;
switch (sortDateMethod) {
case "ASC":
notebook = service.findAllByOrderByDateAsc();
break;
case "DESC":
notebook = service.findAllByOrderByDateDesc();
break;
}
return notebook;
}
แบบสอบถามเล็กๆ แต่สำคัญมาก
เป็นเรื่องน่าอายที่ต้องยอมรับ การกรองค่าซึ่งตรงกันข้ามกับความคาดหวัง กลายเป็นอุปสรรคอีกประการหนึ่งในการทำงานทางเทคนิคให้สำเร็จ โดยเอาชนะเกณฑ์ความซับซ้อนที่กำหนดโดยการแบ่งหน้าได้อย่างมั่นใจ - แบ่งอาร์เรย์ข้อมูลออกเป็นหน้าที่แยกจากกันในขนาดที่กำหนดเพื่อแสดงผลต่อไป เป็นไปได้มากว่าความเหนื่อยล้าที่สะสมมากำลังส่งผลกระทบ แต่... แรงบันดาลใจเกิดขึ้นหลังจากการพบกับข้อความค้นหาโดยไม่ได้ตั้งใจpublic interface NoteRepository extends JpaRepository<Note, Integer> {
List<Note> findAllByOrderByDateAsc();
List<Note> findAllByOrderByDateDesc();
}
Spring Data JPA มอบความสามารถในการสร้างการสืบค้นฐานข้อมูลที่มีรายละเอียดสูง ซึ่งช่วยลดความจำเป็นในการจัดเรียงข้อมูลเมื่อได้รับแล้ว และมีศักยภาพในการใช้งานที่หลากหลาย ตัวอย่างเช่น:
List<Note> findAllByOrderByDateAsc();
วิธีการนี้จะถูกแปลงเป็นแบบสอบถาม SQL และแสดงระเบียนทั้งหมด (findAll) เรียงลำดับ (byOrder) ตามวันที่ (byDate) ตามลำดับจากน้อยไปหามาก (Asc) นอกจากนี้ คุณสามารถสร้างชุดค่าผสมที่ซับซ้อนและสุ่มตัวอย่างในหลายสาขาด้วยข้อกำหนดเดียว สมมติว่า เลือกเรกคอร์ดที่เสร็จสมบูรณ์ (byDoneTrue) ทั้งหมด (findAll) ตามลำดับ (byOrder) ลดลง (Decs) ตามค่าวันที่ (byDate):
Page<Note> findAllByDoneTrueOrderByDateDesc(Pageable pageable);
บทสรุปหรือคำสารภาพอื่นของโปรแกรมเมอร์มือใหม่
ทั้งหมด! คุณสามารถเปิดแอปพลิเคชันเว็บได้อย่างปลอดภัยโดยใช้ชุดค่าผสม Shift+F10 หรือโดยการคลิกที่ไอคอนที่เกี่ยวข้อง Spring Boot จะสร้างโปรแกรมบน Apache Maven และติดตั้งเซิร์ฟเวอร์ Apache Tomcat ในเครื่องที่ localhost:8080 ตอนนี้คุณเพียงแค่ต้องไปตามลิงก์ในเบราว์เซอร์ใดก็ได้

GO TO FULL VERSION