redis java entitybean key 设计
时间: 2024-04-07 22:31:49 浏览: 67
Redis中使用Java实体类时,通常需要为实体类的Key设计一个合适的命名规则,以便于管理和查询。以下是一些常用的Key设计规则:
1. 命名空间+实体类名:将实体类名作为Key的一部分,例如"user:id:1",其中"user"是命名空间,"id:1"是实体类名。
2. 实体类名+ID:将实体类名和ID组合作为Key的一部分,例如"User:1",其中"User"是实体类名,"1"是ID。
3. 实体类名+字段值:将实体类名和某个字段的值组合作为Key的一部分,例如"User:username:Tom",其中"User"是实体类名,"username:Tom"是某个字段的值。
4. 命名空间+实体类名+ID:将命名空间、实体类名和ID组合作为Key的一部分,例如"user:id:1",其中"user"是命名空间,"id"是实体类名,"1"是ID。
在实际应用中,选择合适的Key设计规则需要根据具体业务场景和数据模型来确定。一般来说,应该考虑Key的可读性、唯一性和易于管理。此外,为了避免Key重复,建议使用命名空间来区分不同的实体类和业务模块。
相关问题
java中springcache使用redis设置过期时间
在Spring Cache中,你可以利用Redis作为缓存存储,并通过Redis的TTL(Time To Live,生存时间)特性来设置缓存数据的过期时间。首先,你需要在Spring Boot中配置Redis支持,然后在Spring Cache中创建一个`CacheManager`实例,指定Redis缓存。
以下是一个简单的步骤:
1. 添加依赖:在你的`pom.xml`文件中添加Spring Data Redis和Spring Boot Actuator的依赖,例如:
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
```
2. 配置Redis:在`application.properties`或`application.yml`中设置Redis的相关连接信息:
```properties
spring.redis.host=your-redis-host
spring.redis.port=6379
spring.redis.database=0
```
3. 创建`CacheManager`:在Spring Boot的主类上添加`@EnableCaching`注解,然后注入`RedisCacheManager`:
```java
@EnableCaching
public class Application {
private static final String DEFAULT_CACHE_NAME = "myCache";
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
SimpleCacheConfig config = new SimpleCacheConfig();
config.setExpireAfterWriteSeconds(30); // 设置默认的过期时间为30秒
return new RedisCacheManager(factory, DEFAULT_CACHE_NAME, config);
}
}
```
4. 使用Cache:在需要缓存的service或repository中,直接使用`@Cacheable`或`@CacheEvict`注解操作缓存,如:
```java
@Service
@Cacheable(value = DEFAULT_CACHE_NAME, key = "#id")
public MyEntity loadFromDatabase(Long id) {
// 从数据库加载实体
}
@CacheEvict(value = DEFAULT_CACHE_NAME, key = "#id")
public void updateMyEntity(MyEntity entity) {
// 更新数据库并移除对应缓存
}
```
Java微服务项目:家具商城同时拥有PC端、小程序、APP,实现单点登录功能,使用Spring Security+JWT+Redis完成单点登录,代码实现流程
好的,针对你的问题,我会给出一份 Java 微服务项目:家具商城的单点登录功能实现代码流程,使用 Spring Security+JWT+Redis 完成单点登录。代码实现流程如下:
1. 添加依赖
在 pom.xml 文件中添加以下依赖:
```
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
```
2. 配置 Spring Security
在 Spring Security 配置类中,添加以下配置:
```
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
@Bean
public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
return new JwtAuthenticationTokenFilter();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
```
3. 实现 JWT 工具类
实现 JwtTokenUtil 工具类,用于生成和解析 JWT Token。
```
@Component
public class JwtTokenUtil {
private static final String SECRET = "secret";
private static final String ISSUER = "issuer";
private static final String AUDIENCE = "audience";
private static final String CLAIM_KEY_USERNAME = "sub";
private static final String CLAIM_KEY_CREATED = "created";
private static final long EXPIRATION_TIME = 86400000; // 24 hours
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername());
claims.put(CLAIM_KEY_CREATED, new Date());
return Jwts.builder()
.setClaims(claims)
.setIssuer(ISSUER)
.setAudience(AUDIENCE)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
public String getUsernameFromToken(String token) {
String username;
try {
final Claims claims = getClaimsFromToken(token);
username = claims.getSubject();
} catch (Exception e) {
username = null;
}
return username;
}
public Date getExpirationDateFromToken(String token) {
Date expiration;
try {
final Claims claims = getClaimsFromToken(token);
expiration = claims.getExpiration();
} catch (Exception e) {
expiration = null;
}
return expiration;
}
private Claims getClaimsFromToken(String token) {
Claims claims;
try {
claims = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
claims = null;
}
return claims;
}
public boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
}
private boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
}
```
4. 实现认证过滤器
实现 JwtAuthenticationTokenFilter 过滤器,用于在请求头中解析 JWT Token,并进行认证。
```
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String authToken = authHeader.substring("Bearer ".length());
String username = jwtTokenUtil.getUsernameFromToken(authToken);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
}
chain.doFilter(request, response);
}
}
```
5. 实现单点登录功能
在登录接口中,使用 JWT 工具类生成 JWT Token,并将 Token 存储到 Redis 中,设置 Token 过期时间,并返回 Token 给客户端。
```
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private UserService userService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
User user = userService.findByUsername(loginRequest.getUsername());
if (user == null) {
return ResponseEntity.badRequest().body(new ApiResponse(false, "Invalid username"));
}
if (!user.getPassword().equals(loginRequest.getPassword())) {
return ResponseEntity.badRequest().body(new ApiResponse(false, "Invalid password"));
}
UserDetails userDetails = new User(user.getUsername(), user.getPassword(), new ArrayList<>());
String token = jwtTokenUtil.generateToken(userDetails);
redisTemplate.opsForValue().set(token, userDetails.getUsername(), jwtTokenUtil.EXPIRATION_TIME, TimeUnit.MILLISECONDS);
return ResponseEntity.ok(new JwtAuthenticationResponse(token));
}
}
```
6. 实现单点登录拦截器
在请求过程中,使用 JwtAuthenticationInterceptor 拦截器,从请求头中解析 JWT Token,并从 Redis 中获取 Token 对应的用户名,将用户名设置到请求属性中,供后续业务使用。
```
@Component
public class JwtAuthenticationInterceptor implements HandlerInterceptor {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String authToken = authHeader.substring("Bearer ".length());
String username = (String) redisTemplate.opsForValue().get(authToken);
if (username != null && !jwtTokenUtil.isTokenExpired(authToken)) {
request.setAttribute("username", username);
return true;
}
}
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
}
```
7. 配置 Redis
在 application.properties 中,添加以下配置:
```
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.database=0
```
至此,Java 微服务项目:家具商城的单点登录功能使用 Spring Security+JWT+Redis 完成。
阅读全文