当前位置:网站首页>Seckill system 2 redis solves the problem of distributed session
Seckill system 2 redis solves the problem of distributed session
2022-07-03 15:21:00 【You are my forever bug】
Preface
If you operate on one Tomcat On , There is no problem , But when we deploy multiple systems , coordination Nginx There will be a problem of user login .
reason
because Nginx Use a load balancing policy , Distribute the request to the backend ,
in other words , stay Tomcat 1 After logging in , User information exists Tomcat1 Of Session in , The next request is coming Tomcat2 On , At this time Tomcat2 On Session There is no user information in , I'm going to log in .

solve
redis Installation tutorial self-study
Redis Implement distributed Session
Method 1、 Use SpringSession Realization ( This method can't jump to the page )
1、 Add dependency :
<!-- spring data redis rely on -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- commons-pool2 Object pool dependency -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- spring-session rely on -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
2、 To configure Redis
spring:
# thymeleaf Turn off caching
thymeleaf:
cache: false
# MySql Data source configuration
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/secKill?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
# Fastest connection pool
hikari:
# The name of the connection pool
pool-name: DateHikariCP
# Minimum number of idle connections
minimum-idle: 5
# Maximum free connection lifetime Default 600000(10 minute )
idle-timeout: 1800000
# maximum connection Default 10
maximum-pool-size: 10
# Connections returned from the connection pool are automatically submitted
auto-commit: true
# Maximum connection lifetime 0 For permanent survival , Default 1800000( minute )
max-lifetime: 1800000
# Connection timeout Default 30000(30 second )
connection-timeout: 30000
# A query statement to test whether the connection is possible
connection-test-query: SELECT 1
# Redis To configure
redis:
host: 127.0.0.1
port: 6379
# Database used 0
database: 0
# Connection timeout
timeout: 10000ms
lettuce:
# Configuration of connection pool
pool:
# maximum connection 8
max-active: 8
# Maximum connection blocking time
max-wait: 10000ms
# Maximum free connection
max-idle: 200
# Minimum free connection
min-idle: 5
# mybatis-plus To configure
mybatis-plus:
# To configure Mapper.xml The path of the mapping file
mapper-locations: classpath*:/mapper/*.xml # mybatis SQL Print ( Interface method in package , No mapper.xml The bag where it is ) logging: level: com.example.seckill.mapper: DEBUG This is the time Just OK 了 , After logging in ,Session It will be saved Redis - 0( library ) -spring Session in 
here Comment out the
// /**
// * After verifying the user successfully, generate cookie, take cookie Save with the user session in
// */
// // Use UUID Generate cookie
// String cookie = UUIDUtil.uuid();
// // take cookie Save with the user session in
// request.getSession().setAttribute(cookie,user);
// // Set up cookie
// CookieUtil.setCookie(request,response,"userCookie",cookie);
Log in again Discovery will also be saved Redis in .
Method 2、 Save user information in redis in
1、 Add dependency
<!-- spring data redis rely on -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- commons-pool2 Object pool dependency -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2、redis Configuration of And methods 1 equally
3、Redsi Configuration class
package com.example.seckill.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/** * Redis To configure */
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
//key serialize
redisTemplate.setKeySerializer(new StringRedisSerializer());
//value serialize
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//hash type value serialize
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
// Injection connection factory
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}
4、json Tool class
This is very important , If not from redis From user The information does not match , I can't jump Product page
package com.example.seckill.util;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.List;
/** * Json Tool class * * @author zhoubin * @since 1.0.0 */
public class JsonUtil {
private static ObjectMapper objectMapper = new ObjectMapper();
/** * Converts an object to json character string * * @param obj * @return */
public static String object2JsonStr(Object obj) {
try {
return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
// Print exception information
e.printStackTrace();
}
return null;
}
/** * Convert a string to an object * * @param <T> Generic */
public static <T> T jsonStr2Object(String jsonStr, Class<T> clazz) {
try {
return objectMapper.readValue(jsonStr.getBytes("UTF-8"), clazz);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/** * take json Data to pojo object list * <p>Title: jsonToList</p> * <p>Description: </p> * * @param jsonStr * @param beanType * @return */
public static <T> List<T> jsonToList(String jsonStr, Class<T> beanType) {
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, beanType);
try {
List<T> list = objectMapper.readValue(jsonStr, javaType);
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
5、 modify UserServiceImpl Code
After verifying the user , take user Put in redis
And add through cookie obtain user Methods
package com.example.seckill.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.seckill.common.RespBean;
import com.example.seckill.common.RespBeanEnum;
import com.example.seckill.controller.parm.LoginRequestParam;
import com.example.seckill.exception.GlobalException;
import com.example.seckill.mapper.UserMapper;
import com.example.seckill.pojo.User;
import com.example.seckill.service.IUserService;
import com.example.seckill.util.CookieUtil;
import com.example.seckill.util.JsonUtil;
import com.example.seckill.util.MD5Util;
import com.example.seckill.util.UUIDUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** * <p> * User table Service implementation class * </p> * * @author jobob * @since 2022-06-13 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
@Autowired(required = false)
UserMapper userMapper;
@Autowired
private RedisTemplate redisTemplate;
@Override
public RespBean doLogin(LoginRequestParam param, HttpServletRequest request, HttpServletResponse response) {
String password = param.getPassword();
String mobile = param.getMobile();
User user = userMapper.selectById(mobile);
if (null == user){
throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
}
if (!MD5Util.formPassToDBPass(password,user.getSalt()).equals(user.getPassword())){
throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
}
/** * After verifying the user successfully, generate cookie, take cookie Save with the user session in */
// Use UUID Generate cookie
String cookie = UUIDUtil.uuid();
// take cookie Save with the user session in
// request.getSession().setAttribute(cookie,user);
redisTemplate.opsForValue().set("user:" + cookie, JsonUtil.object2JsonStr(user));
// Set up cookie
CookieUtil.setCookie(request,response,"userCookie",cookie);
return RespBean.success(cookie);
}
@Override
public User getUserByCookie(String cookie, HttpServletRequest request, HttpServletResponse response) {
if (StringUtils.isEmpty(cookie)){
return null;
}
String userJson = (String) redisTemplate.opsForValue().get("user:" + cookie);
User user = JsonUtil.jsonStr2Object(userJson, User.class);
if (null != user){
// Set up cookie
CookieUtil.setCookie(request,response,"userCookie",cookie);
}
return user;
}
}
6、 goods Controller
package com.example.seckill.controller;
import com.example.seckill.common.RespBean;
import com.example.seckill.controller.parm.LoginRequestParam;
import com.example.seckill.pojo.User;
import com.example.seckill.service.IGoodsService;
import com.example.seckill.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@RequestMapping("/goods")
@Controller
@Slf4j
public class GoodsController {
@Autowired
IGoodsService goodsService;
@Autowired
IUserService userService;
/** * Jump to product page * @param * @param model * @param cookie * @return */
@RequestMapping("/toList")
public String toList(HttpServletRequest request, HttpServletResponse response, Model model, @CookieValue("userCookie") String cookie){
if (StringUtils.isEmpty(cookie)){
// If cookie by empty Jump to The login page
return "login";
}
// from session Get users
// User user = (User) session.getAttribute(cookie);
User user = userService.getUserByCookie(cookie, request, response);
if (null == user){
// If the user information is empty Jump to login
return "login";
}
// Put user information To the front page
model.addAttribute("user",user);
return "goodsList";
}
}
Avoid completing each interface above according to Cookie obtain User Information , Avoid code redundancy , Special optimization :
1、UserArgumentResolvers class
package com.example.seckill.config;
import com.example.seckill.pojo.User;
import com.example.seckill.service.IUserService;
import com.example.seckill.util.CookieUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** * Custom user parameters */
@Component
public class UserArgumentResolvers implements HandlerMethodArgumentResolver {
@Autowired
IUserService userService;
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> parameterType = parameter.getParameterType();
return parameterType == User.class;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
String cookie = "486ceb27176a485f85e3c3d1f4f35e77";
// String cookie = CookieUtil.getCookieValue(request, "userCookie");
if (StringUtils.isEmpty(cookie)){
// If cookie by empty Jump to The login page
return null;
}
return userService.getUserByCookie(cookie, request, response);
}
}
2、
package com.example.seckill.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/** * MVC Configuration class * */
@Configuration
//@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Autowired
UserArgumentResolvers userArgumentResolvers;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers){
resolvers.add(userArgumentResolvers);
}
}
3、goodController
package com.example.seckill.controller;
import com.example.seckill.common.RespBean;
import com.example.seckill.controller.parm.LoginRequestParam;
import com.example.seckill.pojo.User;
import com.example.seckill.service.IGoodsService;
import com.example.seckill.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@RequestMapping("/goods")
@Controller
@Slf4j
public class GoodsController {
@Autowired
IGoodsService goodsService;
@Autowired
IUserService userService;
/** * Jump to product page * @param * @param model * @param * @return */
@RequestMapping("/toList")
public String toList(Model model,User user){
// Put user information To the front page
model.addAttribute("user",user);
return "goodsList";
}
}
problem : Here I have a problem , Each generation Cookie Put in Redis It's normal , But call other interfaces after successful login adopt CookieUtil Acquired Cookie Not generated by this login Cookie It's annoying ~ I don't know much about this So I'm making sure that redis There is this cookie , take cookie It's dead
边栏推荐
- GCC cannot find the library file after specifying the link library path
- 高并发下之redis锁优化实战
- Visual upper system design and development (Halcon WinForm) -6 Nodes and grids
- Puppet自动化运维排错案例
- [cloud native training camp] module 7 kubernetes control plane component: scheduler and controller
- High quality workplace human beings must use software to recommend, and you certainly don't know the last one
- 【云原生训练营】模块八 Kubernetes 生命周期管理和服务发现
- Global and Chinese markets for flexible chips 2022-2028: Research Report on technology, participants, trends, market size and share
- Jvm-02-class loading subsystem
- 什么是Label encoding?one-hot encoding ,label encoding两种编码该如何区分和使用?
猜你喜欢

