1 장 요구 사항 분석
팀의 오픈 소스 프로젝트에서 캐시 처리를 구현하기 위해 Redis를 추가 할 계획입니다. 비즈니스 기능은 부분적으로 구현 된 다음 Redis Tool 클래스를 작성한 다음 참조하여 변경량이 크며 디커플링을 달성 할 수 없으므로 스프링 프레임 워크의 AOP (섹션 지향 프로그래밍)를 생각했습니다.
오픈 소스 프로젝트 : https://github.com/u014427391/jeepatform
2 장 SpringBoot 소개
Javaee 프레임 워크 분야에서 중요한 오픈 소스 프레임 워크로서 Spring Framework는 엔터프라이즈 애플리케이션 개발에서 중요한 역할을합니다. 동시에, 스프링 프레임 워크와 서브 프레임은 많은 것이므로 지식의 양은 매우 넓습니다.
SPRINGBOOT : Spring Framework의 서브 프레임 (Microframework)은 2014 년에 시작된 프레임 워크입니다. 스프링 프레임 워크에 대한 모든 지식을 배우면 스프링 프레임 워크에는 필연적으로 많은 XML이 필요합니다. SpringBoot 프레임 워크를 사용하는 경우 주석 개발을 사용하여 스프링 프레임 워크를 기반으로 개발을 크게 단순화 할 수 있습니다. SpringBoot는 JavaconFig의 구성 모드를 최대한 활용하고 "컨벤션은 구성보다 낫다"는 개념을 사용하여 SpringMVC를 기반으로 웹 애플리케이션 및 REST 서비스의 개발을 크게 단순화 할 수 있습니다.
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 프레임 워크를 시작하려면 이전 기사를 참조하십시오 : http://www.vevb.com/article/111197.htm
4 장 REDIS 캐시 구현
4.1 다음 구조 다이어그램
프로젝트 구조 다이어그램 :
4.2 SpringBoot의 YML 파일 구성
MySQL, Druid 및 Redis가 주로 구성되는 Resource 아래에 Application.yml 구성을 추가하십시오.
Spring : DataSource : # Main Data Source Shop : URL : JDBC : mysql : //127.0.0.1 : 3306/jeepatform? autoreconnect = true & useUnicode = true & char com.alibaba.druid.pool.druiddatasource # 연결 풀 설정 Druid : 초기 크기 : 5 Min-Idle : 5 Max-Active : 20 # 연결 시간을 대기하는 데 시간 구성 Max-Wait : 60000 # 60000 # 닫히는 데 걸리는 데 걸리는 데 걸리는 데 걸리는 시간 : 60000에서 60000을 닫아야합니다. # 수영장에서 생존 할 수있는 최소 시간을 밀리 초, 밀리 초의 최소-예기 가능-시간-시간-밀리 스 : 300000 # Oracle을 사용하여 듀얼 검증-쿼리에서 선택 1을 선택하십시오 : 'X'테스트-바일 링크 : 실제 테스트-퇴직 : 허위 테스트 : 각 연결 풀에서 pscache의 크기를 지정합니다. 최대 풀 준비된 문자-연결 당 크기 : 20 # 통계 인터셉트 모니터링을위한 필터 구성. 모니터링 인터페이스를 제거한 후 SQL을 계산할 수 없으며, '벽'은 방화벽 필터에 사용됩니다 : STAT, WALL, SLF4J # ConnectProperties 속성을 통한 MERGESQL 기능; 느린 SQL 레코드 Connection-properties : druid.stat.mergesql = true; druid.stat.slowsqlmillis = 5000 # 여러 druiddatasource 사용 global-data-source-stat의 데이터 모니터링 데이터 : true jpa : database : mysql hibernate : show_sql : true ddlllll : true qu _sql : true _sql : true _sql : true _sql. Physical-Strategy : org.hibernate.boot.model.naming.naming.physicalnamingstrategystandardardimpl mvc : view : prefix :/web-inf/jsp/pubix : .jsp #jedis 구성 jedis : pool : 호스트 : 127.0.0.1 포트 : 6379 비밀번호 : 0 config : 10 maxidtal : 100 maxidtom : 10 maxidtom : 10 maxidtom : 10 maxidtom : 10 maxidtom : 10 maxidtom : 10 maxid. 100000
구성 클래스를 작성하여 구성을 시작하십시오. jedisconfig.java :
패키지 org.muses.jeepatform.config; import org.springframework.beans.beans.annotation.autowired; import org.springframework.bean.beans.annotation.qualifier; import org.spramframework.beans.annotation.value; import org.springframework.boot.autoconfigure.condition.conditionalonmissingbean; import org.springframework.boot.context.properties.configurationProperties; import org.springframework.context.annotation.bean; import org.springframework.context.anget redis.clients.jedis.jedispool; import redis.clients.jedis.jedispoolconfig; @configuration //@configurationProperties (prefix = jedisconfig.jedis_prefix) public class jedisconfig {// public static final String jedis_prefix = "Jedis"; @Bean (name = "jedispool") @autowired public jedispool jedispool (@qualifier ( "jedispoolconfig") jedispoolconfig config, @value ( "$ {spring.jedis.pool.host}") 문자열 호스트, @value ( "$ {spring.jedis.pool.pool.pool.pool.pool}" @Value ( "$ {spring.jedis.pool.timeout}") int timeout, @value ( "$ {spring.jedis.pool.password}") 문자열 암호) {return new jedispool (구성, 호스트, 포트, 타임 아웃, 암호); } @Bean (name = "jedispoolconfig") public jedispoolconfig jedispoolconfig (@value ( "$ {spring.jedis.pool.config.maxtotal}") int maxtotal, @value ( "$ {spring.jedis.pool.config.comidle}") int maxidle, @Value ( "$ {spring.jedis.pool.config.maxwaitmillis}") int maxwaitmillis) {jedispoolconfig config = new jedispoolconfig (); config.setmaxtotal (maxtotal); config.setmaxidle (maxidle); config.setmaxwaitmillis (Maxwaitmillis); 반환 구성; }}4.3 메타 공석 수업 쓰기
메타 주석 클래스 readiscache.java를 작성하십시오. 수정 된 주석으로 정의 된 모든 클래스는 AOP 캐시 처리에서 자동으로 구현됩니다.
package org.muses.jeepatform.annotation; import org.muses.jeepatform.common.rediscachenamespace; import java.lang.annotation.*;/***meta annotation은 database*/@documented@target (electmepe.method)@inter retonation (retentionpe.method)을 식별하는 데 사용됩니다. {// readiscachenamespace namespace ();} 보유 외에도 JDK 5에서 제공하는 다른 3 가지 주석, 즉 대상, 상속 및 문서화가 있습니다. 이를 바탕으로 사용자 정의 메타 주석을 구현할 수 있습니다
방법 방법 수준에 따라 RESISCACHE를 참조로 설정했습니다.
1. retentionpolicy.source이 유형의 주석은 소스 코드 수준에서만 예약되어 있으며 컴파일 중에 무시됩니다.
2. rendentionPolicy.class이 유형의 주석은 편집 중에 유지되며 클래스 파일에 존재하지만 JVM은이를 무시합니다.
3. rendentionPolicy.runtime이 유형의 주석은 JVM에 의해 예약되므로 JVM 또는 런타임에 반사 메커니즘을 사용하는 다른 코드에서 읽고 사용할 수 있습니다.
4.4 Redis 캐시 처리를 구현하기 위해 Jedispool에 전화하십시오
패키지 org.muses.jeepatform.cache; import org.springframework.bean.beans.beans.annotation.autouired; import org.spramepramework.stereotyp.component; import org.springframework.stereotyp.service; import redis.clients.jedis.jedis; import redis.clients.jedis.jedispool; javax.annotation.resource; @component ( "readiscache") public class readiscache {@autowired private jedispool jedispool; Private Jedispool getJedispool () {return jedispool; } public void setjedispool (Jedispool jedispool) {this.jedispool = jedispool; } / ** * redis cache에서 데이터 가져옵니다 * @param rediskey * @return * / public object getDataFromedis (String rediskey) {jedis jedis = jedispool.getResource (); 바이트 [] bytearray = jedis.get (rediskey.getBytes ()); if (bytearray! = null) {return serializeutil.unserialize (bytearray); } return null; } / ** * Redis에 데이터 저장 * @param rediskey * / public string savedatatoredis (String rediskey, object obj) {byte [] bytes = serialize.serialize (obj); Jedis Jedis = jedispool.getResource (); 문자열 코드 = jedis.set (rediskey.getBytes (), 바이트); 반환 코드; }}객체 직렬화 도구 클래스 :
package org.muses.jeepatform.cache; import java.io.*; public class serializeutil { / *** Serialized Object* @param obj* @return* / public static byte [] serialize (Object obj) {ObjectoutoutOutStream oos = null; BYTEARRAYOUTPUTSTREAM BAOS = NULL; try {baos = new BytearRayoutputStream (); OOS = 새로운 ObjectOutputStream (BAOS); oos.writeobject (obj); 바이트 [] bytearray = baos.tobytearray (); BytearRay 반품; } catch (ioexception e) {e.printstacktrace (); } return null; } / ** * Deserialize Object * @param bytearray * @return * / public static 객체 unserialize (byte [] bytearray) {bytearrayinputStream bais = null; try {// object bais에 대한 deserialize = new bytearrayinputstream (bytearray); ObjectInputStream OIS = New ObjectInputStream (BAIS); return ois.readobject (); } catch (예외 e) {e.printstacktrace (); } return null; }} 여기서 VO 클래스는 직렬화 가능해야한다는 것을 기억합니다
예를 들어, 메뉴 정보 VO 클래스, 이것은 JPA 매핑 엔티티 클래스입니다.
package org.muses.jeepatform.core.entity.admin; import javax.persistence.*; import java.io.serializable; import java.util.list;/*** @description 메뉴 정보 엔티티* @author nicky* @date 2017 년 3 월 17 일*/ @table (name = "sys _menu") @entitypublic instrements. { / ** 메뉴 ID ** / private int menuid; / ** 우수한 ID **/ private int parentid; / ** 메뉴 이름 **/ 개인 문자열 메뉴 이름; / ** 메뉴 아이콘 **/ 개인 문자열 메뉴; / ** 메뉴 URL **/ 개인 문자열 메뉴; / ** 메뉴 유형 **/ 개인 문자열 menutype; / ** 메뉴 정렬 **/ 개인 문자열 menuorder; / ** 메뉴 상태 **/ 개인 문자열 menustatus; 개인 목록 <메뉴> 하위 메뉴; 개인 문자열 대상; 개인 부울 Hassubmenu = 거짓; 공개 메뉴 () {super (); } @id @generatedValue (전략 = GenerationType.identity) public int getMenuid () {return this.menuid; } public void setMenuid (int menuid) {this.menuid = menuid; } @Column (길이 = 100) public int getParentId () {return parentid; } public void setparentId (int parentid) {this.parentid = parentid; } @Column (길이 = 100) public String getMenUname () {return this.menUname; } public void setMenUname (String Menuname) {this.menuname = menuname; } @Column (길이 = 30) public String getMenuicon () {return this.menuicon; } public void setMenuicon (String Menuicon) {this.menuicon = menuicon; } @Column (길이 = 100) public String getMenuurl () {return this.menuurl; } public void setMenuurl (String Menuurl) {this.menuurl = menuurl; } @column (length = 100) public String getMenUtype () {return this.menutype; } public void setMenUtype (String Menutype) {this.menutype = menutype; } @Column (길이 = 10) public String getMenuorder () {return Menuorder; } public void setMenuorder (String Menuorder) {this.menuorder = menuorder; } @Column (길이 = 10) public String getMenustatus () {return menustatus; } public void setMenustatus (String menustatus) {this.menustatus = menustatus; } @transient public list <메뉴> getSubmenu () {return submenu; } public void setsubmenu (list <menu> submenu) {this.submenu = submenu; } public void settarget (문자열 target) {this.target = target; } @transient public String getTarget () {return target; } public void sethassubmenu (부울 하부 메 누) {this.hassubmenu = hassubmenu; } @transient public boolean gethassubmenu () {return hassubmenu; }}4.5 스프링 AOP
먼저 Redis에서 캐시를 얻습니다. 쿼리 할 수없는 경우 MySQL 데이터베이스를 쿼리 한 다음 Redis 캐시에 저장하십시오. 다음에 쿼리 할 때 Redis 캐시에 직접 전화하십시오.
package org.muses.jeepatform.cache; import org.aspectj.lang.lang.proeessingjoinpoint; import org.aspectj.lang.annotation.around; import org.aspectj.lang.annotation.aspect; import org.aspectj.lang.annotation.spointcut; import org.slf4j.logger; org.slf4j.loggerfactory; import org.springframework.beans.beans.bean.annotation.autowired; import org.springframework.beans.beans.annotation.qualifier; import org.spramepramework.stereotyp.component;/*** aop steplic redis cache processing*@aop redis [email protected]@emport org.springframepramegring@org.springframepramegr.springframegring@emport org. 최종 로거 로거 = loggerfactory.getLogger (redisaspect.class); @autowired @qualifier ( "Rediscache") Private readiscache readiscache; /*** 모든 메타 주석을 가로 채는 방법 재정의 주석 재정의 주석* /@pointcut ( " @annotation (org.muses.jeepatform.annotation.rediscache)") 공개 void pointcutmethod () {} /*** 주변 처리의 경우 먼저 Redis에서 캐시를 얻습니다. 쿼리 할 수없는 경우 MySQL 데이터베이스를 쿼리 한 다음 * redis cache * @param joinpoint */@around ( "pointCutMethod ()") 공개 객체 주변 (ProceedingJoinPoint JoinPoint) {// previouse : 먼저 대상 메소드를 가져 오기 Long StartTime = Systemmillis (); 문자열 applid = null; Object [] args = joinpoint.getargs (); if (args! = null && args.length> 0) {applid = string.valueof (args [0]); } // 대상 메소드가 위치한 클래스를 얻습니다. String target target = joinpoint.getTarget (). ToString className = target.split ( "@") [0]; // 대상 메소드의 메소드 이름을 가져옵니다. String methodName = joinSignature (). getName (); // redis 키 형식 : applid : 메소드 이름 String rediskey = applid + ":" + className + ". + MethodName; Object obj = readiscache.getDatafromedis (rediskey); if (obj! = null) {logger.info ( "************ redis ****************"에서 찾은 데이터 "); logger.info ( "Redis Key value :"+rediskey); logger.info ( "Redis 값 값 :"+obj.tostring ()); 반환 obj; } long endtime = System.CurrentTimeMillis (); logger.info ( "Redis Cache AOP 처리 시간 :"+(endtime-startTime)); logger.info ( "*************** redis에서 찾은 데이터 없음 ****************"); try {obj = joinpoint.proceed (); } catch (Throwable e) {e.printstacktrace (); } logger.info ( "***************** MySQL에서 데이터 쿼리 시작 *************"); // post-set : 데이터베이스에있는 데이터를 redis string code = readiscache.savedatatoredis (rediskey, obj)에 저장합니다. if (code.equals ( "ok")) {logger.info ( "************ 데이터는 Redis 캐시에 성공적으로 저장되었습니다 !!! ************"); logger.info ( "Redis Key value :"+rediskey); logger.info ( "Redis 값 값 :"+obj.tostring ()); } return obj; }}
그런 다음 @rediscache에 전화하여 캐시를 구현하십시오
/ ** * 메뉴 ID * @param id * @return */ @transactional public menu findmenubyid (@rediscachekey ind id) {return menurepository.findmenubymenuid (id); }시스템에 로그인 한 다음 @rediscache 주석을 추가하는 메소드는 Redis 캐시 처리를 구현합니다.
Redis가 캐시에 저장된 것을 알 수 있습니다
프로젝트 코드 : https://github.com/u014427391/jeepatform
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.