当前位置: 首页 > wzjs >正文

手机网站吧wordpress导航插件

手机网站吧,wordpress导航插件,微同步网站,网站建设柒金手指排名二一在某个mysqlredis的业务中,有个根据id查询用户表数据逻辑,逻辑为: 1、先从redis中查询,如果redis中有,则返回redis结果 2、如果redis中没有,则查询mysql 3、将查出的结果放入redis中,并在方法中…

在某个mysql+redis的业务中,有个根据id查询用户表数据逻辑,逻辑为:
1、先从redis中查询,如果redis中有,则返回redis结果
2、如果redis中没有,则查询mysql
3、将查出的结果放入redis中,并在方法中返回该查询结果
代码如下:

@Override
public User getUserById(Integer id) {User user = null;//1 拼装缓存keyString key = CACHE_KEY_USER + id;//2 查询redisuser = (User)redisTemplate.opsForValue().get(key);//3 redis无,进一步查询mysqlif (user == null) {//3.1 从mysql查出来useruser = this.userMapper.selectByPrimaryKey(id);//3.2 mysql有,redis无if (user != null) {//3.3 把mysql捞到的数据写入redis,方便下次查询能redis命中。redisTemplate.opsForValue().set(key, user);}}//4 redis有,直接返回return user;
}

这样写逻辑是没有问题的,但是如果以后有更多类似的需求,难道每个方法里面都要写这么长一串的重复判断逻辑吗?并且今天业务可能根据id来查询,明天需求变更,根据username查询,要改的话就比较麻烦了

因此,我们可以通过热拔插AOP+反射+Redis自定义缓存注解+SpringEL表达式,重构缓存代码,思路来源链接

通过编写通用组件,代码可精简到如下程度,以后有类似的mysql+redis需求,也只需要一个注解即可使用。通过修改#后面的值,保持值和方法传参名一致

@Override
@MyRedisCache(keyPrefix = "user",matchValue = "#id")
public User getUserById(Integer id){return userMapper.selectByPrimaryKey(id);
}

项目结构:标准的Springboot
在这里插入图片描述
pom.xml:引入mybatisplus、mysql驱动、lombok、redis、asepct相关

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.4.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>org.example</groupId><artifactId>my-redis</artifactId><version>0.0.1-SNAPSHOT</version><name>my-redis</name><description>my-redis</description><url/><licenses><license/></licenses><developers><developer/></developers><scm><connection/><developerConnection/><tag/><url/></scm><properties><java.version>21</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.36</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.10.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.20</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.11</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.22.1</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.properties:配置了redis和sql数据源

spring.application.name=my-redis
server.port=8081spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/你的库?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
spring.datasource.username=你的账号
spring.datasource.password=你的密码spring.data.redis.database=0
spring.data.redis.host=127.0.0.1
spring.data.redis.port=6379
spring.data.redis.password=
spring.data.redis.lettuce.pool.max-active=8
spring.data.redis.lettuce.pool.max-wait=-1ms
spring.data.redis.lettuce.pool.max-idle=8
spring.data.redis.lettuce.pool.min-idle=0

启动类:无改动,保持默认

package org.example.myredis;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class MyRedisApplication {public static void main(String[] args) {SpringApplication.run(MyRedisApplication.class, args);}}

RedisConfig:标准的序列化配置,注意额外加上注解@EnableAspectJAutoProxy,作用是开启AOP自动代理

