JavaRush /จาวาบล็อก /Random-TH /พิชิตรองเท้าบูทสปริง
Surplus
ระดับ
Москва

พิชิตรองเท้าบูทสปริง

เผยแพร่ในกลุ่ม
ขอให้เป็นวันที่ดีผู้อ่านที่รัก! และยินดีที่ได้พบคุณแม้ว่าชื่อที่โอ่อ่าจะเป็นเหตุผลหลักในการดูหัวข้อที่เรียบง่ายเกี่ยวกับความใกล้ชิดครั้งแรกกับการพัฒนา Spring Boot ฉันต้องการแบ่งปันประสบการณ์ของฉันในการทำภารกิจเบื้องต้นสำหรับการฝึกงานในพอร์ทัล JavaRush โดยนำเสนอภาพรวมจากด้านข้างของนักศึกษามหาวิทยาลัยด้านเทคนิคธรรมดา ๆ ที่ต้องการทดสอบความแข็งแกร่งของความรู้ที่สั่งสมมา พิชิตรองเท้าบูทสปริง - 1ฉันจะไม่ปฏิเสธความหยาบคายที่เป็นไปได้ในโค้ดหรือวิธีการคิดที่แนบมา และฉันยินดีรับคำวิจารณ์ที่สร้างสรรค์ เพราะต้องขอบคุณ "การกระแทกและรอยฟกช้ำ" ที่ทำให้สามารถพัฒนาไปในทิศทางที่เป็นมืออาชีพได้ ยิ่งไปกว่านั้น ฉันไม่ได้แสร้งทำเป็น "ยาครอบจักรวาล" เลยในการแก้ไขเงื่อนไขที่กำหนดและจงใจละเว้นส่วนย่อยของโปรแกรมโดยทิ้งความสำคัญที่สำคัญของการเข้าสู่หัวข้อที่ค่อนข้างซับซ้อนโดยไม่มีผลกระทบต่อระบบประสาทแม้แต่น้อย เป็นความจริง มันไม่ประมาทที่จะปฏิเสธสิ่งที่ชัดเจน: มันยากสำหรับฉันและไม่มีอะไรชัดเจนเลยจนกระทั่งถึงช่วงเวลาหนึ่ง และหากคุณมีความรู้สึกคล้าย ๆ กันตั้งแต่ครั้งแรกที่พบกับงานนี้ ก็ให้ “ยินดีต้อนรับ!” มาเขียนเว็บแอปพลิเคชันใน Spring Boot โดยใช้การเปรียบเทียบแบบง่ายของการทดสอบเข้าฝึกงานโดยใช้เครื่องมือเทมเพลตThymeleafและqueryสืบค้นไปยังเซิร์ฟเวอร์ MySQL ในเครื่องเพื่อกรองอาร์เรย์ข้อมูลที่เข้ามา มาเริ่มกันเลย!

รองเท้าบูทสปริง มันเป็นสัตว์ชนิดใดและทำอย่างไร?

กล่าวโดยสรุปและกระชับ มันเป็นเครื่องมือที่ยอดเยี่ยมจากPivotelสำหรับการประหยัดเวลาอันมีค่าในกระบวนการสร้างแอปพลิเคชัน โดยไม่จำเป็นต้องเชื่อมต่อไลบรารีของบุคคลที่สามโดยตรง เขียนผืนผ้าใบการทำแผนที่และเซิร์ฟเล็ตที่น่าประทับใจ ก็เพียงพอแล้วที่จะใช้ Spring Initializr builder ซึ่งรวมเข้ากับIntelliJ IDEA Ultimate Edition (ไฟล์ - ใหม่ - โครงการ... - Spring Initializr) หรือตั้งอยู่บน บริการเว็บstart.spring.ioโดยระบุแพ็คเกจที่จะรวมจากหลากหลาย ข้อเสนอ
พิชิตรองเท้าบูทสปริง - 2
ตามข้อกำหนดทางเทคนิคที่นำเสนอ เราจะใช้ชุดสุภาพบุรุษ ซึ่งเป็นมาตรฐานสำหรับการสร้างเว็บแอปพลิเคชันอย่างง่ายโดยใช้ ฐานข้อมูล MySQL :
  • WEBเป็นองค์ประกอบหลักสำหรับการพัฒนาเว็บแอปพลิเคชัน รวมถึงเซิร์ฟเวอร์ Apache Tomcat ในเครื่องที่ที่อยู่มาตรฐาน localhost:8080 และเฟรม เวิร์ก Spring MVC สากล

  • DevTools - ใช้เพื่อรีสตาร์ทแอปพลิเคชันอย่างรวดเร็วใน JVM ที่ร้อนแรงเมื่อตรวจพบการเปลี่ยนแปลงในโค้ดหรือเทมเพลตที่คอมไพล์แล้ว ยิ่งไปกว่านั้น ยังช่วยให้ Thymeleaf ว่างจากการล้างแคชหากเอ็นจิ้นที่เลือกรวมอยู่ในโปรเจ็กต์

  • JPAเป็นเทคโนโลยีที่จำเป็นสำหรับการทำงานกับฐานข้อมูล และจัดให้มีการแมปเชิงวัตถุเชิงสัมพันธ์ของวัตถุ Java มี API ( ไฮเบอร์เนตในกรณีของเรา) สำหรับการจัดการ บันทึก และเรียกค้นเอนทิตี

  • Thymeleaf (Mustache, AngularJS, Vaadin และอื่นๆ) - เอ็นจิ้นเทมเพลตสำหรับการแสดงภาพแอปพลิเคชัน ด้วยความคุ้นเคยกับหลักการของ html ฉันจึงเลือก Thymeleaf ซึ่งผลักดันภาษาให้เป็นรากฐานที่สำคัญของโลก

  • MySQL - เชื่อมต่อไดรเวอร์การเชื่อมต่อฐานข้อมูล Java เพื่อดำเนินการสืบค้น SQL กับฐานข้อมูล
