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里面添加
#主意這個需要在你每個注冊到網關的服務上面都要添加一個這個
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; } }
好了,基本上就是這樣子,這個問題,我也是糾結了一天,總結下來,希望可以幫到以后的你們
