1. Use Redis to store verification code
- The verification code needs frequent access and refresh, which requires high performance.
- The verification code does not need to be saved permanently, and it usually becomes invalid after a short time.
- During distributed deployment, there is a problem of Session sharing.
2. Use Redis to store login credentials
- When processing each request, the user's login credentials must be queried, and the frequency of access is very high.
3. Use Redis to cache user information
- When processing each request, the user information should be queried according to the credentials, and the frequency of access is very high.
cache
Use Redis to store verification code
LoginController writes and generates the verification code and stores the verification code in the session, but there will be performance problems:
- The verification code needs frequent access and refresh, which requires high performance.
- The verification code does not need to be saved permanently, and it usually becomes invalid after a short time.
- During distributed deployment, there is a problem of Session sharing.
- Data stored on the server is safer, but it will also increase the memory pressure on the server.
Therefore, store the verification code in Redis and obtain the verification code through the Key. However, when using the verification code, the user did not log in and could not obtain the user information, so the randomly generated string for a short time was stored in the cookie as a credential.
RedisKey generation
public class RedisKeyUtil { private static final String PREFIX_KAPTCHA = "kaptcha"; // Login verification code public static String getKaptchaKey(String owner) { return PREFIX_KAPTCHA + SPLIT + owner; }
Rewrite generated verification code
@Controller public class LoginController implements CommunityConstant { ... @Value("${server.servlet.context-path}") private String contextPath; @RequestMapping(path = "/kaptcha", method = RequestMethod.GET) public void getKaptcha(HttpServletResponse response/*, HttpSession session*/) { // Generate verification code String text = kaptchaProducer.createText(); BufferedImage image = kaptchaProducer.createImage(text); // Save the verification code into session // session.setAttribute("kaptcha", text); // Ownership of verification code String kaptchaOwner = CommunityUtil.generateUUID(); Cookie cookie = new Cookie("kaptchaOwner", kaptchaOwner); cookie.setMaxAge(60); // Set cookie lifetime cookie.setPath(contextPath); // Set the effective range of cookie s response.addCookie(cookie); // Store the verification code in Redis String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner); redisTemplate.opsForValue().set(redisKey, text, 60, TimeUnit.SECONDS); // Output the image to the browser response.setContentType("image/png"); try { OutputStream os = response.getOutputStream(); ImageIO.write(image, "png", os); } catch (IOException e) { logger.error("Response verification code failed:" + e.getMessage()); } }
1. Generate verification code, but no longer store it in Session
2. Randomly generated string kaptchaOwner stored in cookie
3. Generate the corresponding RedisKey according to the kaptchaOwner and store the verification code in Redis.
redisTemplate.opsForValue().set(redisKey, text, 60, TimeUnit.SECONDS); String type is used here: 60 indicates the survival time, timeunit Seconds is the unit of time
Use Redis to store login credentials
The previous login information is to construct the LoginTicket entity class and store it in the database through logintickemapper.
1. LoginTicketMapper set to expire
@Mapper @Deprecated public interface LoginTicketMapper { }
2. Refactoring UserService
1) When logging in, put the generated login credentials into Redis
// Generate login credentials LoginTicket loginTicket = new LoginTicket(); loginTicket.setUserId(user.getId()); loginTicket.setTicket(CommunityUtil.generateUUID()); loginTicket.setStatus(0); loginTicket.setExpired(new Date(System.currentTimeMillis() + expiredSeconds * 1000)); // loginTicketMapper.insertLoginTicket(loginTicket); String redisKey = RedisKeyUtil.getTicketKey(loginTicket.getTicket()); redisTemplate.opsForValue().set(redisKey, loginTicket); map.put("ticket", loginTicket.getTicket());
2) Exit function
Take the value from Redis, forcibly convert it to loginTicket class, change the status of login voucher to 1, and then re pass it into Redis.
public void logout(String ticket) { // loginTicketMapper.updateStatus(ticket, 1); String redisKey = RedisKeyUtil.getTicketKey(ticket); LoginTicket loginTicket = (LoginTicket) redisTemplate.opsForValue().get(redisKey); loginTicket.setStatus(1); redisTemplate.opsForValue().set(redisKey, loginTicket); }
3) Query voucher
public LoginTicket findLoginTicket(String ticket) { // return loginTicketMapper.selectByTicket(ticket); String redisKey = RedisKeyUtil.getTicketKey(ticket); return (LoginTicket) redisTemplate.opsForValue().get(redisKey); }
Use Redis to cache user information
1. First encapsulate the cache operation
Take the value from the cache first, initialize the cached data when it cannot be obtained, and clear the cached data when the data is changed
// 1. Take priority from the cache private User getCache(int userId) { String redisKey = RedisKeyUtil.getUserKey(userId); return (User) redisTemplate.opsForValue().get(redisKey); } // 2. Initialize the cache data when it cannot be fetched private User initCache(int userId) { User user = userMapper.selectById(userId); String redisKey = RedisKeyUtil.getUserKey(userId); redisTemplate.opsForValue().set(redisKey, user, 3600, TimeUnit.SECONDS); return user; } // 3. Clear cached data when data changes private void clearCache(int userId) { String redisKey = RedisKeyUtil.getUserKey(userId); redisTemplate.delete(redisKey); }
2. Refactoring findUserById
public User findUserById(int id) { // return userMapper.selectById(id); User user = getCache(id); if (user == null) { user = initCache(id); } return user; }