spring-session之二:简单配置

摘要:
有两种常见的方式能够完成上述的SpringSession配置步骤。第一种方式是使用SpringBoot来自动配置SpringSession。借助像Maven或Gradle这样的依赖管理器,将SpringSession添加应用中是很容易的。spring-session依赖将会引入SpringSession的jar。至于SpringSessionServletfilter的配置,可以通过SpringBoot的自动配置来实现,这只需要在SpringBoot的配置类上使用@EnableRedisHttpSession注解就可以了,如下面的代码片段所示。packagecom.dxz.springsession.demo3.httpsession;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.boot.web.servlet.ServletComponentScan;importorg.springframework.context.annotation.Bean;importorg.springframework.web.servlet.ViewResolver;importorg.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;importorg.springframework.web.servlet.config.annotation.EnableWebMvc;importorg.springframework.web.servlet.view.InternalResourceViewResolver;@ServletComponentScan@SpringBootApplicationpublicclassSpringsecurityDemo3Application{publicstaticvoidmain{SpringApplication.run;}}至于SpringSession到Redis连接的配置,可以添加如下配置到SpringBoot的application.properties文件中:spring.redis.host=localhostspring.redis.password=123456spring.redis.port=6379SpringBoot提供了大量的基础设施用来配置到Redis的连接,定义到Redis数据库连接的各种方式都可以用在这里。

官方示例:https://docs.spring.io/spring-session/docs/current/reference/html5/#samples

配置Spring Session

在Web项目中配置Spring Session分为四步:

  • 搭建用于Spring Session的数据存储
  • 将Spring Session的jar文件添加到web应用中
  • 将Spring Session filter添加到web应用的配置中
  • 配置Spring Session如何选择session数据存储的连接

Spring Session自带了对Redis的支持。搭建和安装redis的细节可以参考《windows下安装redis》。

有两种常见的方式能够完成上述的Spring Session配置步骤。第一种方式是使用Spring Boot来自动配置Spring Session。第二种配置Spring Session的方式是手动完成上述的每一个配置步骤。

借助像Maven或Gradle这样的依赖管理器,将Spring Session添加应用中是很容易的。如果你使用Maven和Spring Boot的话,那么可以在pom.xml中使用如下的依赖:

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
</dependency>

其中,spring-boot-starter-redis依赖能够确保使用redis所需的所有jar都会包含在应用中,所以它们可以借助Spring Boot进行自动装配。spring-session依赖将会引入Spring Session的jar。

至于Spring Session Servlet filter的配置,可以通过Spring Boot的自动配置来实现,这只需要在Spring Boot的配置类上使用@EnableRedisHttpSession注解就可以了,如下面的代码片段所示。

packagecom.dxz.springsession.demo3.httpsession;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importorg.springframework.boot.web.servlet.ServletComponentScan;
importorg.springframework.context.annotation.Bean;
importorg.springframework.web.servlet.ViewResolver;
importorg.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
importorg.springframework.web.servlet.config.annotation.EnableWebMvc;
importorg.springframework.web.servlet.view.InternalResourceViewResolver;
@ServletComponentScan
@SpringBootApplication
public classSpringsecurityDemo3Application {
    public static voidmain(String[] args) {
        SpringApplication.run(SpringsecurityDemo3Application.class, args);
    }
}

至于Spring Session到Redis连接的配置,可以添加如下配置到Spring Boot的application.properties文件中:

spring.redis.host=localhost
spring.redis.password=123456
spring.redis.port=6379

Spring Boot提供了大量的基础设施用来配置到Redis的连接,定义到Redis数据库连接的各种方式都可以用在这里。你可以参考该地址的逐步操作指南,来了解如何使用Spring Session和Spring Boot。

packagecom.dxz.springsession.demo3.httpsession.config;
importorg.springframework.context.annotation.Bean;
importorg.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
importorg.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@EnableRedisHttpSession
public classConfig {
    @Bean
    publicLettuceConnectionFactory connectionFactory() {
        LettuceConnectionFactory factory = newLettuceConnectionFactory();
        factory.setPassword("123456");
        returnfactory;
    }
}
packagecom.dxz.springsession.demo3.httpsession.config;
importorg.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
public class Initializer extendsAbstractHttpSessionApplicationInitializer {
    publicInitializer() {
        super(Config.class);
    }
}
packagecom.dxz.springsession.demo3.httpsession.config;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.ComponentScan;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.session.web.http.HeaderHttpSessionStrategy;
importorg.springframework.web.servlet.ViewResolver;
importorg.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
importorg.springframework.web.servlet.config.annotation.EnableWebMvc;
importorg.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
importorg.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc //启动Spring MVC
@ComponentScan("com.dxz.springsession.demo3.httpsession") //启动组件扫描
public class WebConfig extendsWebMvcConfigurerAdapter {
    //配置JSP视图解析器
@Bean
    publicViewResolver viewResolver() {
        InternalResourceViewResolver resolver = newInternalResourceViewResolver();
        //resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        returnresolver;
    }
    //配置静态资源的处理
@Override
    public voidconfigureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        //对"静态文件"开启默认转发给servlet容器(如tomcat)处理
configurer.enable();
    }
}
packagecom.dxz.springsession.demo3.httpsession;
importorg.springframework.stereotype.Controller;
importorg.springframework.web.bind.annotation.RequestMapping;
@Controller
public classHomeHttpSessionController {
    @RequestMapping("/")
    publicString index() {
        return "index";
    }
}