package org.example.myredis.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;/**** @author xiajunfeng*/
@Configuration
@EnableAspectJAutoProxy //V2  开启AOP自动代理
public class RedisConfig {/*** @param lettuceConnectionFactory* @return redis序列化的工具配置类,下面这个请一定开启配置* 127.0.0.1:6379> keys ** 1) "ord:102"  序列化过* 2) "\xac\xed\x00\x05t\x00\aord:102"   野生,没有序列化过*/@Beanpublic RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(lettuceConnectionFactory);//设置key序列化方式stringredisTemplate.setKeySerializer(new StringRedisSerializer());//设置value的序列化方式jsonredisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.afterPropertiesSet();return redisTemplate;}}

实体类User:记得在数据库中也创建表t_user,字段只有id和username即可

package org.example.myredis.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.io.Serializable;/*** @author xiajunfeng*/
@Data
@TableName("t_user")
public class User implements Serializable {@TableId(type = IdType.AUTO)private Integer id;@TableFieldprivate String username;}

UserController

package org.example.myredis.controller;import jakarta.annotation.Resource;
import org.example.myredis.entity.User;
import org.example.myredis.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;/*** UserController* @author xiajunfeng* @date 2025/03/09*/
@RestController
public class UserController {@Resourceprivate UserService service;@GetMapping(value = "/user/{id}")public User getUserById(@PathVariable("id") Integer id) {return service.getUserById(id);}}

UserService

package org.example.myredis.service;import org.example.myredis.entity.User;/*** @author xiajunfeng*/
public interface UserService {User getUserById(Integer id);}

UserServiceImpl:注意这里使用了自定义注解@MyRedisCache

package org.example.myredis.service.impl;import jakarta.annotation.Resource;
import org.example.myredis.annotation.MyRedisCache;
import org.example.myredis.entity.User;
import org.example.myredis.mapper.UserMapper;
import org.example.myredis.service.UserService;
import org.springframework.stereotype.Service;/*** UserServiceImpl* @author xiajunfeng* @date 2025/03/09*/
@Service
public class UserServiceImpl implements UserService {@Resourceprivate UserMapper userMapper;@Override@MyRedisCache(keyPrefix = "user",matchValue = "#id")public User getUserById(Integer id) {return userMapper.selectById(id);}}

UserMapper

package org.example.myredis.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.example.myredis.entity.User;/*** @author xiajunfeng*/
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

自定义注解MyRedisCache

package org.example.myredis.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** MyRedisCache* @author xiajunfeng* @date 2025/03/09*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRedisCache {String keyPrefix();String matchValue();}

最后一个就是关键的AOP:MyRedisCacheAspect

package org.example.myredis.aop;import jakarta.annotation.Resource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.example.myredis.annotation.MyRedisCache;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;/*** MyRedisCacheAspect* @author xiajunfeng* @date 2025/03/09*/
@Component
@Aspect
public class MyRedisCacheAspect {@Resourceprivate RedisTemplate redisTemplate;@Around("@annotation(org.example.myredis.annotation.MyRedisCache)")public Object doCache(ProceedingJoinPoint joinPoint) {Object result = null;try {//1 获得重载后的方法名MethodSignature signature = (MethodSignature)joinPoint.getSignature();Method method = signature.getMethod();//2 确定方法名后获得该方法上面配置的注解标签MyRedisCacheMyRedisCache myRedisCacheAnnotation = method.getAnnotation(MyRedisCache.class);//3 拿到了MyRedisCache这个注解标签,获得该注解上面配置的参数进行封装和调用String keyPrefix = myRedisCacheAnnotation.keyPrefix();String matchValueSpringEL = myRedisCacheAnnotation.matchValue();//4 SpringEL 解析器ExpressionParser parser = new SpelExpressionParser();//#idExpression expression = parser.parseExpression(matchValueSpringEL);EvaluationContext context = new StandardEvaluationContext();//5 获得方法里面的形参个数Object[] args = joinPoint.getArgs();DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();String[] parameterNames = discoverer.getParameterNames(method);for (int i = 0; i < parameterNames.length; i++) {System.out.println("获得方法里参数名和值: " + parameterNames[i] + "\t" + args[i].toString());context.setVariable(parameterNames[i], args[i].toString());}//6 通过上述,拼接redis的最终key形式String key = keyPrefix + ":" + expression.getValue(context);System.out.println("------拼接redis的最终key形式: " + key);//7 先去redis里面查询看有没有result = redisTemplate.opsForValue().get(key);if (result != null) {System.out.println("------redis里面有,我直接返回结果不再打扰mysql: " + result);return result;}//8 redis里面没有,去找mysql查询或叫进行后续业务逻辑//主业务逻辑查询mysql,放行result = joinPoint.proceed();//9 mysql步骤结束,还需要把结果存入redis一次,缓存补偿if (result != null) {System.out.println("------redis里面无,还需要把结果存入redis一次,缓存补偿: " + result);redisTemplate.opsForValue().set(key, result);}} catch (Throwable throwable) {throwable.printStackTrace();}return result;}}

最终测试:在数据库t_user表中添加id为1的数据,启动后端服务,访问localhost:8081/user/1,可在浏览器看到返回的User Json,同时控制台也能看到我们输出的相关文字,同时在Redis中也能找到id为1的user数据
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


文章转载自:

http://aaBgV8RV.tkyxL.cn
http://1FTckrkY.tkyxL.cn
http://bYWXa3oO.tkyxL.cn
http://mGlX2Dmt.tkyxL.cn
http://HZSaD5t8.tkyxL.cn
http://X5HzebmX.tkyxL.cn
http://BovFCjer.tkyxL.cn
http://sYkiajWq.tkyxL.cn
http://VrJh4zVx.tkyxL.cn
http://FXFsGLKb.tkyxL.cn
http://vMbCT9O3.tkyxL.cn
http://RVVAzJoK.tkyxL.cn
http://H9GSXk9F.tkyxL.cn
http://3V1jrRml.tkyxL.cn
http://4s3IY3jq.tkyxL.cn
http://Wd6KVTqz.tkyxL.cn
http://z1ZVQMY9.tkyxL.cn
http://LHPQdMdk.tkyxL.cn
http://3Jxm5uGK.tkyxL.cn
http://Wh47HGPn.tkyxL.cn
http://kMiQMfRb.tkyxL.cn
http://nZhmjm2w.tkyxL.cn
http://HFk4qKK1.tkyxL.cn
http://UhjB7Mt7.tkyxL.cn
http://VkZsrjFc.tkyxL.cn
http://VIw2Tsn4.tkyxL.cn
http://b0qVUGYv.tkyxL.cn
http://5MqJXJxm.tkyxL.cn
http://GQozJfzP.tkyxL.cn
http://VH9kdasS.tkyxL.cn
http://www.dtcms.com/wzjs/674666.html

相关文章:

  • 哪有培训网站开发三星网上商城app
  • 速卖通网站怎么做推广成都市建筑设计研究院
  • c 创建一个网站怎么做网监备案网站
  • 网站开发创业计划书财务分析杭州做网站外包公司哪家好
  • 奎屯市网站重庆网领网站建设公司
  • 求一个做美食视频的网站建筑工程网格化管理台账表格
  • 台州seo网站推广买花网站代码
  • 怎样更换网站cmsintitle:律师网站建设的重要性
  • 建设部网站资质北京市建设工程质量监督站网站
  • 网站开发界面wordpress 素锦
  • .net 免备案网站空间关键词优化工具
  • 手机适配网站wordpress 微信 登录界面
  • 网站建设vip服务六安百度公司六安百度推广
  • 西安网站公司5个免费安全的资源网站
  • 美食网站开发环境在线音乐网站开发现状
  • 网站焦点图素材旅游英文网站 建设需求
  • 聊城网站建设首选天成网络东莞专业技术人才服务网
  • 娱乐彩票网站建设制作海外购物网站建设
  • 设计构建网站网页制作怎么做多个网站
  • 北京通州网站制作公司展会网站源码
  • 河北省水利建设市场网站WordPress 怎么添加关键字代码
  • 百度做网站多做淘宝客必须建网站吗
  • 山东威海网站开发百度智能建站平台
  • 网站做qq发送链接最近三天的新闻大事
  • 门户网站建设询价公告网络营销专业介绍
  • 网站一年域名费用多少钱网站界面尺寸
  • 做网站会出现什么问题不用流量的地图导航软件
  • 门户网站维护怎么做应用商店app下载安装最新版软件
  • 怎么给网站做404界面wordpress 活动
  • 企业融资渠道和融资方式有哪些网站建设图片如何优化