พื้นหลัง
Springboot ได้ทำให้เป็นหนึ่งในกรอบการพัฒนาเว็บ Java ที่สำคัญที่สุดในปัจจุบันเนื่องจากมีปลั๊กอินนอกกรอบที่หลากหลาย MyBatis เป็นกรอบ ORM ที่มีน้ำหนักเบาและใช้งานง่าย Redis เป็นฐานข้อมูลคีย์-ค่าที่หลากหลายมากในปัจจุบัน ในการพัฒนาเว็บเรามักจะใช้มันเพื่อแคชผลลัพธ์การสืบค้นฐานข้อมูล
บล็อกนี้จะแนะนำวิธีการสร้างเว็บแอปพลิเคชันอย่างรวดเร็วโดยใช้ Springboot และใช้ MyBatis เป็นกรอบ ORM ของเรา เพื่อปรับปรุงประสิทธิภาพเราใช้ Redis เป็นแคชระดับที่สองสำหรับ mybatis ในการทดสอบรหัสของเราเราเขียนการทดสอบหน่วยและใช้ฐานข้อมูล H2 ในหน่วยความจำเพื่อสร้างข้อมูลการทดสอบของเรา ผ่านโครงการนี้เราหวังว่าผู้อ่านจะสามารถฝึกฝนทักษะและแนวปฏิบัติที่ดีที่สุดของการพัฒนาเว็บ Java ที่ทันสมัยได้อย่างรวดเร็ว
รหัสตัวอย่างสำหรับบทความนี้สามารถดาวน์โหลดได้ใน GitHub: https://github.com/lovelcp/spring-boot-mybatis-with-redis/tree/master
สิ่งแวดล้อม
สภาพแวดล้อมการพัฒนา: MAC 10.11
IDE: Intellij 2017.1
JDK: 1.8
Spring-Boot: 1.5.3.lelease
Redis: 3.2.9
mysql: 5.7
ฤดูใบไม้ผลิ
สร้างโครงการใหม่
ก่อนอื่นเราต้องเริ่มต้นโครงการฤดูใบไม้ผลิของเรา ผ่านการเริ่มต้นฤดูใบไม้ผลิของ Intellij มันเป็นเรื่องง่ายมากที่จะสร้างโครงการฤดูใบไม้ผลิใหม่ ก่อนอื่นเราเลือกโครงการใหม่ใน Intellij:
จากนั้นในอินเทอร์เฟซเพื่อเลือกการพึ่งพา, ตรวจสอบเว็บ, mybatis, redis, mysql, h2:
หลังจากโครงการใหม่ประสบความสำเร็จเราจะเห็นโครงสร้างเริ่มต้นของโครงการดังแสดงในรูปด้านล่าง:
Spring Initializer ช่วยให้เราสร้างคลาสเริ่มต้นโดยอัตโนมัติ - SpringbootMyBatiswithRedisApplication รหัสของคลาสนี้ง่ายมาก:
@springbootapplicationPublic คลาส SpringbootMyBatisWithRedIsapplication {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {springapplication.run (SpringbootMyBatiswithRedisapplication.class, args); -@springbootapplication Annotation หมายถึงการเปิดใช้งานคุณสมบัติการกำหนดค่าอัตโนมัติของ Spring Boot โอเคโครงกระดูกของโครงการของเราได้รับการสร้างสำเร็จเพื่อให้ผู้อ่านที่สนใจสามารถเริ่มผลลัพธ์ผ่าน Intellij
สร้างอินเทอร์เฟซ API ใหม่
ต่อไปเราจะเขียนเว็บ API สมมติว่าวิศวกรรมเว็บของเรารับผิดชอบในการจัดการผลิตภัณฑ์ของผู้ค้า (ผลิตภัณฑ์) เราจำเป็นต้องให้อินเทอร์เฟซ GET ที่ส่งคืนข้อมูลผลิตภัณฑ์ตามรหัสผลิตภัณฑ์และอินเทอร์เฟซที่อัปเดตข้อมูลผลิตภัณฑ์ ก่อนอื่นเรากำหนดคลาสผลิตภัณฑ์ซึ่งรวมถึงรหัสผลิตภัณฑ์ชื่อผลิตภัณฑ์และราคา:
ผลิตภัณฑ์ระดับสาธารณะใช้งาน serializable {ส่วนตัวคงที่สุดท้าย long serialversionuid = 1435515995276255188L; ID ยาวส่วนตัว; ชื่อสตริงส่วนตัว; ราคาส่วนตัว // getters setters}จากนั้นเราต้องกำหนดคลาสคอนโทรลเลอร์ เนื่องจาก Spring Boot ใช้ Spring MVC เป็นส่วนประกอบของเว็บภายในเราจึงสามารถพัฒนาคลาสอินเตอร์เฟสของเราได้อย่างรวดเร็วผ่านคำอธิบายประกอบ:
@restcontroller @requestmapping ("/product") คลาสสาธารณะ ProductController {@getMapping ("/{id}") ผลิตภัณฑ์สาธารณะ getProductInfo (@PathVariable ("id") ผลิตภัณฑ์ยาว) {// toDo return null; } @putMapping ("/{id}") ผลิตภัณฑ์สาธารณะ UpdateProductInfo (@PathVariable ("id") ProductId Long, @requestbody Product Product Newproduct) {// todo return null; -มาแนะนำฟังก์ชั่นของคำอธิบายประกอบที่ใช้ในรหัสด้านบนสั้น ๆ :
@RestController: หมายความว่าคลาสเป็นคอนโทรลเลอร์และให้อินเทอร์เฟซ REST นั่นคือค่าของอินเทอร์เฟซทั้งหมดจะถูกส่งกลับในรูปแบบ JSON คำอธิบายประกอบนี้เป็นคำอธิบายประกอบการรวมกันของ @Controller และ @ResponseBody ซึ่งช่วยให้เราพัฒนาส่วนที่เหลือ API
@RequestMapping, @GetMapping, @PutMapping: แสดงถึงที่อยู่ URL ของอินเทอร์เฟซ คำอธิบายประกอบ @requestmapping คำอธิบายประกอบในคลาสหมายความว่า URL ของอินเทอร์เฟซทั้งหมดภายใต้คลาสเริ่มต้นด้วย /ผลิตภัณฑ์ @getMapping หมายความว่านี่เป็นอินเตอร์เฟส HTTP, @putMapping หมายความว่านี่คืออินเทอร์เฟซ HTTP ที่ใส่
@PathVariable, @requestbody: แสดงถึงความสัมพันธ์การแมปของพารามิเตอร์ สมมติว่าการเข้าถึงคำขอรับ /ผลิตภัณฑ์ /123 คำขอจะถูกประมวลผลโดยวิธี getProductInfo โดยที่ 123 ใน URL จะถูกแมปเข้ากับ ProductID ในทำนองเดียวกันหากเป็นคำขอใส่ร่างกายที่ร้องขอจะถูกแมปเข้ากับวัตถุนิวเคลียส
ที่นี่เรากำหนดอินเทอร์เฟซเท่านั้นและตรรกะการประมวลผลจริงยังไม่เสร็จสมบูรณ์เนื่องจากข้อมูลของผลิตภัณฑ์มีอยู่ในฐานข้อมูล ต่อไปเราจะรวม mybatis ในโครงการและโต้ตอบกับฐานข้อมูล
การบูรณาการ mybatis
กำหนดค่าแหล่งข้อมูล
ก่อนอื่นเราต้องกำหนดค่าแหล่งข้อมูลของเราในไฟล์การกำหนดค่า เราใช้ MySQL เป็นฐานข้อมูลของเรา ที่นี่เราใช้ YAML เป็นรูปแบบของไฟล์การกำหนดค่าของเรา เราสร้างไฟล์ Application.yml ใหม่ในไดเรกทอรีทรัพยากร:
Spring:# DataBase Configuration DataSource: url: jdbc: mysql: // {your_host}/{your_db} ชื่อผู้ใช้: {your_username} รหัสผ่าน: {your_password} driver-class-name: org.gjt.mm.mysql.driverเนื่องจาก Spring Boot มีคุณสมบัติการกำหนดค่าอัตโนมัติเราไม่จำเป็นต้องสร้างคลาสการกำหนดค่าแหล่งข้อมูลใหม่ Spring Boot จะโหลดไฟล์การกำหนดค่าโดยอัตโนมัติและสร้างพูลการเชื่อมต่อฐานข้อมูลตามข้อมูลไฟล์การกำหนดค่าซึ่งสะดวกมาก
ผู้เขียนแนะนำให้คุณใช้ YAML เป็นรูปแบบไฟล์การกำหนดค่า XML ดูยาวและคุณสมบัติไม่มีโครงสร้างแบบลำดับชั้น Yaml เพิ่งทำขึ้นสำหรับข้อบกพร่องของทั้งคู่ นี่คือเหตุผลว่าทำไม Spring Boot รองรับรูปแบบ YAML โดยค่าเริ่มต้น
กำหนดค่า mybatis
เราได้แนะนำห้องสมุด MyBatis-Spring-Boot-Starte ใน POM.XML ผ่าน Spring Initializer ซึ่งจะช่วยให้เราเริ่มต้น mybatis โดยอัตโนมัติ ก่อนอื่นเรากรอกการกำหนดค่าที่เกี่ยวข้องของ mybatis ใน application.yml:
# mybatis กำหนดค่า mybatis: # กำหนดค่าชื่อแพ็คเกจที่คลาสการแม็พตั้งอยู่ที่ Type-aliases-package: com.wooyoo.learning.dao.domain # กำหนดค่าเส้นทางที่ไฟล์ Mapper XML อยู่นี่คืออาร์เรย์
จากนั้นกำหนดคลาส productmapper ในรหัส:
@mapperpublic อินเตอร์เฟส productmapper {ผลิตภัณฑ์เลือก (@param ("id") id ยาว); การอัปเดตเป็นโมฆะ (ผลิตภัณฑ์ผลิตภัณฑ์);}ที่นี่ตราบใดที่เราเพิ่มคำอธิบายประกอบ @mapper การบูตสปริงจะโหลดคลาส Mapper โดยอัตโนมัติเมื่อเริ่มต้น mybatis
เหตุผลที่ยิ่งใหญ่ที่สุดว่าทำไม Spring Boot จึงเป็นที่นิยมมากคือคุณสมบัติการกำหนดค่าอัตโนมัติ นักพัฒนาจำเป็นต้องให้ความสนใจกับการกำหนดค่าส่วนประกอบ (เช่นข้อมูลการเชื่อมต่อฐานข้อมูล) โดยไม่ต้องดูแลเกี่ยวกับวิธีการเริ่มต้นส่วนประกอบแต่ละตัวซึ่งช่วยให้เราสามารถมุ่งเน้นไปที่การใช้งานธุรกิจและทำให้กระบวนการพัฒนาง่ายขึ้น
การเข้าถึงฐานข้อมูล
หลังจากเสร็จสิ้นการกำหนดค่า MyBatis เราสามารถเข้าถึงฐานข้อมูลในส่วนต่อประสานของเรา เราแนะนำคลาส Mapper ผ่าน @autowired ภายใต้ ProductController และเรียกใช้วิธีการที่สอดคล้องกันเพื่อใช้การสืบค้นและอัปเดตการดำเนินการบนผลิตภัณฑ์ ที่นี่เราใช้อินเทอร์เฟซแบบสอบถามเป็นตัวอย่าง:
@restcontroller @requestmapping ("/product") คลาสสาธารณะ ProductController {@autoWired ProductMapper ProductMapper @getMapping ("/{id}") ผลิตภัณฑ์สาธารณะ getProductInfo (@PathVariable ("id") ผลิตภัณฑ์ยาว) {ส่งคืน productmapper.select (productId); } // หลีกเลี่ยงนานเกินไปและละเว้นรหัสของ UpdateProductInfo}จากนั้นแทรกข้อมูลผลิตภัณฑ์บางส่วนลงใน MySQL ของคุณและคุณสามารถเรียกใช้โครงการเพื่อดูว่าแบบสอบถามสำเร็จหรือไม่
จนถึงตอนนี้เราได้รวม MyBatis เข้ากับโครงการของเราสำเร็จเพิ่มความสามารถในการโต้ตอบกับฐานข้อมูล แต่นั่นไม่เพียงพอ โครงการเว็บที่ทันสมัยจะเร่งความเร็วแบบสอบถามฐานข้อมูลของเราบนแคชอย่างแน่นอน ต่อไปเราจะแนะนำวิธีการรวม REDIS เข้ากับแคชรองของ MyBatis เพื่อรับรู้แคชอัตโนมัติของการสืบค้นฐานข้อมูล
Redis แบบบูรณาการ
กำหนดค่า Redis
เช่นเดียวกับการเข้าถึงฐานข้อมูลเราจำเป็นต้องกำหนดค่าข้อมูลการเชื่อมต่อ Redis เพิ่มการกำหนดค่าต่อไปนี้ในไฟล์ application.yml:
Spring: Redis: # ดัชนีฐานข้อมูล Redis (ค่าเริ่มต้นคือ 0) เราใช้ฐานข้อมูลที่มีดัชนี 3 เพื่อหลีกเลี่ยงความขัดแย้งกับฐานข้อมูลฐานข้อมูลอื่น ๆ : 3 # ที่อยู่เซิร์ฟเวอร์ Redis (ค่าเริ่มต้นคือ localhost) โฮสต์: localhost # พอร์ต Redis (ค่าเริ่มต้นคือ 6379) พอร์ต: 6379 # รหัสผ่านการเข้าถึง Redis Infinite) Max-Active: 8 # จำนวนสูงสุดของการเชื่อมต่อที่ไม่ได้ใช้งาน (ค่าเริ่มต้นคือ 8, ตัวเลขติดลบแสดงถึงอนันต์) Max-Idle: 8 # จำนวนขั้นต่ำของการเชื่อมต่อที่ไม่ได้ใช้งาน (ค่าเริ่มต้นคือ 0 ค่านี้มีผลบังคับใช้เท่านั้น
รายการทั้งหมดข้างต้นเป็นการกำหนดค่าที่ใช้กันทั่วไปและผู้อ่านสามารถเข้าใจบทบาทเฉพาะของแต่ละรายการการกำหนดค่าผ่านข้อมูลความคิดเห็น เนื่องจากเราได้แนะนำไลบรารี Spring-Boot-Starter-Data-Redis ใน pom.xml, Spring Boot จะช่วยให้เราโหลดการเชื่อมต่อ REDIS โดยอัตโนมัติและคลาสการกำหนดค่าเฉพาะ
org.springframework.boot.autoconfigure.data.redis.redisautoconfiguration ผ่านคลาสการกำหนดค่านี้เราสามารถพบได้ว่าเลเยอร์พื้นฐานใช้ไลบรารีเจไดโดยค่าเริ่มต้นและจัดเตรียม redistemplate และ stringtemplate ออกจากกล่อง
ใช้ Redis เป็นแคชระดับ 2
หลักการของการแคชรองของ MyBatis จะไม่ได้รับการอธิบายในบทความนี้ ผู้อ่านจำเป็นต้องรู้ว่าการแคชรองของ MyBatis สามารถแคชแคชโดยอัตโนมัติและสามารถอัปเดตแคชโดยอัตโนมัติเมื่ออัปเดตข้อมูล
การใช้การแคชรองของ MyBatis นั้นง่ายมาก คุณจะต้องสร้างคลาสใหม่เพื่อใช้งานอินเตอร์เฟส org.apache.ibatis.cache.cache
มีห้าวิธีสำหรับอินเทอร์เฟซนี้:
String getId (): ตัวระบุของวัตถุการดำเนินงานแคช MyBatis Mapper สอดคล้องกับวัตถุการทำงานของแคช MyBatis
โมฆะ putobject (คีย์วัตถุค่าวัตถุ): สิ่งที่สืบค้นส่งผลลงในแคช
วัตถุ getObject (คีย์วัตถุ): รับผลลัพธ์การสืบค้นแคชจากแคช
Object RemoveObject (คีย์วัตถุ): ลบคีย์และค่าที่เกี่ยวข้องออกจากแคช ยิงเมื่อกลิ้งกลับเท่านั้น โดยทั่วไปเราไม่จำเป็นต้องนำไปใช้ สำหรับวิธีการใช้งานเฉพาะโปรดดูที่: org.apache.ibatis.cache.decorators.transactionalcache
Void Clear (): ล้างแคชเมื่อมีการอัปเดตเกิดขึ้น
int getsize (): การใช้งานเสริม ส่งคืนจำนวนแคช
ReadWriteLock getReadWriteLock (): การใช้งานเสริม ใช้ในการใช้งานการดำเนินการแคชอะตอม
ต่อไปเราสร้างคลาส Rediscache ใหม่เพื่อใช้งานอินเตอร์เฟสแคช:
การอ่านคลาสสาธารณะใช้แคช {ส่วนตัว logger สุดท้ายคงที่ logger = loggerFactory.getLogger (rediscache.class); Private Final ReadWriteLock ReadWriteLock = ใหม่ reentRantReadWriteLock (); รหัสสตริงสุดท้ายส่วนตัว; // แคชอินสแตนซ์ ID ส่วนตัว redistemplate private redistemplate; ส่วนตัวคงที่สุดท้าย Long Expire_time_in_minutes = 30; // redis เวลาหมดอายุการลงโทษสาธารณะ (string id) {ถ้า (id == null) {โยน unlegalargumentException ใหม่ ("อินสแตนซ์แคชต้องใช้รหัส"); } this.id = id; } @Override สตริงสาธารณะ getId () {return id; } / ** * ใส่ผลลัพธ์การสืบค้นไปที่ Redis * * @param key * @param value * / @Override @suppresswarnings ("Unchecked") โมฆะสาธารณะ putobject (คีย์วัตถุค่าวัตถุ) {redistemplate redistemplate = getRedistemplate () ValueOperations opsForValue = redistemplate.opSforValue (); opsforvalue.set (คีย์, ค่า, expire_time_in_minutes, timeunit.minutes); logger.debug ("ใส่ผลลัพธ์การสืบค้นกับ Redis"); } / ** * รับเคียวรีแคชผลลัพธ์จาก Redis * * @param key * @return * / @Override วัตถุสาธารณะ getObject (คีย์วัตถุ) {redistemplate redistemplate = getRedistemplate (); ValueOperations opsForValue = redistemplate.opSforValue (); logger.debug ("รับการสอบถามแคชผลลัพธ์จาก Redis"); return opsforvalue.get (คีย์); } / ** * ลบการสืบค้นแคชผลลัพธ์จาก Redis * * @param key * @return * / @Override @SuppressWarnings ("ไม่ได้ตรวจสอบ") วัตถุสาธารณะลบวุฒิการศึกษา (ปุ่มวัตถุ) {redistemplate redistemplate = getRedistemplate () Redistemplate.delete (คีย์); logger.debug ("ลบผลการค้นหาแคชออกมาจาก redis"); คืนค่า null; } / ** * ล้างอินสแตนซ์แคชนี้ * / @Override โมฆะสาธารณะล้าง () {redistemplate redistemplate = getRedistemplate (); REDISTEMPLATE.EXECUTE ((rediscallback) การเชื่อมต่อ -> {connection.flushdb (); return null;}); logger.debug ("ล้างการสืบค้นแคชทั้งหมดจาก Redis"); } @Override สาธารณะ int getSize () {return 0; } @Override สาธารณะ readWriteLock getReadWriteLock () {return readWriteLock; } ส่วนตัว redistemplate getRedistemplate () {ถ้า (redistemplate == null) {redistemplate = applicationContextholder.getBean ("Redistemplate"); } return redistemplate; -ให้ฉันอธิบายประเด็นสำคัญบางประการในรหัสด้านบน:
แคชระดับที่สองที่คุณใช้จะต้องมีตัวสร้างที่มี ID มิฉะนั้นจะมีการรายงานข้อผิดพลาด
เราใช้สปริง encapsulated redistemplate เพื่อใช้งาน REDIS บทความทั้งหมดออนไลน์ที่แนะนำ Redis ให้กับแคชรองของระดับ 2 ใช้ห้องสมุดเจไดโดยตรง แต่ผู้เขียนเชื่อว่านี่ไม่ใช่สไตล์ฤดูใบไม้ผลิที่ไม่เพียงพอ ยิ่งไปกว่านั้น Redistemplate ห่อหุ้มการใช้งานพื้นฐาน หากเราไม่ใช้เจไดในอนาคตเราสามารถแทนที่ไลบรารีพื้นฐานได้โดยตรงโดยไม่ต้องแก้ไขรหัสบน สิ่งที่สะดวกกว่าคือการใช้ Redistemplate เราไม่จำเป็นต้องสนใจเกี่ยวกับการเปิดตัวการเชื่อมต่อ Redis มิฉะนั้นจะง่ายสำหรับสามเณรที่จะลืมที่จะปล่อยการเชื่อมต่อและทำให้แอปพลิเคชันติดอยู่
ควรสังเกตว่า Redistemplate ไม่สามารถอ้างอิงผ่าน AutoWire ได้เนื่องจาก Rediscache ไม่ใช่ถั่วในภาชนะสปริง ดังนั้นเราจำเป็นต้องเรียกใช้วิธีการของ GetBean ด้วยตนเองเพื่อรับถั่วนี้ สำหรับวิธีการใช้งานเฉพาะโปรดดูรหัสใน GitHub
วิธีการทำให้เป็นอนุกรม Redis ที่เราใช้คือการทำให้เป็นอนุกรม JDK เริ่มต้น ดังนั้นวัตถุเคียวรีฐานข้อมูล (เช่นคลาสผลิตภัณฑ์) จำเป็นต้องใช้อินเทอร์เฟซแบบ serializable
ด้วยวิธีนี้เราใช้คลาสแคชที่สง่างามวิทยาศาสตร์และ Redis กับสไตล์ฤดูใบไม้ผลิ
เปิดแคชระดับ 2
ต่อไปเราต้องเปิดใช้งานแคชระดับ 2 ใน productmapper.xml:
<? xml version = "1.0" การเข้ารหัส = "utf-8"?> <! doctype mapper สาธารณะ "-// mybatis.org//dtd mapper 3.0 // en" "http://mybatis.org/dtd/mybatis-3-mapper.dtd namespace = "com.wooyoo.learning.dao.mapper.productmapper"> <!-เปิดใช้งานแคชรองที่ใช้ Redis-based-> <cache type = "com.wooyoo.learning.util.rediscache"/> <select id = "select" selectType = "Products" parameterType = "product" flushcache = "true"> อัปเดตผลิตภัณฑ์ที่ตั้งค่าชื่อ = #{ชื่อ}, price = #{ราคา} โดยที่ id = #{id} ขีด จำกัด 1 </update> </mapper><cache type = "com.wooyoo.learning.util.rediscache"/> หมายถึงการเปิดใช้งานแคชรองที่ใช้ Redis และในคำสั่งอัปเดตเราตั้งค่า flushcache เป็นจริงดังนั้นเมื่ออัปเดตข้อมูลผลิตภัณฑ์แคชสามารถไม่ถูกต้องโดยอัตโนมัติ
ทดสอบ
กำหนดค่าฐานข้อมูลหน่วยความจำ H2
ณ จุดนี้เราได้เสร็จสิ้นการพัฒนารหัสทั้งหมดและต่อไปเราต้องเขียนรหัสทดสอบหน่วยเพื่อทดสอบคุณภาพของรหัสของเรา ในกระบวนการพัฒนาเราใช้ฐานข้อมูล MySQL และโดยทั่วไปเรามักจะใช้ฐานข้อมูลในหน่วยความจำระหว่างการทดสอบ ที่นี่เราใช้ H2 เป็นฐานข้อมูลที่ใช้ในสถานการณ์การทดสอบของเรา
นอกจากนี้ยังใช้ H2 ได้ง่ายมากคุณเพียงแค่กำหนดค่าเมื่อใช้ MySQL ในไฟล์ application.yml:
--- ฤดูใบไม้ผลิ: โปรไฟล์: ทดสอบ # ฐานข้อมูลการกำหนดค่าฐานข้อมูล: URL: JDBC: H2: MEM: TEST USERNAME: รหัสผ่านรูท: 123456 DRIVER-CLASS-NAME: org.h2.driver schema: classpath: schema.sql ข้อมูล: classpath: data.sql.sql.sql.sql.sql
เพื่อหลีกเลี่ยงความขัดแย้งกับการกำหนดค่าเริ่มต้นเราใช้ --- เพื่อเริ่มย่อหน้าใหม่และใช้โปรไฟล์: ทดสอบเพื่อระบุว่านี่คือการกำหนดค่าในสภาพแวดล้อมการทดสอบ จากนั้นเพียงเพิ่มคำอธิบายประกอบ @ActiveProfiles (profiles = "test") ลงในคลาสทดสอบของเราเพื่อเปิดใช้งานการกำหนดค่าในสภาพแวดล้อมการทดสอบเพื่อให้คุณสามารถเปลี่ยนจากฐานข้อมูล MySQL ไปยังฐานข้อมูล H2 ด้วยคลิกเดียว
ในการกำหนดค่าข้างต้น schema.sql ใช้เพื่อจัดเก็บคำสั่งการสร้างตารางของเราและ data.sql ใช้เพื่อจัดเก็บข้อมูลแทรก ด้วยวิธีนี้เมื่อเราทดสอบ H2 จะอ่านสองไฟล์นี้เริ่มต้นโครงสร้างตารางและข้อมูลที่เราต้องการจากนั้นทำลายมันในตอนท้ายของการทดสอบซึ่งจะไม่มีผลกระทบใด ๆ ต่อฐานข้อมูล MySQL ของเรา นี่คือประโยชน์ของฐานข้อมูลในหน่วยความจำ นอกจากนี้อย่าลืมกำหนดขอบเขตของการพึ่งพา H2 เพื่อทดสอบใน pom.xml
การใช้ Spring Boot นั้นง่ายคุณสามารถสลับฐานข้อมูลในสภาพแวดล้อมที่แตกต่างกันได้อย่างง่ายดายโดยไม่ต้องแก้ไขรหัสใด ๆ
การเขียนรหัสทดสอบ
เนื่องจากเราเริ่มต้นผ่าน Spring Initializer เราจึงมีคลาสทดสอบอยู่แล้ว - SpringbootMyBatiswithRedIsapplicationTests
Spring Boot จัดเตรียมคลาสเครื่องมือบางอย่างที่อำนวยความสะดวกให้เราทำการทดสอบเว็บอินเตอร์เฟสเช่น TestRestTemplate จากนั้นในไฟล์การกำหนดค่าเราปรับระดับบันทึกเพื่อแก้ไขข้อบกพร่องเพื่ออำนวยความสะดวกในการสังเกตบันทึกการดีบัก รหัสทดสอบเฉพาะมีดังนี้:
@runwith (springrunner.class) @springboottest (webenvironment = springboottest.webenvironment.random_port) @ActiveProfiles (โปรไฟล์ = "ทดสอบ") ชั้นเรียนสาธารณะ SpringbootMyBatiswithRedisapplicationTests @AutoWired Private TestRestTemplate RestTemplate; @Test Public Void Test () {Long ProductId = 1; ผลิตภัณฑ์ผลิตภัณฑ์ = RestTemplate.getForObject ("http: // localhost:" + พอร์ต + "/ผลิตภัณฑ์/" + productId, product.class); assertThat (product.getPrice ()). isequalto (200); ผลิตภัณฑ์ newProduct = ผลิตภัณฑ์ใหม่ (); long newprice = new random (). nextlong (); newProduct.setName ("ชื่อใหม่"); newProduct.SetPrice (NewPrice); RestTemplate.put ("http: // localhost:" + พอร์ต + "/ผลิตภัณฑ์/" + productId, newproduct); Product TestProduct = RestTemplate.getForObject ("http: // localhost:" + พอร์ต + "/ผลิตภัณฑ์/" + productId, product.class); assertThat (testProduct.getPrice ()). isequalto (newprice); -ในรหัสทดสอบข้างต้น:
ก่อนอื่นเราโทรหาอินเทอร์เฟซ GET และใช้คำสั่ง Assert เพื่อพิจารณาว่าวัตถุที่คาดหวังนั้นได้รับหรือไม่ ในเวลานี้วัตถุผลิตภัณฑ์จะถูกเก็บไว้ใน Redis
จากนั้นเราเรียกอินเทอร์เฟซ Put เพื่ออัปเดตวัตถุผลิตภัณฑ์และแคช Redis จะไม่ถูกต้อง
ในที่สุดเราเรียกอินเทอร์เฟซ GET อีกครั้งเพื่อตรวจสอบว่าเราได้รับวัตถุผลิตภัณฑ์ใหม่หรือไม่ หากได้รับวัตถุเก่าหมายความว่ารหัสแคชที่ไม่ถูกต้องไม่สามารถดำเนินการและมีข้อผิดพลาดในรหัสมิฉะนั้นหมายความว่ารหัสของเราไม่เป็นไร
การทดสอบหน่วยการเขียนเป็นนิสัยการเขียนโปรแกรมที่ดี แม้ว่าจะต้องใช้เวลาเป็นระยะเวลาหนึ่งสำหรับคุณเมื่อคุณต้องการทำงาน Refactoring ในอนาคตคุณจะขอบคุณตัวเองที่เคยเขียนบททดสอบในอดีต
ดูผลการทดสอบ
เราคลิกเพื่อเรียกใช้กรณีทดสอบใน Intellij และผลการทดสอบมีดังนี้:
สีเขียวจะปรากฏขึ้นซึ่งระบุว่ากรณีทดสอบได้ดำเนินการสำเร็จแล้ว
สรุป
บทความนี้แนะนำวิธีการสร้างโครงการเว็บที่ทันสมัยอย่างรวดเร็วด้วย Spring Boot, MyBatis และ Redis และยังแนะนำวิธีการเขียนการทดสอบหน่วยอย่างสง่างามภายใต้ Spring Boot เพื่อให้แน่ใจว่าคุณภาพของรหัสของเรา แน่นอนว่ามีปัญหาอีกอย่างหนึ่งเกี่ยวกับโครงการนี้นั่นคือแคชระดับ 2 ของ MyBatis สามารถแคชได้โดยการล้างฐานข้อมูลทั้งหมด ในเวลานี้แคชบางอย่างที่ไม่จำเป็นต้องเป็นโมฆะอาจไม่ถูกต้องดังนั้นจึงมีข้อ จำกัด บางประการ