หลังจากการเลือกส่วนประกอบและการสร้างขั้นสุดท้าย เราจะได้สถาปัตยกรรมเว็บแอปพลิเคชันธรรมดาพร้อมไดเร็กทอรีที่พร้อมสำหรับการเติมเพิ่มเติม ชิ้นส่วนสำหรับการโต้ตอบกับส่วนที่เป็นภาพ ไม่ว่าจะเป็นสไตล์กราฟิก CSS, หน้า HTML มาตรฐาน หรือฟังก์ชันการทำงานของ JavaScript ควรอยู่ใน “ทรัพยากร” และองค์ประกอบแบ็คเอนด์จึงควรอยู่ใน “java” เราควรใส่ใจกับไฟล์ pom.xml ในช่วงรูทซึ่งจัดเก็บโครงสร้างโปรเจ็กต์และการขึ้นต่อกันระหว่างคอมโพเนนต์ หากคุณต้องการขยายฟังก์ชันการทำงานเพิ่มเติมด้วยแพ็คเกจเพิ่มเติมหรือลบสิ่งที่ไม่จำเป็นออก คุณควรดำเนินการจัดการระหว่างแท็ก<dependencies></dependencies>ตามวิธีการที่คล้ายกัน
พิชิตรองเท้าบูทสปริง - 3

ก้าวแรกสู่อนาคตอันยิ่งใหญ่

ต่อไปมีคำถามที่ค่อนข้างน่าสนใจและสมเหตุสมผลเกิดขึ้น:“ จะทำอย่างไรตอนนี้? วิธีนี้จะทำงานอย่างไร? โปรแกรมนี้สร้างขึ้นบนหลักการของ Model-View-Controller: มันจัดระเบียบการอ่านเอนทิตีจากฐานข้อมูลที่เชื่อมต่อ (Model) และแสดงในส่วนต่อประสานผู้ใช้พร้อมการควบคุม (ดู) การสื่อสารระหว่างส่วนประกอบและการดำเนินการตามคำขอที่ส่งนั้นดำเนินการโดยผู้ควบคุม เป็นการสร้างองค์ประกอบสำคัญที่ทำหน้าที่เป็นจุดอ้างอิงในการพัฒนาอย่างต่อเนื่อง เพื่อหลีกเลี่ยงความลาดชันและรักษาความเคารพต่อสหายของคุณในสาขางาน คุณควรวางส่วนประกอบไว้ในไดเร็กทอรีที่เหมาะสม (เช่น วางไฟล์คอนโทรลเลอร์ในโฟลเดอร์คอนโทรลเลอร์ในสาขา "java") และเก็บอย่างระมัดระวัง การสั่งซื้อในที่ทำงาน

เอสเซ้นส์เป็นเพียงส่วนเล็ก ๆ ในกลไกอันยิ่งใหญ่

หรืออีกนัยหนึ่งคือ Model ของเราตามเงื่อนไขที่กำหนดในปัญหา ออกจากหัวข้อการอภิปรายและกลับไปที่โครงการเบื้องต้น เราสามารถยืนยันได้อย่างมั่นใจว่ามีความแตกต่างกันเล็กน้อยระหว่างงานและปฏิบัติตามแนวคิดโดยเฉลี่ยในการทบทวนเพิ่มเติม สมมติว่าบันทึกย่อในสมุดบันทึก ได้แก่ :
  • หมายเลขประจำตัวเพื่อกำหนดตำแหน่งในการไหลทั่วไป
  • ข้อความตัวอักษรจำนวนหนึ่ง
  • วันที่ที่ผู้ใช้เพิ่มลงในรายการทั่วไป
  • ตัวแปรบูลีนเพื่อกำหนด “เสร็จสิ้นหรือไม่เสร็จสิ้น” (“อ่านหรือไม่อ่าน”)
