¿Por qué cuenta un acceso? Mi blog personal anterior era Bu Suanzi para el conteo de la visita al sitio, lo cual fue muy bueno, pero la respuesta fue lenta por muchas veces. En segundo lugar, mi blog personal era muy pocos para acceder y los datos no eran buenos para ver ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
La publicación de blog anterior introdujo brevemente la configuración y el uso de Redistemplate en Spring. Este artículo se considera un caso de aplicación simple, principalmente basado en contadores de Redis para implementar estadísticas.
I. Diseño
Un contador de acceso simple utiliza principalmente la estructura hash de Redis, y la estructura de almacenamiento correspondiente es la siguiente:
La estructura de almacenamiento es relativamente simple. Para expandirse, cada aplicación (o sitio) corresponde a una aplicación y luego pagine las estadísticas basadas en la ruta de la ruta. Finalmente, hay un recuento de acceso especial para declarar todo el sitio.
II. Implementación
Lo principal es usar la estructura hash de Redis y luego implementar estadísticas de datos. No es demasiado difícil. Puede referirse al entorno Redis en Spring Entorno:
Configuración y uso de Spring's RedistSplate
1. Clase de encapsulación de Redis
Para varios usados comúnmente, hemos hecho encapsulación simple, y usamos directamente el método excut de la plantilla redista. Por supuesto, también podemos usar Template.OpSforValue () y otros métodos convenientes. Aquí usamos JSON para serializar y deserializar objetos.
clase pública QuickRedisclient {Código de charset final estático privado = charset.forname ("UTF-8"); private static redistemplate <string, string> plantplate; Registro de voides estáticos públicos (redistemplate <string, string> template) {QuickRedisClient.template = Template; } public static void nullCheck (objeto ... args) {para (object obj: args) {if (obj == null) {tire nueva ilegalargumentException ("¡El argumento de redis no puede ser nulo!"); }}} public static byte [] tobytes (tecla de cadena) {nullCheck (clave); return key.getBytes (código); } public static byte [] [] tobytes (list <string> keys) {byte [] [] bytes = new byte [keys.size ()] []; int index = 0; for (clave de cadena: teclas) {bytes [index ++] = tobytes (clave); } bytes de retorno; } public static string getStr (clave de cadena) {return Template.exeCute ((rediscallback <string>) con -> {byte [] val = con.get (tobytes (key)); return val == null? null: new String (val);}); } public static void Putstr (clave de cadena, valor de cadena) {Template.exCute ((redisCallback <Void>) con -> {con.set (tobytes (key), tobytes (valor)); return null;}); } public static long inc (clave de cadena, long add) {return Template.Execute ((rediscallback <Along>) Con -> {Long Record = con.incrby (tobytes (clave), agregar); return registro == null? 0l: registro;}); } public static static long hincr (tecla de cadena, campo de cadena, long add) {return Template.execute ((rediscallback <Along>) con -> {long registro = con.hincrby (tobytes (key), tobytes (campo), add); return registro == null? 0l: registro;}); } public static <t> t hget (clave de cadena, campo de cadena, clase <t> clz) {return Template.ExeCute ((rediscallback <t>) con -> {byte [] registros = con.hget (tobytes (key), tobytes (campo)); if (Records == null) {return null;} return.parseObject (Records, Records, CLZ);}; } public static <t> map <string, t> hmget (clave de cadena, list <string> campos, class <t> clz) {list <byte []> list = Template.exeCute ((rediscallback <list <byte []>>) con -> con.hmget (tobytes (clave), tbytes (campos))); if (collectionUtils.isEmpty (list)) {return Collections.emptyMap (); } Map <string, t> dult = new HashMap <> (); for (int i = 0; i <fiields.size (); i ++) {if (list.get (i) == null) {continuar; } result.put (Fields.get (i), Json.ParseObject (list.get (i), clz)); } resultado de retorno; }} Clase de configuración correspondiente
paquete com.git.hui.story.cache.redis; import com.git.hui.story.cache.redis.serializer.defaultstrserializer; importar org.springframework.cache.cachemanager; importación de importación org.springframework.context.annotation.propertySource; import org.springframework.core.env.environment; import org.springframework.data.redis.cache.rediscachemanager; import og.springfrframework.data.redis.conconnection.redisconnectionFactory; importación; import org.springframework.data.redis.connection.redispersword; import org.springframework.data.redis.connection.lettuce.lettuceconnectionFactory; import org.springframework.data.redis.core.redistemplate;/*** creado por Yihui en 18:45 18/11/11. */@Configuration@PropertySource (value = "classpath: Application.yml") Public Class Redisconf {Entorno de entorno final privado; public Redisconf (Environment Environment) {this.environment = Environment; } @Bean public Cachemanager Cachemanager () {return Rediscachemanager.RediscachemanagerBuilder.FromConnectionFactory (redisConnectionFactory ()). Build (); } @Bean public Redistemplate <String, String> redistemplate (redisConnectionFactory redisConnectionFactory) {redistemplate <string, string> redistemplate = new Redistemplate <> (); redistemplate.setConnectionFactory (redisconnectionFactory); DefaultStrserializer Serializer = new DefaultStrserializer (); redistemplate.setValuueSerializer (serializador); redistemplate.SethashValuueSerializer (serializador); redistemplate.setKeySerializer (serializador); redistemplate.SethashKeySerializer (serializador); redistemplate.AfterPropertIesset (); QuickRediSclient.Register (redistemplate); regresar redistemplate; } @Bean public redisConnectionFactory redisConnectionFactory () {LetTucEconnectionFactory fac = new LetTucEConnectionFactory (); fac.getStandaloneconfiguration (). SethostName (Environment.getProperty ("Spring.redis.host")); fac.getStandalOneconfiguration (). SetPort (Integer.ParseInt (Environment.getProperty ("Spring.Redis.port"))); fac.getStandalOneconfiguration (). SetPassword (redisponsword.of (ambiente.getProperty ("spring.redis.password"))); fac.AfterPropertiesSet (); Fac de regreso; }} 2. Soporte del controlador
Primero, defina los parámetros de solicitud:
@DATAPublic Public Webcountreqdo implementa serializable {private string appKey; Referente de cadena privada;}El segundo es implementar la interfaz del controlador. Preste un poco de atención a la lógica de contar según el camino:
@Slf4j@restcontroller@requestmapping (path = "/count") public class WebCountController {@RequestMapping (path = "cc", método = {requestMethod.get}) public respuestaswrappers <centdto> addCount (webcountreqDo webcountreqdo) {String appPpApper = WebCountreAptEpTey (() (); if (stringUtils.isblank (appKey)) {return Responsewrapper.errorreturnmix (status.statusenum.illegal_params_mix, "¡Especifique appKey!"); } String referer = reqinfocontext.getreqinfo (). GetReferer (); if (StringUtils.isblank (referente)) {referente = webcoundreqdo.getreferer (); } if (StringUtils.isblank (referente)) {return responsewrapper.errorreturnmix (status.statusenum.fail_mix, "¡No se puede obtener solicitante!"); } return responsewrapper.successreturn (doupdateCnt (appKey, referente)); } private CountDto DoupDateCnt (String AppKey, String Referer) {try {if (! referente.startswith ("http")) {referente = "https: //" + referente; } Uri uri = nuevo uri (referente); String host = uri.gethost (); Ruta de cadena = uri.getPath (); recuento largo = QuickRediSclient.hincr (appKey, ruta, 1); Long Total = QuickRedIsClient.hincr (AppKey, Host, 1); devolver nuevo countdto (cuenta, total); } catch (Exception e) {log.error ("Obtener un error de ruta de referente! Referente: {}, e: {}", referente, e); devolver nuevo CountDTO (1L, 1L); }}}Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.