在传统的web应用中,可以参考该指南来了解如何通过web.xml来使用Spring Session。

在传统的war文件中,可以参考该指南来了解如何不使用web.xml进行配置。

默认情况下,Spring Session会使用HTTP cookie来存储session id,但是我们也可以配置Spring Session使用自定义的HTTP header信息,如x-auth-token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3,当构建REST API的时候,这种方式是很有用的。完整的指南可以参考该地址

使用Spring Session

Spring Session配置完成之后,我们就可以使用标准的Servlet API与之交互了。例如,如下的代码定义了一个servlet,它使用标准的Servlet session API来访问session。

packagecom.dxz.springsession.demo3.httpsession.config;
importjava.io.IOException;
importjavax.servlet.ServletException;
importjavax.servlet.annotation.WebServlet;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
@WebServlet("/session")
public class SessionServlet extendsHttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throwsServletException, IOException {
        String attributeName = req.getParameter("attributeName");
        String attributeValue = req.getParameter("attributeValue");
        System.out.println("session servlet..." + "attributeName:" + attributeName +", attributeValue:" +attributeValue);
        req.getSession().setAttribute(attributeName, attributeValue);
        resp.sendRedirect(req.getContextPath() + "/");
    }
    private static final long serialVersionUID = 2878267318695777395L;
}

配置sessionListener监听session的创建及销毁,如下:

packagecom.dxz.springsession.demo3.httpsession;
importjavax.servlet.http.HttpSession;
importjavax.servlet.http.HttpSessionEvent;
importjavax.servlet.http.HttpSessionListener;
importorg.springframework.stereotype.Component;
@Component
public class MyListener implementsHttpSessionListener {
    @Override
    public voidsessionCreated(HttpSessionEvent se) {
        System.out.println("sessionCreated()" +printHttpSession(se.getSession()));
        System.out.println("online + 1");
    }
    @Override
    public voidsessionDestroyed(HttpSessionEvent se) {
        System.out.println("sessionDestroyed()"  +printHttpSession(se.getSession()));
        System.out.println("online - 1");
    }
    privateString printHttpSession(HttpSession session) {
        StringBuffer sb = newStringBuffer();
        sb.append("uin:="+session.getAttribute("uin"));
        sb.append(", createtime:="+session.getCreationTime());
        sb.append(", value:="+session.getValue("uin"));
        returnsb.toString();
    }
}

每个浏览器多个Session

Spring Session会为每个用户保留多个session,这是通过使用名为“_s”的session别名参数实现的。例如,如果到达的请求为http://example.com/doSomething?_s=0 ,那么Spring Session将会读取“_s”参数的值,并通过它确定这个请求所使用的是默认session。

如果到达的请求是http://example.com/doSomething?_s=1的话,那么Spring Session就能知道这个请求所要使用的session别名为1.如果请求没有指定“_s”参数的话,例如http://example.com/doSomething,那么Spring Session将其视为使用默认的session,也就是说_s=0

要为某个浏览器创建新的session,只需要调用javax.servlet.http.HttpServletRequest.getSession()就可以了,就像我们通常所做的那样,Spring Session将会返回正确的session或者按照标准Servlet规范的语义创建一个新的session。下面的表格描述了针对同一个浏览器窗口,getSession()面对不同url时的行为。

HTTP请求URL

Session别名

getSession()的行为

example.com/resource

0

如果存在session与别名0关联的话,就返回该session,否则的话创建一个新的session并将其与别名0关联。

example.com/resource?_s=1

1

如果存在session与别名1关联的话,就返回该session,否则的话创建一个新的session并将其与别名1关联。

example.com/resource?_s=0

0

如果存在session与别名0关联的话,就返回该session,否则的话创建一个新的session并将其与别名0关联。

example.com/resource?_s=abc

abc

如果存在session与别名abc关联的话,就返回该session,否则的话创建一个新的session并将其与别名abc关联。

如上面的表格所示,session别名不一定必须是整型,它只需要区别于其他分配给用户的session别名就可以了。但是,整型的session别名可能是最易于使用的,Spring Session提供了HttpSessionManager接口,这个接口包含了一些使用session别名的工具方法。