ดังนั้น เรามาสร้างคลาส Note ในไดเร็กทอรีชื่อ "entity" และเพิ่มฟิลด์ที่เหมาะสม:
@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” ซึ่งติดตั้งไว้ล่วงหน้าบนแพลตฟอร์มเดสก์ท็อปในแอสเซมบลีจากนักพัฒนาอย่างเป็นทางการ พร้อมแพ็คเกจเพิ่มเติมสำหรับการสร้างเซิร์ฟเวอร์ภายในเครื่อง:
พิชิตรองเท้าบูทสปริง - 4
ต่อไป ทำตามคำแนะนำของสภาพแวดล้อมหลังจากคลิกที่ไอคอนเซิร์ฟเวอร์ท้องถิ่นปัจจุบันในหน้าต่างหลัก เราจะสร้างไดอะแกรมตารางตามฟิลด์ของเอนทิตีของเรา (หมายเหตุ) และกรอกข้อมูลด้วยข้อมูลที่เหมาะสม มีความจำเป็นต้องชี้แจงรายละเอียดปลีกย่อยของภาษา MySQL แยกต่างหากซึ่งต้องการความสนใจอย่างเร่งด่วนเพื่อให้บรรลุผลตามที่ต้องการ:
  • ไม่มีประเภทบูลีนแยกจากกันเช่นนี้ การดำเนินการประมวลผลคำขอใด ๆ จะแปลง "จริง" หรือ "เท็จ" เป็นค่าบิต "1" หรือ "0" ตามลำดับ
  • วันที่จะถูกจัดเก็บในรูปแบบการประทับเวลาทั้งหมด หากคุณใช้วันที่ซึ่งเป็นแกนหลักที่คุ้นเคย คุณจะต้องจำกัดตัวเองให้อยู่เฉพาะตำแหน่งในปฏิทินเท่านั้น
พิชิตรองเท้าบูทสปริง - 5
หลังจากเสร็จสิ้นขั้นตอนการเตรียมการขั้นสุดท้าย เราจะระบุ "MySQL Workbench" เพื่อส่งข้อมูลไปยังเซิร์ฟเวอร์ภายในเครื่องโดยคลิกที่ไอคอน "Lightning" บนแถบเครื่องมือ ตอนนี้ หากการเพิ่มข้อมูลเสร็จสมบูรณ์อย่างถูกต้อง เราก็สามารถกลับไปยัง IDE ดั้งเดิมของเราได้อย่างมั่นใจเพื่อดำเนินการพัฒนาต่อไปโดยการเพิ่มการกำหนดค่าฐานข้อมูลปัจจุบันให้กับ application.properties (โดยปกติจะอยู่ในไดเร็กทอรี “ทรัพยากร”):
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 ตอนนี้คุณเพียงแค่ต้องไปตามลิงก์ในเบราว์เซอร์ใดก็ได้
พิชิตรองเท้าบูทสปริง - 6
และแน่นอน พัฒนาวิธีการเพื่อตอบสนองความต้องการทางธุรกิจอื่นๆ ศักยภาพของแอปพลิเคชันถูกจำกัดด้วยความพยายาม ความรอบรู้ และจินตนาการของนักพัฒนา
พิชิตรองเท้าบูทสปริง - 7
ด้วยความตรงไปตรงมาและใส่ใจกับเส้นทางที่เดินทาง ฉันมั่นใจครั้งแล้วครั้งเล่าถึงความถูกต้องของทิศทางที่เลือก และตระหนักถึงประโยชน์ของการศึกษาบนพอร์ทัลการศึกษา JavaRush ด้วยงานภาคปฏิบัติที่หลากหลาย จึงเป็นไปได้ที่จะคืนความสนใจอันน่าดึงดูดใจในการเรียนรู้การเขียนโปรแกรม ซึ่งถูกระงับโดยสิ้นเชิงในโปรแกรมที่ล้าสมัยและน่าเบื่ออย่างน่าประหลาดใจของสถาบันการศึกษาระดับสูงในทิศทางเดียวกัน สี่เดือนของการศึกษาเนื้อหาในกลุ่มเทคโนโลยีแบ็คเอนด์อย่างกระตือรือร้นได้ลงทุนความรู้มากขึ้นมากเมื่อเทียบกับการเข้าร่วมการบรรยายและชั้นเรียนในห้องปฏิบัติการตลอดทั้งปี เชื่อหรือไม่. ฉันหวังว่าคุณจะไม่ยอมแพ้ต่อความยากลำบากในการเข้าสู่เนื้อหาที่ซับซ้อน เพราะว่าการเอาชนะอุปสรรคทำให้เราดีขึ้นและพัฒนาทั้งในด้านอาชีพและส่วนตัว ฉันหวังว่าเรื่องราวเล็กๆ นี้จะช่วยให้ฉันค้นพบไอเดียใหม่ๆ ในการใช้เครื่องมือที่น่าทึ่งที่เรียกว่า SpringBoot ป.ล. Github _
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION