1.首先在相应的pom.xml中导入redis的依赖
1 <!--添加redis--> 2 <dependency> 3 <groupId>org.springframework.boot</groupId> 4 <artifactId>spring-boot-starter-data-redis</artifactId> 5 </dependency> 6 <dependency> 7 <groupId>org.springframework.session</groupId> 8 <artifactId>spring-session-data-redis</artifactId> 9 </dependency>
2.在application.properties里添加redis的配置信息
1 #添加redis 2 spring.redis.database=0 3 spring.redis.host=localhost 4 spring.redis.port=6379 5 spring.redis.password=123456 6 spring.redis.timeout=20000ms 7 spring.redis.jedis.pool.max-active=8 8 spring.redis.jedis.pool.max-wait=-1ms 9 spring.redis.jedis.pool.max-idle=8 10 spring.redis.jedis.pool.min-idle=0
3.在启动类里面添加注解
@SpringBootApplication @EnableRedisHttpSession(flushMode = FlushMode.IMMEDIATE) public class UserServiceApplication { public static void main(String[] args) { SpringApplication.run(UserServiceApplication.class, args); } }
4.需要在网关中定义服务的头信息过滤规则,zuul默认会将头信息全部过滤掉,这会导致cookie丢失,就无法从redis中取出session数据了。
在网关的application.properties里面添加
#需要忽略的头部信息,不在传播到其他服务 sensitive-headers: Access-Control-Allow-Origin ignored-headers: Access-Control-Allow-Origin,H-APP-Id,Token,APPToken
#主意这个需要在你每个注册到网关的服务上面都要添加一个这个
zuul.routes.服务名称.sensitiveHeaders="*"
5.存session和取session的过程,spring帮我们自动的取完成了,存session
public Result ifLogin(HttpSession session) { //存session,spring自动帮我们存取到redis中 session.setAttribute("user", user1); //取session session.getAttribute("user"); }
到这里基本就可以实现session在不同服务间的session共享了,如果不能,请往下看
- 第一种解决方案直接存在redis里面,然后在不同服务间直接去取
-
@Autowired private RedisTemplate redisTemplate; @RequestMapping("login") public String login(){ //直接将session存入到redis中 redisTemplate.opsForValue().set("user",user); //然后取 redisTemplate.opsForValue().get("user"); }
注意:如果你是使用ajax来发送请求,你发现不管怎么样,session都共享不了,即使在同一个controller的不同请求之间,session都共享不了,那么你需要设置以下:
//使用原生的ajax $.ajax({ url: "http://localhost:8080/orders", type: "GET", //这里是重点 xhrFields: { withCredentials: true }, crossDomain: true, success: function (data) { render(data); } }); 如果使用的是$.post("http://192.168.10.*/user/user/ifLogin",callback,"json") 还需设置ajax全局发送请求的方式,带上请求头,和原生的自己比较便知 $(function(){ $.ajaxSetup({xhrFields: { withCredentials: true }}) })
- 另外还需在zuul网关里面设置一下配置
@Configuration public class CorsConfig { @Bean public CorsFilter corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); // 允许cookies跨域 config.addAllowedOrigin("*");// #允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin config.addAllowedHeader("*");// #允许访问的头信息,*表示全部 config.setMaxAge(7200L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了 config.addAllowedMethod("*");// 允许提交请求的方法,*表示全部允许 source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } }
package com.study.zuul.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpStatus; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Configuration public class FirstFilter extends ZuulFilter { /** * pre:可以在请求被路由之前调用 * route:在路由请求时候被调用 * post:在route和error过滤器之后被调用 * error:处理请求时发生错误时被调用 * * @return */ @Override public String filterType() { return FilterConstants.PRE_TYPE; } /** * 优先级为0,数字越大,优先级越低 * * @return */ @Override public int filterOrder() { return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletResponse response = ctx.getResponse(); HttpServletRequest request = ctx.getRequest(); response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH"); response.setHeader("Access-Control-Allow-Headers", "x-access-token, content-type"); response.setHeader("Access-Control-Expose-Headers", "X-forwared-port, X-forwarded-host"); response.setHeader("Vary", "Origin,Access-Control-Request-Method,Access-Control-Request-Headers"); // 跨域请求一共会进行两次请求 先发送options 是否可以请求 if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { ctx.setSendZuulResponse(false); //验证请求不进行路由 ctx.setResponseStatusCode(HttpStatus.OK.value());//返回验证成功的状态码 return null; } ctx.setSendZuulResponse(true); //对请求进行路由 ctx.setResponseStatusCode(HttpStatus.OK.value()); return null; } }
好了,基本上就是这样子,这个问题,我也是纠结了一天,总结下来,希望可以帮到以后的你们