Article catalog
1, Redis common command operations
1. String type
Assignment command: set key value
Value command: get key
Increasing number: incr key
Number decrement: incr key
Increase the specified integer: increment key increment
Reduce the specified integer: decrby key increment
E:\Redis>redis-cli.exe 127.0.0.1:6379> set test:name zhangsan OK 127.0.0.1:6379> get test:name "zhangsan" 127.0.0.1:6379> incr num -- Automatic initialization num,And return the result after adding 1 (integer) 1 127.0.0.1:6379> decr num -- Returns the result after subtracting 1 (integer) 0 127.0.0.1:6379> incrby num 5 -- Return the result after adding 5 (integer) 5 127.0.0.1:6379> decrby num 4 -- Return the result after subtracting 5 (integer) 1 127.0.0.1:6379>
2. Hash type
Assignment command: hset key field value returns 1 to indicate that the new Field has been set to a new value, 0 to indicate that the Field already exists, and overwrites the original value with the new value
Value instruction: hget key field
Delete instruction: hdel key field
127.0.0.1:6379> hset test:teacher username zhangsan -- value yes hash Types include key-value (integer) 1 127.0.0.1:6379> hget test:teacher username "zhangsan" 127.0.0.1:6379> hset test:person id 1 (integer) 1 127.0.0.1:6379> hget test:person id "1" 127.0.0.1:6379> hset test:person id 2 (integer) 0 127.0.0.1:6379> hdel test:person id (integer) 1
3. List type list
list can be made into stack and queue. If it is left in, right out, stack, left in, left out, queue
Add an element to the list header: lpush key value [value ]Number of elements in the list after inserting successfully
Add an element to the end of the list: rpushkey value [value ]Number of elements in the list after inserting successfully
Element stack from the left: the first step of lpop key is to remove the element on the left of the list, and the second step is to return the removed element value
The first step is to remove the elements on the right side of the list, and the second step is to return the removed element values
Get the number of elements in the list: len key
Get the element value of the specified index: lindex key index this command will return the element of the specified location (index) in the linked list. The index is 0-based
Get list: lrange key start stop returns the list of elements in the specified range.
127.0.0.1:6379> lpush list 1 2 3 4 5 (integer) 5 127.0.0.1:6379> lpop list "5" 127.0.0.1:6379> llen list (integer) 4 127.0.0.1:6379> lindex list 2 "2" 127.0.0.1:6379> rpop list "1"
4. Unordered set
Add element: sadd key memer returns the number of elements actually inserted into the collection
Get the number of elements in the collection: scar key
Pop an element from the collection: pop key returns the removed member (arbitrary)
Determine whether the element is in the collection: sismer key member returns 1 to indicate that it already exists, 0 to indicate that it does not exist
127.0.0.1:6379> sadd myset 1 (integer) 1 127.0.0.1:6379> sadd myset 2 3 4 (integer) 3 127.0.0.1:6379> scard myset (integer) 4 127.0.0.1:6379> spop myset "2" 127.0.0.1:6379> sismember myset 3 (integer) 1 127.0.0.1:6379>
5. Ordered sort
Add element: zadd key score member [score] [member] add successfully returns the number of members actually inserted
Get the number of elements in the collection: zcard key
Get the number of elements in the specified score range: zcount key min max this command is used to get the number of members whose score is between min and Max
Get score of element: zscore key member
Increase the score of an element: zincrby key increment member
Get the ranking of elements: zrank key member
127.0.0.1:6379> zadd myzset 1 a 2 b 3 c (integer) 3 127.0.0.1:6379> zcard myzset (integer) 3 127.0.0.1:6379> zcount myzset 1 3 (integer) 3 127.0.0.1:6379> zscore myzset a "1" 127.0.0.1:6379> zscore myzset c "3" 127.0.0.1:6379> zincrby myzset 2 a "3" 127.0.0.1:6379> zscore myzset a "3" 127.0.0.1:6379> zrank myzset a (integer) 1 127.0.0.1:6379> zrank myzset c (integer) 2 127.0.0.1:6379>
2, Distributed shared session
Implementation ideas:
(1) The login page submits the user name and password.
(2) Generate token after login. Token is equivalent to the original sessionid, string, and uuid can be used.
(3) Save the user information to redis. Key is token and value is userId.
(4) Set the expiration time of the key. Simulate the expiration time of the Session. Generally one hour.
(5) Interceptor intercept request verification sessionId
1. LoginReqVO login user to submit user name and password
@Data public class LoginReqVO { @ApiModelProperty(value = "user name") private String username; @ApiModelProperty(value = "password") private String password; }
2. LoginRespVO responds user information and token to browser
@Data public class LoginRespVO { @ApiModelProperty(value = "User authentication certificate") private String token; @ApiModelProperty(value = "user id") private String userId; }
3,UserServiceImpl
@Service public class UserServiceImpl implements UserService { @Autowired private SysUserMapper sysUserMapper; @Autowired private RedisTemplate redisTemplate; @Override public LoginRespVO login(LoginReqVO vo) { //Find the user in the database summary according to the submitted user name SysUser sysUser = sysUserMapper.selectByUsername(vo.getUsername()); //If the user does not exist if(sysUser==null){ throw new BusinessException(4001005,"The user does not exist, please register first"); } //If the user status is disabled if(sysUser.getStatus()==2){ throw new BusinessException(4001006,"This account has been disabled. Please contact the system administrator"); } //If the user password is incorrect (encrypt the plaintext and compare it with the password in the database) if(!PasswordUtils.matches(sysUser.getSalt(),vo.getPassword(),sysUser.getPassword())){ throw new BusinessException(4001007,"User name and password do not match"); } //Login succeeded, generate token String token= UUID.randomUUID().toString(); //Respond token and user information to browser LoginRespVO respVO=new LoginRespVO(); respVO.setUserId(sysUser.getId()); respVO.setToken(token); //Put the user information in the redis cache. The key is the token and the value is the user information. At the same time, set the token expiration time to 60s redisTemplate.opsForValue().set(token,sysUser.getId(),60, TimeUnit.MINUTES); return respVO; } }
4,UserController
@RestController @RequestMapping("/api") @Api(tags = "User module") public class UserController { @Autowired private UserService userService; @PostMapping("/user/login") @ApiOperation(value = "User login interface") public LoginRespVO login(@RequestBody LoginReqVO vo){ return userService.login(vo); } }
5. Configure interception path: login registration request cannot be intercepted and needs to be released
@Configuration public class WebAppConfig implements WebMvcConfigurer { @Bean public TokenInterceptor tokenInterceptor(){ return new TokenInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(tokenInterceptor()) .addPathPatterns("/api/**").excludePathPatterns("/api/user/login","/api/user/register","/api/user/code/*"); } }
6. TokenInterceptor configuration Interceptor: for other requests except login registration, interceptors are required to determine whether the user is in login status.
public class TokenInterceptor implements HandlerInterceptor { @Autowired private RedisService redisService; private RedisTemplate redisTemplate; //Intercept the login request and verify whether the user is in login state before executing the Controller layer method @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //Get token from request header String token=request.getHeader("token"); //Judge whether the token is empty if(StringUtils.isEmpty(token)){ throw new BusinessException(4001002,"User certificate cannot be empty, please login again"); }else { //If the token is not empty, you need to determine whether the token is valid if(!redisTemplate.hasKey(token)){ throw new BusinessException(4001002,"User credentials are invalid, please login again"); } } return true; } }
3, Remote login reminder offline
Recently, I received a request from the product that an account can only be logged in at one place at the same time. If it is logged in at other places, it will prompt that it has been logged in elsewhere. At the same time, the same browser can only log in to one user at the same time.
Implementation ideas:
(1) The login page submits the user name and password.
(2) Generate token after login.
(3) Save the user information to redis. Key is token and value is userId.
(4) Set the expiration time of the key.
(5) Store the token in redis, key is userid, and value is the token
(6) Interceptor intercepts request verification token.
(7) After obtaining the userId, compare whether the token carried by the header is consistent with the token marked by redis. In case of inconsistency, the user will be prompted that he has logged in from another place.
1, LoginReqVO
@Data public class LoginReqVO { @ApiModelProperty(value = "user name") private String username; @ApiModelProperty(value = "password") private String password; }
2,LoginRespVO
@Data public class LoginRespVO { @ApiModelProperty(value = "User authentication certificate") private String token; @ApiModelProperty(value = "user id") private String userId; }
3. UserServiceImpl: after the user logs in successfully, generate a token and respond to the browser
@Service public class UserServiceImpl implements UserService { @Autowired private SysUserMapper sysUserMapper; @Autowired private RedisTemplate redisTemplate; @Override public LoginRespVO login(LoginReqVO vo) { //Find the user in the database summary according to the submitted user name SysUser sysUser = sysUserMapper.selectByUsername(vo.getUsername()); //If the user does not exist if(sysUser==null){ throw new BusinessException(4001005,"The user does not exist, please register first"); } //If the user status is disabled if(sysUser.getStatus()==2){ throw new BusinessException(4001006,"This account has been disabled. Please contact the system administrator"); } //If the user password is incorrect if(!PasswordUtils.matches(sysUser.getSalt(),vo.getPassword(),sysUser.getPassword())){ throw new BusinessException(4001007,"User name and password do not match"); } //Login succeeded, generate token String token= UUID.randomUUID().toString(); //Respond token and user information to browser LoginRespVO respVO=new LoginRespVO(); respVO.setUserId(sysUser.getId()); respVO.setToken(token); //Put the user information in the redis cache. The key is the token, and the value is the user information. The expiration time is 60 minutes redisTemplate.opsForValue().set(token,sysUser.getId(),60, TimeUnit.MINUTES); //Mark token, store token into redis cache, key is userId, value is token, expiration time is 60 minutes redisTemplate.opsForValue().set(sysUser.getId(),token,60,TimeUnit.MINUTES); return respVO; } }
4,UserController:
@RestController @RequestMapping("/api") @Api(tags = "User module") public class UserController { @Autowired private UserService userService; @PostMapping("/user/login") @ApiOperation(value = "User login interface") public LoginRespVO login(@RequestBody LoginReqVO vo){ return userService.login(vo); } }
5. Configure interceptor interception path: release login
@Configuration public class WebAppConfig implements WebMvcConfigurer { @Bean public TokenInterceptor tokenInterceptor(){ return new TokenInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(tokenInterceptor()) .addPathPatterns("/api/**").excludePathPatterns("/api/user/login","/api/user/register","/api/user/code/*"); } }
6. Configure Interceptor: judge whether the token of the front end passing through the class is consistent with the token of the redis cache
public class TokenInterceptor implements HandlerInterceptor { @Autowired private RedisService redisService; private RedisTemplate redisTemplate; //Intercept the login request and verify whether the user is in login state before executing the Controller layer method @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //Get token from request header String token=request.getHeader("token"); //Judge whether the token is empty if(StringUtils.isEmpty(token)){ throw new BusinessException(4001002,"User certificate cannot be empty, please login again"); }else { //Determine whether the token in the cache expires if(!redisTemplate.hasKey(token)){ throw new BusinessException(4001002,"User credentials are invalid, please login again"); } //Get the value userId according to the key token String userId= (String) redisTemplate.opsForValue().get(token); //If there is no userId in redis or the token passed from the browser does not match the token in redis cache if(redisTemplate.hasKey(userId)&&!token.equals(redisTemplate.opsForValue().get(userId)){ throw new BusinessException(4001002,"Your account has been logged in from another place, please log in again"); } } return true; } }
4, Register SMS verification code
SMS verification code is one of the essential basic functional modules of all projects. If one day suddenly you are assigned a requirement by your leader. Check the mobile number when the user registers.
The requirements are as follows:
(1) Check mobile number when registering
(2) Each mobile phone number can send up to five registered SMS verification codes every day
(3) The verification code is valid for 5 minutes.
Ideas:
(1) Verify that the phone number meets the requirements before sending.
(2) Generate SMS verification code.
(3) Send the verification code to the phone.
(4) Store the verification code in redis
(5) Mark mobile number
(6) Check whether the mobile number and verification code are correct when registering
1,RegisterReqVO
@Data public class RegisterReqVO { @ApiModelProperty(value = "account number") private String username; @ApiModelProperty(value = "cell-phone number") private String phone; @ApiModelProperty(value = "password") private String password; @ApiModelProperty(value = "Verification Code") private String code; }
2. Contact: key to build redis
*/ public class Contant { /** * Judge whether it reaches the online key */ public final static String REGISTER_CODE_COUNT_KEY="register-code-count-key_"; /** * Validation code validity key */ public final static String REGISTER_CODE_COUNT_VALIDITY_KEY="register-code-count-validity-key_"; }
3,UserServiceImpl
@Service public class UserServiceImpl implements UserService { @Autowired private SysUserMapper sysUserMapper; @Autowired private RedisTemplate redisTemplate; /** * Get verification code */ @Override public String getCode(String phone) { //Verify the phone number is legal Pattern pattern = Pattern.compile("^1(3|4|5|7|8)\\d{9}$"); Matcher matcher = pattern.matcher(phone); if(!matcher.matches()) { throw new BusinessException(4001004,"Mobile number format error"); } //Add 1 to the number of times for each access to the verification code to determine whether the access to the verification code exceeds the limit long count = redisTemplate.opsForValue().increment(Contant.REGISTER_CODE_COUNT_KEY+phone,1); if(count>5){ throw new BusinessException(4001004,"The delivery limit of the day has been reached"); } //Generate 6-bit random number as verification code String code=generateCode(); //Store the generated verification code in redis with an expiration time of 5 minutes redisService.set(Contant.REGISTER_CODE_COUNT_VALIDITY_KEY+phone,code,5,TimeUnit.MINUTES; //Send SMS here with output simulation System.out.println(code); return code; } /** * Generate six digit verification code */ private String generateCode(){ Random random = new Random(); int x = random.nextInt(899999); String code = String.valueOf(x + 100000); return code; } /** * User registration */ @Override public String register(RegisterReqVO vo) { //Judge whether the verification code is valid if(!redisTemplate.hasKey(Contant.REGISTER_CODE_COUNT_VALIDITY_KEY+vo.getPhone()){ throw new BusinessException(4001008,"The verification code is invalid. Please get it again"); } //Check whether the verification code is correct (whether the verification code passed from the front end is consistent with that in the redis cache) if(!vo.getCode().equals(redisTemplate.opsForValue().get(Contant.REGISTER_CODE_COUNT_VALIDITY_KEY+vo.getPhone()))){ throw new BusinessException(4001009,"Please enter the correct verification code"); } SysUser sysUser = sysUserMapper.selectByUsername(vo.getUsername()); if(sysUser!=null){ throw new BusinessException(4001010,"The user name is already registered"); } //Constructing user information to store in database SysUser user=new SysUser(); //Property copy BeanUtils.copyProperties(vo,user); user.setId(UUID.randomUUID().toString()); user.setCreateTime(new Date()); String salt=PasswordUtils.getSalt(); String ecdPwd=PasswordUtils.encode(vo.getPassword(),salt); user.setSalt(salt); user.setPassword(ecdPwd); int i = sysUserMapper.insertSelective(user); if(i!=1){ throw new BusinessException(4001011,"operation failed"); } //Clear redis cache when registration is successful redisTemplate.delete(Contant.REGISTER_CODE_COUNT_VALIDITY_KEY+vo.getPhone()); redisTemplate.delete(Contant.REGISTER_CODE_COUNT_KEY+vo.getPhone()); return "login was successful"; } }
4,UserController
@RestController @RequestMapping("/api") @Api(tags = "User module") public class UserController { @Autowired private UserService userService; @PostMapping("/user/register") @ApiOperation(value = "User registration interface") public String register(@RequestBody RegisterReqVO vo){ return userService.register(vo); } @GetMapping("/user/code/{phone}") public String getCode(@PathVariable("phone") String phone){ return userService.getCode(phone); } }