บทที่ 1 การวิเคราะห์ข้อกำหนด
มีการวางแผนที่จะเพิ่ม Redis เพื่อใช้การประมวลผลแคชในโครงการโอเพ่นซอร์สของทีม เนื่องจากฟังก์ชั่นทางธุรกิจได้รับการดำเนินการบางส่วนโดยการเขียนคลาสเครื่องมือ REDIS และจากนั้นอ้างถึงพวกเขาจำนวนของการเปลี่ยนแปลงมีขนาดใหญ่และไม่สามารถ decoupling ได้ดังนั้นฉันจึงนึกถึง AOP
โครงการโอเพ่นซอร์ส: https://github.com/u014427391/jeepatform
บทที่ 2 บทนำสู่ Springboot
ในฐานะที่เป็นเฟรมเวิร์กโอเพ่นซอร์สที่สำคัญในด้านกรอบงาน Javaee Framework Spring Framework มีบทบาทสำคัญในการพัฒนาแอปพลิเคชันระดับองค์กร ในเวลาเดียวกันกรอบฤดูใบไม้ผลิและเฟรมย่อยของมันมีจำนวนมากดังนั้นปริมาณของความรู้จึงกว้างมาก
Springboot: เฟรมย่อยของ Framework สปริงหรือที่เรียกว่า Microframework เป็นกรอบที่เปิดตัวในปี 2014 ที่ทำให้การพัฒนา Framework Spring เป็นเรื่องง่าย หลังจากเรียนรู้ความรู้ทั้งหมดเกี่ยวกับกรอบฤดูใบไม้ผลิเฟรมเวิร์กฤดูใบไม้ผลิย่อมต้องใช้ XML จำนวนมากอย่างหลีกเลี่ยงไม่ได้ หากคุณใช้ Frameworks Springboot คุณสามารถใช้การพัฒนาคำอธิบายประกอบเพื่อลดความซับซ้อนของการพัฒนาตามกรอบฤดูใบไม้ผลิ Springboot ใช้ประโยชน์จากโหมดการกำหนดค่าของ Javaconfig อย่างเต็มที่และแนวคิดของ "การประชุมดีกว่าการกำหนดค่า" ซึ่งสามารถทำให้การพัฒนาเว็บแอปพลิเคชันและบริการพักผ่อนได้ง่ายขึ้นอย่างมาก
บทที่ 3 บทนำสู่ Redis
3.1 การติดตั้งและการปรับใช้ Redis (Linux)
สำหรับการติดตั้งและการปรับใช้ Redis โปรดดูบล็อกของฉัน (Redis เขียนขึ้นอยู่กับ C ดังนั้นติดตั้งคอมไพเลอร์ GCC ก่อนการติดตั้ง): //www.vevb.com/article/79096.htm
3.2 บทนำสู่ Redis
ตอนนี้ Redis ได้กลายเป็นหนึ่งในฐานข้อมูลในหน่วยความจำที่ได้รับความนิยมมากที่สุดในชุมชนการพัฒนาเว็บ ด้วยการพัฒนาอย่างรวดเร็วของ Web2.0 และการเพิ่มขึ้นของสัดส่วนของข้อมูลกึ่งโครงสร้างเว็บไซต์มีความต้องการมากขึ้นเรื่อย ๆ เพื่อประสิทธิภาพที่มีประสิทธิภาพ
นอกจากนี้เว็บไซต์ขนาดใหญ่โดยทั่วไปมีเซิร์ฟเวอร์ Redis หลายร้อยตัวขึ้นไป ในฐานะที่เป็นระบบที่ทรงพลัง Redis มีการใช้งานของตัวเองไม่ว่าจะเป็นระบบจัดเก็บคิวหรือระบบแคช
สำหรับการเริ่มต้นใช้งาน Springboot Framework โปรดดูบทความก่อนหน้า: http://www.vevb.com/article/111197.htm
บทที่ 4 การใช้งานแคช Redis
4.1 แผนภาพโครงสร้างต่อไปนี้
แผนภาพโครงสร้างโครงการ:
4.2 การกำหนดค่าไฟล์ YML ของ Springboot
เพิ่มการกำหนดค่า application.yml ด้านล่างทรัพยากรที่ MySQL, DRUID และ REDIS ส่วนใหญ่จะถูกกำหนดค่า
ฤดูใบไม้ผลิ: DataSource: # แหล่งข้อมูลหลักร้านค้า: URL: JDBC: mysql: //127.0.0.1: 3306/jeepatform? autoreconnect = true & useunicode = true & areightencoding = utf8 com.alibaba.druid.pool.druiddatasource # การตั้งค่าพูลการเชื่อมต่อ DRUID: ขนาดเริ่มต้น: 5 นาที-ต่ำ: 5 MAX-ACTIVE: 20 # กำหนดค่าเวลาเพื่อให้การเชื่อมต่อรอการเชื่อมต่อสูงสุด: 60000 # กำหนดเวลาในการดำเนินการตรวจจับ กำหนดค่าเวลาขั้นต่ำเพื่อความอยู่รอดในสระว่ายน้ำในมิลลิวินาที min-evictable-idle-time-millis: 300000 # oracle โปรดใช้ Select 1 จากการตรวจสอบคู่-คำถาม: เลือก 'x'-idle: การทดสอบที่แท้จริง: การทดสอบเท็จ การเชื่อมต่อขนาดสูงสุดที่เตรียมไว้สูงสุด: 20 # กำหนดค่าตัวกรองสำหรับการตรวจสอบสถิติการสกัดกั้น หลังจากลบอินเทอร์เฟซการตรวจสอบ SQL ไม่สามารถนับได้ 'Wall' จะใช้สำหรับตัวกรองไฟร์วอลล์: Stat, Wall, SLF4J # Open MergesQL ฟังก์ชั่นผ่านคุณสมบัติ ConnectProperties; SLOW SQL Records Properties การเชื่อมต่อ: druid.stat.mergesql = true; druid.stat.slowsqlmillis = 5000 # ข้อมูลการตรวจสอบผสานข้อมูลของ druiddatasource การใช้งาน-global-data-source-stat: true jpa: database: mysql hibernate การตั้งชื่อ: Physical-Strategy: org.hibernate.boot.model.naming.PhysicalnamingStrategystandardimpl MVC: ดู: คำนำหน้า:/web-inf/jsp/คำต่อท้าย: .JSP #JEDIS การกำหนดค่า: MAXXTITION: MAXXTITION: MAXXTION: HOST: 127.0.0.0.1 พอร์ต: 6379 รหัสผ่าน: Maxwaitmillis: 100000
เขียนคลาสการกำหนดค่าเพื่อเริ่มการกำหนดค่า jedisconfig.java:
แพ็คเกจ org.muses.jeepatform.config; นำเข้า org.springframework.beans.factory.annotation.autowired; นำเข้า org.springframework.beans.factory.annotation.qualifier; org.springframework.boot.autoconfigure.condition.conditionalonmissingbean; นำเข้า org.springframework.boot.context.properties.configurationProperties; นำเข้า org.springframework.context.annotation.bean; redis.clients.jedis.jedispool; นำเข้า redis.clients.jedis.jedispoolconfig; @configuration //@configurationproperties (คำนำหน้า = jedisconfig.jedis_prefix) คลาสสาธารณะ jedisconfig {// @bean (name = "Jedispool") @autowired สาธารณะ Jedispool Jedispool (@qualifier ("jedispoolconfig") jedispoolconfig config, @value ("$ {spring.jedis.pool.host}") @value ("$ {spring.jedis.pool.timeout}") int หมดเวลา, @Value ("$ {spring.jedis.pool.password}") รหัสผ่านสตริง) {ส่งคืน Jedispool ใหม่ (config, โฮสต์, พอร์ต, หมดเวลา, รหัสผ่าน); } @bean (name = "jedispoolconfig") สาธารณะ jedispoolconfig jedispoolconfig (@value ("$ {spring.jedis.pool.config.maxtotal}") int Maxtotal, @value @value ("$ {spring.jedis.pool.config.maxwaitmillis}") int maxwaitmillis) {jedispoolconfig config = new Jedispoolconfig (); config.setmaxtotal (maxtotal); config.setMaxidle (maxidle); config.setmaxwaitmillis (Maxwaitmillis); ส่งคืนการกำหนดค่า; -4.3 การเขียนชั้นเรียน Meta-Annotation
เขียนคลาส Meta Annotation Rediscache.java คลาสทั้งหมดที่กำหนดโดยคำอธิบายประกอบที่แก้ไขจะถูกนำไปใช้โดยอัตโนมัติในการประมวลผลแคช AOP
แพ็คเกจ org.muses.jeepatform.annotation; นำเข้า org.muses.jeepatform.common.rediscachenamespace; นำเข้า java.lang.annotation.*;/***คำอธิบายประกอบเมตาใช้เพื่อระบุวิธีการที่ใช้ในการสอบถามฐานข้อมูล rediscache {// rediscachenamespace namespace ();} นอกเหนือจากการเก็บรักษาแล้วยังมีคำอธิบายประกอบอื่น ๆ อีกสามคำที่จัดทำโดย JDK 5 คือเป้าหมายที่สืบทอดและบันทึกไว้ จากสิ่งนี้เราสามารถใช้คำอธิบายประกอบเมตาที่กำหนดเองได้
เราตั้งค่า rediscache เป็นอ้างอิงตามระดับวิธีวิธี
1. RetentionPolicy.Source คำอธิบายประกอบประเภทนี้สงวนไว้ที่ระดับซอร์สโค้ดเท่านั้นและจะถูกละเว้นในระหว่างการรวบรวม
2. REATINGINTPOLICY.CLASS คำอธิบายประกอบประเภทนี้จะถูกเก็บไว้ในระหว่างการรวบรวมและมีอยู่ในไฟล์คลาส แต่ JVM จะไม่สนใจ
3. RECENTIONPICALY.RUNTIME คำอธิบายประกอบประเภทนี้จะถูกสงวนไว้โดย JVM ดังนั้นพวกเขาจึงสามารถอ่านและใช้งานได้โดย JVM หรือรหัสอื่น ๆ ที่ใช้กลไกการสะท้อนกลับที่รันไทม์
4.4 การโทรหา Jedispool เพื่อใช้การประมวลผลแคช Redis
แพ็คเกจ org.muses.jeepatform.cache; นำเข้า org.springframework.beans.factory.annotation.autowired; นำเข้า org.springframework.stereotype.Component; นำเข้า org.springframework.stereotype.service; redis.clients.jedis.jedispool; นำเข้า javax.annotation.resource; @component ("rediscache") คลาสสาธารณะ rediscache {@autowired ส่วนตัว Jedispool Jedispool; Private Jedispool GetJedispool () {return Jedispool; } โมฆะสาธารณะ SetJedispool (Jedispool Jedispool) {this.jedispool = Jedispool; } / ** * รับข้อมูลจาก Redis Cache * @param Rediskey * @return * / วัตถุสาธารณะ getDataFromredis (String rediskey) {Jedis Jedis = Jedispool.getResource (); ไบต์ [] bytearray = jedis.get (rediskey.getBytes ()); if (bytearray! = null) {return serializeutil.unserialize (bytearray); } return null; } / ** * บันทึกข้อมูลไปยัง Redis * @param Rediskey * / สตริงสาธารณะ Savedatatoredis (String rediskey, Object obj) {byte [] bytes = serializeutil.serialize (obj); Jedis Jedis = Jedispool.getResource (); รหัสสตริง = jedis.set (rediskey.getBytes (), ไบต์); รหัสส่งคืน; -Object Serialization Tool Class:
แพ็คเกจ org.muses.jeepatform.cache; นำเข้า java.io.*; คลาสสาธารณะ serializeutil { / *** วัตถุที่เป็นอนุกรม* @param obj* @return* / ไบต์คงที่สาธารณะ [] serialize (object obj) ByTeArrayOutputStream BAOS = NULL; ลอง {baos = ใหม่ byteArrayOutputStream (); oos = new ObjectOutputStream (BAOS); oos.writeObject (obj); ไบต์ [] bytearray = baos.tobytearray (); Bytearray กลับมา; } catch (ioexception e) {e.printstacktrace (); } return null; } / ** * deserialize object * @param byteArray * @return * / วัตถุคงที่สาธารณะ unserialize (byte [] bytearray) {byteArrayInputStream bais = null; ลอง {// deserialize ไปที่ Object bais = new ByteArrayInputStream (ByTearray); ObjectInputStream OIS = ใหม่ ObjectInputStream (BAIS); return ois.readObject (); } catch (exception e) {e.printstacktrace (); } return null; - ที่นี่ฉันจำได้ว่าคลาส VO ต้องใช้ serializable
ตัวอย่างเช่นข้อมูลเมนู VO คลาสนี่คือคลาสเอนทิตีการทำแผนที่ JPA
แพ็คเกจ org.muses.jeepatform.core.entity.admin; นำเข้า Javax.persistence.*; นำเข้า java.io.serializable; นำเข้า java.util.list;/*** @description Entity Entity* @author nicky* @ @@Date มีนาคม { / ** รหัสเมนู ** / ส่วนตัว Int เมนู INT; / ** ID ที่เหนือกว่า **/ Private Int Parentid; / ** ชื่อเมนู **/ Menuname สตริงส่วนตัว; / ** ไอคอนเมนู **/ เมนูสตริงส่วนตัว; / ** URL เมนู **/ สตริงส่วนตัวเมนู MENICORL; / ** ประเภทเมนู **/ สตริงส่วนตัว menutype; / ** เมนูเรียงลำดับ **/ สตริงส่วนตัวเมนูเมนู; / ** สถานะเมนู **/ สตริงส่วนตัว menustatus; รายการส่วนตัว <เมนู> เมนูย่อย; เป้าหมายสตริงส่วนตัว Boolean ส่วนตัว hassubmenu = false; เมนูสาธารณะ () {super (); } @id @GeneratedValue (strategy = generationType.Identity) สาธารณะ int getMenuid () {return this.menuid; } โมฆะสาธารณะ setMenuid (int menuid) {this.menuid = menuid; } @Column (ความยาว = 100) สาธารณะ int getParentId () {return parentId; } โมฆะสาธารณะ setParentId (int parentId) {this.parentId = parentId; } @Column (ความยาว = 100) สตริงสาธารณะ getMenUname () {return this.menuname; } โมฆะสาธารณะ setMenuname (Menuname String) {this.menuname = Menuname; } @column (ความยาว = 30) สตริงสาธารณะ getMenuicon () {return this.menuicon; } โมฆะสาธารณะ setMenuicon (String menuicon) {this.menuicon = menuicon; } @column (ความยาว = 100) สตริงสาธารณะ getMenuurl () {return this.menuurl; } โมฆะสาธารณะ setMenuurl (สตริงเมนู url) {this.menuurl = menuurl; } @column (ความยาว = 100) สตริงสาธารณะ getMenutype () {return this.menutype; } โมฆะสาธารณะ setMenutype (String menutype) {this.menutype = menutype; } @column (ความยาว = 10) สตริงสาธารณะ getMenuorder () {return menuorder; } โมฆะสาธารณะ setMenuorder (สตริงเมนู MenerOrder) {this.menuorder = menuorder; } @column (ความยาว = 10) สตริงสาธารณะ getMenustatus () {return menustatus; } โมฆะสาธารณะ setMenustatus (String menustatus) {this.menustatus = menustatus; } @Transient Public List <เมนู> getSubmenu () {ส่งคืนเมนูย่อย; } โมฆะสาธารณะ setSubMenu (รายการ <เมนู> เมนูย่อย) {this.submenu = เมนูย่อย; } โมฆะสาธารณะ settarget (เป้าหมายสตริง) {this.target = เป้าหมาย; } @Transient Public String getTarget () {return target; } โมฆะสาธารณะ sethassubmenu (boolean hassubmenu) {this.hassubmenu = hassubmenu; } @Transient Public Boolean Gethassubmenu () {return hassubmenu; -4.5 สปริง AOP ใช้เมธอดแคชที่ตรวจสอบทั้งหมดที่มีคำอธิบายประกอบโดย @Rediscache
ก่อนอื่นรับแคชจาก Redis หากคุณไม่สามารถสอบถามได้ให้สอบถามฐานข้อมูล MySQL แล้วบันทึกลงในแคช Redis ครั้งต่อไปที่คุณสอบถามโทรหาแคช Redis โดยตรง
แพ็คเกจ org.muses.jeepatform.cache; นำเข้า org.aspectj.lang.proceedingjoinpoint; นำเข้า org.aspectj.lang.annotation.around; นำเข้า org.aspectj.lang.annotation.aspect; org.slf4j.loggerfactory; นำเข้า org.springframework.beans.factory.annotation.autowired; นำเข้า org.springframework.beans.factory.annotation.qualifier; นำเข้า org.springframework.stereotype.Component; redisaspect {ส่วนตัวคงที่ logger สุดท้าย logger = loggerFactory.getLogger (redisaspect.class); @autowired @qualifier ("rediscache") rediscache ส่วนตัว rediscache rediscache; /*** วิธีการสกัดกั้นคำอธิบายประกอบ meta ทั้งหมด rediscache คำอธิบายประกอบ* /@pointcut (" @annotation (org.muses.jeepatform.annotation.rediscache)") โมฆะสาธารณะ pointcutmethod () {} /*** สำหรับการประมวลผลรอบ ๆ หากคุณไม่สามารถสอบถามได้คุณจะสืบค้นฐานข้อมูล MySQL * จากนั้นบันทึกลงใน Redis Cache * @Param JoinPoint * @return */@Around ("PointCutMethod ()") วัตถุสาธารณะรอบ ๆ สตริง applid = null; Object [] args = joinpoint.getargs (); if (args! = null && args.length> 0) {applid = string.valueof (args [0]); } // รับคลาสที่เมธอดเป้าหมายอยู่ที่สตริงเป้าหมายเป้าหมาย = joinPoint.getTarget (). toString className = target.split ("@") [0]; // รับชื่อเมธอดของเมธอดเมธอดเมธอดเมธอด name = joinpoint.getSignature (). getName (); // รูปแบบคีย์ Redis: applId: ชื่อสตริงเมธอด rediskey = applid + ":" + classname + " + MethodName; Object OBJ = rediscache.getDataFromredis (Rediskey); if (obj! = null) {logger.info ("************ ข้อมูลที่พบจาก Redis ******************"); logger.info ("ค่าคีย์ Redis:"+Rediskey); logger.info ("ค่า redis ค่า:"+obj.toString ()); คืน OBJ; } endtime long = system.currentTimeMillis (); logger.info ("Redis Cache AOP เวลาประมวลผล:"+(endtime-starttime)); logger.info ("************* ไม่พบข้อมูลจาก Redis **************"); ลอง {obj = joinpoint.proceed (); } catch (throwable e) {e.printstacktrace (); } logger.info ("*************** เริ่มสอบถามข้อมูลจาก mysql *************"); // post-set: บันทึกข้อมูลที่พบในฐานข้อมูลเป็น redis string code = rediscache.savedatatoredis (Rediskey, OBJ); if (code.equals ("ok")) {logger.info ("************ ข้อมูลถูกบันทึกไว้ใน Redis Cache สำเร็จ !!! ************"); logger.info ("ค่าคีย์ Redis:"+Rediskey); logger.info ("ค่า redis ค่า:"+obj.toString ()); } return obj; -จากนั้นโทร @rediscache เพื่อใช้แคช
/ ** * รับข้อมูลเมนูผ่านรหัสเมนู * @param id * @return */ @transactional @rediscache เมนูสาธารณะ findmenubyid (@rediscachekey int id) {return menurepository.findmenubymenuid (id); -วิธีการที่ลงชื่อเข้าใช้ระบบจากนั้นเพิ่มคำอธิบายประกอบ @rediscache จะใช้การประมวลผลแคช REDIS
คุณจะเห็นว่า Redis ถูกบันทึกไว้ในแคช
รหัสโครงการ: https://github.com/u014427391/jeepatform
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น