Visual upper system design and development (Halcon WinForm) -5 camera

Concurrency-01-create thread, sleep, yield, wait, join, interrupt, thread state, synchronized, park, reentrantlock

Visual upper system design and development (Halcon WinForm) -4 Communication management

Halcon与Winform学习第二节

Construction of operation and maintenance system

Kubernetes will show you from beginning to end

The markdown file obtains the pictures of the network and stores them locally and modifies the URL

Popular understanding of decision tree ID3

Jvm-05-object, direct memory, string constant pool

Reentrantlock usage and source code analysis
随机推荐
视觉上位系统设计开发(halcon-winform)-2.全局变量设计
Didi off the shelf! Data security is national security
Global and Chinese markets for flexible chips 2022-2028: Research Report on technology, participants, trends, market size and share
Using Tengine to solve the session problem of load balancing
Global and Chinese markets for infrared solutions (for industrial, civil, national defense and security applications) 2022-2028: Research Report on technology, participants, trends, market size and sh
Global and Chinese market of air cargo logistics 2022-2028: Research Report on technology, participants, trends, market size and share
阿特拉斯atlas扭矩枪 USB通讯教程基于MTCOM
官网MapReduce实例代码详细批注
Jvm-03-runtime data area PC, stack, local method stack
视觉上位系统设计开发(halcon-winform)-3.图像控件
开启 Chrome 和 Edge 浏览器多线程下载
Functional modules and application scenarios covered by the productization of user portraits
[pytorch learning notes] datasets and dataloaders
Kubernetes - YAML文件解读
Halcon与Winform学习第二节
Characteristics of MySQL InnoDB storage engine -- Analysis of row lock
Digital image processing -- popular understanding of corrosion and expansion
Jvm-09 byte code introduction
视觉上位系统设计开发(halcon-winform)-6.节点与宫格
Visual upper system design and development (Halcon WinForm) -6 Nodes and grids