springboot2.1.3+redis+session+nginx负载均衡
1、项目工程依赖pom.xml
<?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 http://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> 2.1.3.RELEASE</ version>
< relativePath/>
</ parent>
< groupId> com.redis</ groupId>
< artifactId> session</ artifactId>
< version> 0.0.1-SNAPSHOT</ version>
< packaging> war</ packaging>
< name> session</ name>
< description> Demo project for Spring Boot</ description>
< properties>
< java.version> 1.8</ java.version>
</ properties>
< dependencies>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-data-redis</ artifactId>
</ dependency>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-web</ artifactId>
</ dependency>
< dependency>
< groupId> org.springframework.session</ groupId>
< artifactId> spring-session-data-redis</ artifactId>
</ dependency>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-tomcat</ artifactId>
< scope> provided</ scope>
</ dependency>
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-test</ artifactId>
< scope> test</ scope>
</ dependency>
</ dependencies>
< build>
< plugins>
< plugin>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-maven-plugin</ artifactId>
</ plugin>
</ plugins>
</ build>
</ project>
2、application.properties配置
# REDIS (RedisProperties)
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=192.168.230.135
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=10
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=5
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=2
# 连接超时时间不能设置为0,不然不能启动(毫秒)
spring.redis.timeout=1000
3、配置Redis key和value的序列化方式
package com. redis. session. config;
import com. fasterxml. jackson. annotation. JsonAutoDetect;
import com. fasterxml. jackson. annotation. PropertyAccessor;
import com. fasterxml. jackson. databind. ObjectMapper;
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. core. StringRedisTemplate;
import org. springframework. data. redis. serializer. Jackson2JsonRedisSerializer;
import org. springframework. data. redis. serializer. StringRedisSerializer;
@Configuration
public class RedisCacheConfig {
@Bean
public RedisTemplate< Object, Object> redisTemplate ( RedisConnectionFactory connectionFactory) {
RedisTemplate< Object, Object> template = new RedisTemplate < > ( ) ;
template. setConnectionFactory ( connectionFactory) ;
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer ( Object. class ) ;
ObjectMapper mapper = new ObjectMapper ( ) ;
mapper. setVisibility ( PropertyAccessor. ALL, JsonAutoDetect. Visibility. ANY) ;
mapper. enableDefaultTyping ( ObjectMapper. DefaultTyping. NON_FINAL) ;
serializer. setObjectMapper ( mapper) ;
template. setValueSerializer ( serializer) ;
template. setKeySerializer ( new StringRedisSerializer ( ) ) ;
template. afterPropertiesSet ( ) ;
return template;
}
@Bean
public StringRedisTemplate stringRedisTemplate ( RedisConnectionFactory factory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate ( ) ;
stringRedisTemplate. setConnectionFactory ( factory) ;
return stringRedisTemplate;
}
}
4、拦截器
package com. redis. session. interceptor;
import org. springframework. beans. factory. annotation. Autowired;
import org. springframework. data. redis. core. StringRedisTemplate;
import org. springframework. web. servlet. HandlerInterceptor;
import javax. servlet. http. HttpServletRequest;
import javax. servlet. http. HttpServletResponse;
import javax. servlet. http. HttpSession;
public class RedisSessionInterceptor implements HandlerInterceptor {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public boolean preHandle ( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession httpSession = request. getSession ( ) ;
String userId = ( String) httpSession. getAttribute ( "user_id" ) ;
if ( userId != null) {
String sessionId = stringRedisTemplate. opsForValue ( ) . get ( userId) ;
if ( httpSession. getId ( ) . equals ( sessionId) ) {
return true ;
} else {
return false ;
}
} else {
response. setCharacterEncoding ( "utf-8" ) ;
response. setContentType ( "application/json;charset=utf-8" ) ;
response. getWriter ( ) . print ( "用户未登录!" ) ;
return false ;
}
}
}
5、拦截器配置和乱码处理
package com. redis. session. config;
import com. fasterxml. jackson. databind. ObjectMapper;
import com. redis. session. interceptor. RedisSessionInterceptor;
import org. springframework. context. annotation. Bean;
import org. springframework. context. annotation. Configuration;
import org. springframework. http. converter. HttpMessageConverter;
import org. springframework. http. converter. StringHttpMessageConverter;
import org. springframework. http. converter. json. MappingJackson2HttpMessageConverter;
import org. springframework. web. servlet. config. annotation. InterceptorRegistry;
import org. springframework. web. servlet. config. annotation. WebMvcConfigurationSupport;
import java. nio. charset. Charset;
import java. util. List;
@Configuration
public class WebSecurityConfig extends WebMvcConfigurationSupport {
@Bean
public RedisSessionInterceptor getSessionInterceptor ( ) {
RedisSessionInterceptor interceptor = new RedisSessionInterceptor ( ) ;
return interceptor;
}
@Override
protected void addInterceptors ( InterceptorRegistry registry) {
registry. addInterceptor ( getSessionInterceptor ( ) ) . addPathPatterns ( "/user/**" ) . excludePathPatterns ( "/user/login" ) ;
super . addInterceptors ( registry) ;
}
@Bean
public HttpMessageConverter< String> responseBodyConverter ( ) {
StringHttpMessageConverter converter = new StringHttpMessageConverter ( Charset. forName ( "UTF-8" ) ) ;
return converter;
}
/ / 2.1 :解决中文乱码后,返回json时可能会出现No converter found for return value of type: xxxx
/ / 或这个:Could not find acceptable representation
/ / 解决此问题如下
public ObjectMapper getObjectMapper ( ) {
return new ObjectMapper ( ) ;
}
/ / 2.2 :解决No converter found for return value of type: xxxx
public MappingJackson2HttpMessageConverter messageConverter ( ) {
MappingJackson2HttpMessageConverter converter= new MappingJackson2HttpMessageConverter ( ) ;
converter. setObjectMapper ( getObjectMapper ( ) ) ;
return converter;
}
@Override
public void configureMessageConverters ( List< HttpMessageConverter< ? >> converters) {
super . configureMessageConverters ( converters) ;
/ / 解决中文乱码
converters. add ( responseBodyConverter ( ) ) ;
/ / 解决: 添加解决中文乱码后的配置之后,返回json数据直接报错 500 :no convertter for return value of type
/ / 或这个:Could not find acceptable representation
converters. add ( messageConverter ( ) ) ;
}
}
6、controller
package com. redis. session. controller;
import com. redis. session. constant. Constant;
import com. redis. session. entity. User;
import org. springframework. beans. factory. annotation. Autowired;
import org. springframework. data. redis. core. StringRedisTemplate;
import org. springframework. web. bind. annotation. RequestMapping;
import org. springframework. web. bind. annotation. RequestMethod;
import org. springframework. web. bind. annotation. RequestParam;
import org. springframework. web. bind. annotation. RestController;
import javax. servlet. http. HttpServletRequest;
import javax. servlet. http. HttpSession;
import java. util. HashMap;
import java. util. Map;
import java. util. concurrent. TimeUnit;
@RestController
@RequestMapping ( "/user" )
public class UserController {
@Autowired
private StringRedisTemplate redisTemplate;
@RequestMapping ( value = "/first" , method = RequestMethod. GET)
public Map< String, Object> firstResp ( HttpServletRequest request) {
Map< String, Object> map = new HashMap < > ( ) ;
request. getSession ( ) . setAttribute ( "request Url地址" , request. getRequestURL ( ) ) ;
map. put ( "request Url地址" , request. getRequestURL ( ) ) ;
return map;
}
@RequestMapping ( "/login" )
public String login ( HttpServletRequest request, @RequestParam ( name = "userName" ) String userName,
@RequestParam ( name = "password" ) String password) {
String mes = request. getRequestURI ( ) ;
System. out. println ( mes) ;
if ( "admin" . equals ( userName) && "123" . equals ( password) ) {
HttpSession session = request. getSession ( ) ;
session. setAttribute ( "user_id" , userName+ ":" + password) ;
redisTemplate. opsForValue ( ) . set ( userName+ ":" + password, session. getId ( ) , 10 , TimeUnit. MINUTES) ;
return "登录成功" ;
}
return "登录失败" ;
}
@RequestMapping ( "/hello" )
public String getInfo ( ) {
return "你好开心" ;
}
@RequestMapping ( "/exit" )
public String exit ( HttpServletRequest request) {
request. getSession ( ) . invalidate ( ) ;
return "注销成功" ;
}
}
7、启用redis管理Session
//第一种方式:修改application.properties,添加
spring.session.store-type=redis
//第二种方式:启用注解
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 600)
8、nginx集群配置
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local ] "$request " '
'$status $body_bytes_sent "$http_referer " '
'"$http_user_agent " "$http_x_forwarded_for "' ;
access_log logs/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
gzip_min_length 5k;
gzip_buffers 4 16k;
gzip_comp_level 4;
gzip_types text/css application/xml text/javascript image/jpeg image/gif;
gzip_vary on;
proxy_temp_path /usr/data/temp;
upstream myserver{
server 192.168.230.1:8080;
server 192.168.230.1:8090;
}
server{
listen 80;
server_name localhost;
access_log off;
error_log off;
location /user {
proxy_pass http://myserver;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr ;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for ;
proxy_set_header Host $host ;
proxy_connect_timeout 1;
proxy_send_timeout 1;
proxy_read_timeout 1;
}
}
}
9、redis配置外部访问redis.conf
1>注释掉bind
#bind 127.0.0.1
2>默认不是守护进程方式运行,这里可以修改
daemonize no
3>禁用保护模式
protected-mode no
10、工程代码
https://github.com/xuzhoukai/springboot2.1.3-redis