Spring Session边学边写(一)第一次实践

最近项目中考虑到跨系统(多个系统共享),跨平台(App和浏览器)的会话管理,还要考虑从现在的jboss替换为tomcat等其他应用服务器。正好spring出了Spring Session,而且更新到了1.0.1 RELEASE版本,借此机会学习一番,将实践经过一起分享。
首先是Spring Session的官方文档地址 : http://docs.spring.io/spring-session/docs/1.0.1.RELEASE/reference/html5/

里面可以看到介绍:
  • HttpSession: 集群会话、浏览器多会话支持、rest样式api
  • WebSocket
以及多种应用类型的示例和指导。 本次实践按照官方示例一:HttpSession进行。

1.搭建Maven工程
官方示例使用Maven工程实现,需要先搭建Maven工程并转为web项目。具体步骤见另外一篇博客(我也是按照他的来实现的,就不粘过来了,尊重原创) http://b-l-east.iteye.com/blog/1246482

按照步骤创建工程TestHttpSession,最后部署至tomcat并启动,访问 http://localhost:8080/TestHttpSession,说明项目搭建成功。

修改/创建src/main/webapp/index.jsp,代码如下
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<head>
	<title>Session Attributes</title>
	<link rel="stylesheet" href="assets/bootstrap.min.css">
	<style type="text/css">
		body {
			padding: 1em;
		}
	</style>
</head>
<body>
	<div class="container">
		<h1>Description</h1>
		<p>This application demonstrates how to use a Redis instance to back your session. Notice that there is no JSESSIONID cookie. We are also able to customize the way of identifying what the requested session id is.</p>

		<h1>Try it</h1>

		<form class="form-inline" role="form" action="./session" method="post">
			<label for="attributeValue">Attribute Name</label>
			<input id="attributeValue" type="text" name="attributeName"/>
			<label for="attributeValue">Attribute Value</label>
			<input id="attributeValue" type="text" name="attributeValue"/>
			<input type="submit" value="Set Attribute"/>
		</form>

		<hr/>

		<table class="table table-striped">
			<thead>
			<tr>
				<th>Attribute Name</th>
				<th>Attribute Value</th>
			</tr>
			</thead>
			<tbody>
			<c:forEach items="${sessionScope}" var="attr">
				<tr>
					<td><c:out value="${attr.key}"/></td>
					<td><c:out value="${attr.value}"/></td>
				</tr>
			</c:forEach>
			</tbody>
		</table>
	</div>
</body>
</html>

访问 http://localhost:8080/TestHttpSession,可看到首页。
设置attributeName和attributeValue并提交后,可以在下方看到设置的值。

如在页面中加入<%=session.getClass() %>以输出session的类型,可以看到session为:class org.apache.catalina.session.StandardSessionFacade类。

2.加入依赖库
修改pom.xml, <dependencies> </dependencies>标签内最后加入以下代码段
	<dependency>
	    <groupId>org.springframework.session</groupId>
	    <artifactId>spring-session-data-redis</artifactId>
	    <version>1.0.1.RELEASE</version>
	    <type>pom</type>
	</dependency>
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-web</artifactId>
	    <version>4.1.6.RELEASE</version>
	</dependency>

保存后项目会自动下载spring及spring session,jedis等依赖库。

3.加入配置代码
按照官方文档,在src/main/java源文件夹下创建sample包,并创建Config类
,代码如下
package sample;

import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.redis.embedded.EnableEmbeddedRedis;
import org.springframework.session.redis.embedded.RedisServerPort;

// tag::class[]
@EnableEmbeddedRedis // <1>
@EnableRedisHttpSession // <2>
public class Config {

	@Bean
	public JedisConnectionFactory connectionFactory(@RedisServerPort int port) {
		JedisConnectionFactory connection = new JedisConnectionFactory(); // <3>
		connection.setPort(port);
		return connection;
	}
}

这本是从GitHub上下载的源码,但是类中会报错,暂时忽略该问题,继续按官方文档执行。

在sample包下新建Initializer类,代码如下
package sample;

import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;

// tag::class[]
public class Initializer
		extends AbstractHttpSessionApplicationInitializer { // <1>

	public Initializer() {
		super(Config.class); // <2>
	}
}
// end::class[]

该类的作用是在应用启动时加载Config类,执行Config中的启动redis并创建连接等操作。

在sample包下新建SessionServlet类,代码如下
package sample;

import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;
import java.io.IOException;

// tag::class[]
@WebServlet("/session")
public class SessionServlet extends HttpServlet {

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String attributeName = req.getParameter("attributeName");
		String attributeValue = req.getParameter("attributeValue");
		req.getSession().setAttribute(attributeName, attributeValue);
		resp.sendRedirect(req.getContextPath() + "/");
	}

	private static final long serialVersionUID = 2878267318695777395L;
}
// tag::end[]

该类的作用是实现路径为/session的servlet,可以将属性post至session中保存。

4.部署测试
重新发布至tomcat。
访问 http://localhost:8080/TestHttpSession,发现无法访问。
查看tomcat控制台,发现意料之中的错误。因Config类中的类引用找不到,系统启动失败。

因Config类中对EnableEmbeddedRedis、RedisServerPort、RedisServerPort 这三个类的引用根本找不到导致类编译失败。
Config类的作用是EnableEmbeddedRedis自动创建内建的redis缓存,并使用jedis连接缓存、创建连接工厂,以供会话存储查询使用。但是不知道是不是因为源码版本的问题,根本找不到这几个类,所以无法启动缓存,jedis也无法连接。
所以只要使用外部redis缓存服务器,并将spring-jedis配置连接至外部缓存,就可以解决该问题。

5.使用外部缓存
redis官网地址: http://redis.io/
本想安装windows版,结果发现redis官方不支持windows。虽然github上有其他版本支持windows的redis,但是安装后启动不成功,遂放弃转向Linux服务器版本。
参考文章如下:
Redis介绍以及安装(Linux): http://www.cnblogs.com/silent2012/p/3499654.html
Redis常用命令: http://www.linuxidc.com/Linux/2012-03/57573.htm

按照文档将redis安装在linux服务器192.168.24.31上并启动redis-server,端口默认6379。
修改sample包下Config类,代码如下:
package sample;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

// tag::class[]
@Configuration
@EnableRedisHttpSession // <2>
public class Config {

	@Bean
	public JedisConnectionFactory connectionFactory() {
		JedisConnectionFactory connection = new JedisConnectionFactory(); // <3>
		connection.setPort(6379);
		connection.setHostName("192.168.24.31");
		return connection;
	}
}
// end::class[]

修改将内建redis的引用、启动去掉,并连接至刚配好的外部redis:192.168.24.31:6379。

5.部署测试
重新发布至tomcat。
访问 http://localhost:8080/TestHttpSession,可看到首页。
设置attributeName和attributeValue并提交后,可以在下方看到设置的值。
同时可以看到session的类型变成了class org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper类。
在linux服务器上使用redis-cli客户端的keys * 命令可看到会话已被缓存。

6.停机测试
将tomcat服务器关闭(但不关闭浏览器,以保留客户端cookie)。
重新启动tomcat后刷新页面,发现还可以取到之前session的值,说明集群会话缓存成功。
使用chrome开发者工具可看到cookie中原有的JSESSIONID被替换成了SESSION。

猜你喜欢

转载自sb33060418.iteye.com/blog/2225506