Por que uma conta de acesso? Meu blog pessoal anterior foi Bu Suanzi para a Visit Counting, o que foi muito bom, mas a resposta foi lenta por muitas vezes. Em segundo lugar, meu blog pessoal era muito poucos para acessar e os dados não eram bons para assistir ?…
A postagem anterior do blog introduziu brevemente a configuração e o uso do Redistemplate na primavera. Este artigo é considerado um caso de aplicação simples, principalmente com base nos contadores Redis para implementar estatísticas.
I. Design
Um contador de acesso simples usa principalmente a estrutura de hash dos redis, e a estrutura de armazenamento correspondente é a seguinte:
A estrutura de armazenamento é relativamente simples. Para expandir, cada aplicativo (ou site) corresponde a um aplicativo e, em seguida, pagina estatísticas com base no caminho do caminho. Finalmente, há uma contagem especial de acesso para declarar todo o site.
Ii. Implementação
O principal é usar a estrutura de hash dos redis e, em seguida, implementar as estatísticas de dados. Não é muito difícil. Você pode se referir ao ambiente Redis no ambiente da primavera:
Configuração e uso do Redistemplate da Spring
1. Classe de encapsulamento Redis
Para vários usados comumente usados, fizemos o encapsulamento simples e usamos diretamente o método de exclusiva do Redistemplate. Obviamente, também podemos usar o modelo.OpsforValue () e outros métodos convenientes. Aqui usamos o JSON para serializar e desserializar objetos.
classe pública QuickredIclient {private Static Final Charset Code = charset.ForName ("UTF-8"); Redistemplate estático privado <string, string> modelo; Registro de vazio estático público (Redistemplate <String, String> Modelo) {quickrediscient.template = modelo; } public static void nullCheck (objeto ... args) {for (objeto obj: args) {if (obj == null) {lança nova ilegalArgumentException ("Redis argumento não pode ser nulo!"); }}} public static byte [] tobytes (chave de string) {NullCheck (key); retornar key.getBytes (código); } public static byte [] [] Tobytes (list <string> keys) {byte [] [] bytes = new Byte [keys.size ()] []; int index = 0; para (chave de string: chaves) {bytes [index ++] = tobytes (chave); } retornar bytes; } public static string getttr (string key) {return modelo.execute ((Rediscallback <string>) con -> {byte [] val = con.get (tobytes (key); retorna val == null? null: new string (val);}); } public static void putstr (chave da string, value string) {template.execute ((Rediscallback <Void>) con } public static long inc (chave de string, long add) {return model.execute ((Rediscallback <long>) con } public static hincr longo (tecla String, campo de string, add) {return model.execute ((Rediscallback <long>) con } public static <t> t HGET (tecla String, campo de string, classe <t> clz) {retorna modelo.execute ((Rediscallback <t>) con -> {byte [] registros = con.hget (tobytes (chave), Tobytes (campo); if (registros == null) {return;}; } public static <t> map <string, t> hmget (chave da string, list <string> campos, classe <t> clz) {list <byte []> list = model.execute ((Rediscallback <list <byte [] >>) con. if (collectionutils.isempty (list)) {return collectionS.emptyMap (); } Mapa <string, t> resultado = novo hashmap <> (); for (int i = 0; i <fields.size (); i ++) {if (list.get (i) == null) {continuação; } resultado.put (campos.get (i), json.parseObject (list.get (i), clz)); } resultado de retorno; }} Classe de configuração correspondente
package com.git.hui.story.cache.redis;import com.git.hui.story.cache.redis.serializer.DefaultStrSerializer;import org.springframework.cache.CacheManager;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.propertysource; importar org.springframework.core.env.environment; importação org.springframework.data.redis.connection.rediscachemanager; import org.springframework.data.redis.connection.redischemanager; import org.springframework.datA.connection.connsection.redisconnlection; import org.springframework.data.connection.connsection.redisconnlection; import org.springframework.datA.connection.REDISCONCENCIONGERNSISCONCENCIONISTIONCENÇÃO; org.springframework.data.redis.connection.redispassword; importar org.springframework.data.redis.connection.lettuce.lettuceConnectionFactory; importen/11.springframework.data.redis.core.redistemplate;/** ** ** criado por yihiwork.data.redis.core.redemplate; */@Configuration@PropertySource (Value = "ClassPath: Application.yml") Classe public Redisconf {Private Final Environment Ambients; public Redisconf (ambiente ambiente) {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); Serializador de defaultstrSerializer = new DefaultStSerializer (); redistemplate.setValueSerializer (serializador); redistemplate.SethashValueSerializer (serializador); redistemplate.setKeySerializer (serializador); redistemplate.SethashKeySerializer (serializador); redistemplate.afterPropertiESSET (); Quickredisclient.register (redistemplate); return 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 (REBRECASSWORD.OF (Environment.getProperty ("spring.redis.password"))); fac.afterpropertiesset (); retornar fac; }} 2. Suporte ao controlador
Primeiro, defina os parâmetros de solicitação:
@Datapublic Class webcountreqdo implementa serializável {private string AppKey; Referente de String Private;}O segundo é implementar a interface do controlador. Preste um pouco de atenção à lógica de contar de acordo com o caminho:
@Slf4j@restcontroller@requestmapping (path = "/count") classe pública webcountController {@RequestMapping (path = "cc", método = {requestmethod.get}) publicKeyTappy) if (stringutils.isblank (AppKey)) {retorna ResponseWrapper.erRorreRorTurnMix (status.statusenum.illegal_params_mix, "Especifique o AppKey!"); } String referente = reqinfocontext.getReqinfo (). GetReferer (); if (stringUtils.isblank (referente)) {referente = webcountreqdo.getReferer (); } if (stringutils.isblank (referente)) {return ResponseWrapper.erRorreTurnMix (status.statusenum.fail_mix, "Não é possível obter solicitante!"); } Retornar ResponseWrapper.SuccessReturn (DoupDATecnt (AppKey, Referent)); } countddto privado doupDatecnt (string appKey, string referente) {try {if (! referent.startswith ("http")) {referent = "https: //" + referent; } Uri Uri = novo URI (referente); String host = uri.gethost (); String Path = Uri.getPath (); long count = quickredisclient.hinCr (AppKey, Path, 1); Total longo = QuickredIclient.hinCr (AppKey, host, 1); devolver novo countdto (contagem, total); } catch (Exceção e) {log.error ("Obtenha erro de caminho do referente! Referente: {}, e: {}", referente, e); devolver novo countdto (1L, 1L); }}}O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.