我们可以在HttpServletRequest中,通过名为“org.springframework.session.web.http.HttpSessionManager”的属性获取当前的HttpSessionManager。如下的样例代码阐述了如何得到HttpSessionManager,并且在样例注释中描述了其关键方法的行为。

@WebServlet("/example")
public class Example extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest request,HttpServletResponse response)
  throws ServletException, IOException {
    /*
     * 在请求中,根据名为org.springframework.session.web.http.HttpSessionManager的key
     * 获得Spring Session session管理器的引用
     */
    HttpSessionManager sessionManager=(HttpSessionManager)request.getAttribute(
        "org.springframework.session.web.http.HttpSessionManager");
    /*
     * 使用session管理器找出所请求session的别名。
     * 默认情况下,session别名会包含在url中,并且请求参数的名称为“_s”。
     * 例如,http://localhost:8080/example?_s=1
     * 将会使如下的代码打印出“Requested Session Alias is: 1”
     */
    String requestedSessionAlias=sessionManager.getCurrentSessionAlias(request);
    System.out.println("Requested Session Alias is:  " + requestedSessionAlias);
    /* 返回一个唯一的session别名id,这个别名目前没有被浏览器用来发送请求。
     * 这个方法并不会创建新的session,
     * 我们需要调用request.getSession()来创建新session。
     */
    String newSessionAlias = sessionManager.getNewSessionAlias(request);
    /* 使用新创建的session别名来建立URL,这个URL将会包含
     * “_s”参数。例如,如果newSessionAlias的值为2的话, 
     * 那么如下的方法将会返回“/inbox?_s=2”
     */
    String encodedURL = sessionManager.encodeURL("/inbox", newSessionAlias);
    System.out.println(encodedURL);
    /* 返回session别名与session id所组成的Map,
    * 它们是由浏览器发送请求所形成的。
     */
    Map < String, String > sessionIds = sessionManager.getSessionIds(request);
  }
}

结论

Spring Session为企业级Java的session管理带来了革新,使得如下的任务变得更加容易:

  • 编写可水平扩展的原生云应用。
  • 将session所保存的状态卸载到特定的外部session存储中,如Redis或Apache Geode中,它们能够以独立于应用服务器的方式提供高质量的集群。
  • 当用户使用WebSocket发送请求的时候,能够保持HttpSession处于活跃状态。
  • 在非Web请求的处理代码中,能够访问session数据,比如在JMS消息的处理代码中。
  • 支持每个浏览器上使用多个session,这样就可以很容易地构建更加丰富的终端用户体验。
  • 控制客户端和服务器端之间如何进行session id的交换,这样更加易于编写Restful API,因为它可以从HTTP 头信息中获取session id,而不必再依赖于cookie。

如果你想抛弃传统的重量级应用服务器,但受制于已经使用了这些应用服务器的session集群特性,那么Spring Session将是帮助你迈向更加轻量级容器的重要一步,这些轻量级的容器包括Tomcat、Jetty或Undertow。

Reference:
http://www.infoq.com/cn/articles/Next-Generation-Session-Management-with-Spring-Session?utm_campaign=rightbar_v2&utm_source=infoq&utm_medium=articles_link&utm_content=link_text

免责声明:文章转载自《spring-session之二:简单配置》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Redis 实现抢票MySQL的binlog数据如何查看下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

如何解决Linux 系统下 ifconfig 命令无网络接口 ens33

今天我在做Redis的哨兵集群模式的时候,以前都是好的,也不知道从什么时候开始就无法连接Redis服务器了,就是运行如下命令,没有效果:redis-server redis.conf,然后在通过命令查看redis的状态,始终没有启动Redis,命令如下:ps -ef|grep redis 或者 ps -ef|grep 6379 ,查询不到Redis服务器的...

ashx文件中使用session提示“未将对象引用设置到对象的实例”

usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Web;usingSystem.Data;usingSystem.Web.SessionState;namespacefriends{///<summary>///Handler的摘要说明///&l...

session的属性设置

2.session的属性设置 先看案例: 登陆页面: <%@page contentType="text/html;charset=gb2312"%> <formaction="login.jsp" method="post">//表单提交激活的页面【此处设为本页】 用户名:<input type="text"...

redis maxmemory设置

关于maxmemory的设置,如果redis的应用场景是作为db使用,那不要设置这个选项,因为db是不能容忍丢失数据的。 如果作为cache使用,则可以启用这个选项(其实既然有淘汰策略,那就是cache了。。。) 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key, #...

(秒嘀)登录短信验证码开发 Demo

注意:前提你要在秒嘀注册:http://www.miaodiyun.com/doc/demo.html 配置类   package com.miaodiyun.httpApiDemo.common; public class Config {/*** url前半部分*/public static final String BASE_URL = "https:...

Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协...