前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring MVC使用redis共享session

Spring MVC使用redis共享session

原创
作者头像
腾讯云数据库 TencentDB
修改2018-05-07 15:49:39
3.5K4
修改2018-05-07 15:49:39
举报
文章被收录于专栏:腾讯云数据库(TencentDB)

Spring MVC

Spring Web MVC是基于Java的轻量级Web框架,使用了MVC架构模式的思想。Spring Web MVC核心架构为:

  1. 用户发送的请求到达前端控制器DispatcherServlet,前端控制器根据请求信息来决定使用哪一个页面控制器,并将处理请求转给该控制器。
  2. 页面控制器收到请求后,可以完成请求的逻辑(这里的逻辑复杂了),处理完毕后返回一个ModelAndView(模型数据和逻辑视图名)。
  3. 前端控制器收回控制权,然后根据返回的逻辑视图名,选择相应的视图进行渲染,渲染时会将返回的模型数据填充到视图中,即形成响应。
  4. 前端控制器将响应返回给用户。

示例应用

  1. 创建一个MAVEN的webapp项目,使用eclipse会默认生成需要的目录
  2. 通过tomcat可以部署该webapp项目,该项目的入口即为web.xml配置文件
代码语言:txt
复制
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    version="3.1">
  <display-name>Archetype Created Web Application</display-name>
  
  <!-- 全局上下文的参数从classpath中的applicationContext.xml获取 -->
  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  <listener>
      <listener-class>
          org.springframework.web.context.ContextLoaderListener
      </listener-class>
  </listener>
  
  <!-- 定义拦截session的过滤器 -->
  <filter>
      <filter-name>springSessionRepositoryFilter</filter-name>
      <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>springSessionRepositoryFilter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <!-- 前端控制器 -->
  <servlet>
      <servlet-name>dispatcherServlet</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:spring-mvc.xml</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
      <servlet-name>dispatcherServlet</servlet-name>
      <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

spring-mvc.xml配置文件定义了前面提到的ModelAndView,只需要在classpath中能够找到即可,不固定文件位置。通常放在src/main/resources目录下:

代码语言:txt
复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
        
    <mvc:annotation-driven />
    <mvc:default-servlet-handler />
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:viewClass="org.springframework.web.servlet.view.JstlView"
        p:prefix="/WEB-INF/views/"
        p:suffix=".jsp" />
    <context:component-scan base-package="sample" />
</beans>

全局的上下文配置文件applicationContext.xml主要用于Redis的连接配置,如下:

代码语言:txt
复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                          http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
    
    <context:component-scan base-package="sample" />
    
    <context:property-placeholder location="classpath:redis.properties"/>
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxTotal" value="${redis.maxActive}" />
        <property name="maxWaitMillis" value="${redis.maxWait}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>
    
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="poolConfig" ref="poolConfig" />
        <property name="port" value="${redis.port}" />
        <property name="hostName" value="${redis.host}" />
    </bean>
    
    <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
    </bean>
    
    <bean id="redisHttpSessionConfiguration" class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
        <property name="maxInactiveIntervalInSeconds" value="1800" />
    </bean>
</beans> 

在上面的配置中有配置component-scan的base-package为sample,也就是搜索页面控制器的包。因此所有的页面控制器都需要放到该包下面。如:

代码语言:txt
复制
package sample;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class AppController {
    @RequestMapping("/")
    public String home() {
        return "index";
    }
    
    @RequestMapping("/put")
    public String put(HttpSession session) {
        session.setAttribute("name", "test");
        return "index";
    }
    
    @RequestMapping("/get")
    @ResponseBody
    public String get(HttpSession session) {
        return (String) session.getAttribute("name");
    }
}

其中使用到的Controller和RequestMapping装饰器是必要的,否则无法处理请求逻辑。

测试&问题

  1. Redis服务未开启时,报错Could not get a resource from the pool。由于无法连接到Redis,因此可用连接耗完。
  2. Redis服务开启时,不支持config命令(可以通过配置文件rename-command屏蔽config命令),报错为:
代码语言:txt
复制
Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'enableRedisKeyspaceNotificationsInitializer' defined in class path resource [org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Unable to configure Redis to keyspace notifications. See http://docs.spring.io/spring-session/docs/current/reference/html5/#api-redisoperationssessionrepository-sessiondestroyedevent
Caused by: java.lang.IllegalStateException: Unable to configure Redis to keyspace notifications. See http://docs.spring.io/spring-session/docs/current/reference/html5/#api-redisoperationssessionrepository-sessiondestroyedevent
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: ERR unknown command 'CONFIG'; nested exception is redis.clients.jedis.exceptions.JedisDataException: ERR unknown command 'CONFIG'

从报错信息中可以看出,由于enableRedisKeyspaceNotificationInitializer的报错而无法初始化,导致程序启动不了。而造成enableRedisKeyspaceNotificationInitializer报错的原因是无法使用CONFIG命令。解决方案:1)通过申请设置notify-keyspace-events为Egx;2)在配置文件中添加如下配置(这个配置和JedisConnectionFactory的放置在一起)

代码语言:txt
复制
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:util="http://www.springframework.org/schema/util"
     xsi:schemaLocation="http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> 
    <!-- 上面的两条util和schemaLocation需要填写,否则会报错util:constant没有匹配 -->
    <util:constant static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP"/>
</beans>

测试时,打开浏览器输入 http://localhost:8080/springsession/put 即可设置session,在Redis中可以查看到:

图1.png
图1.png

然后通过 http://localhost:8080/springsession/get 请问的时候会发现,在请求cookie中会有:

图2.png
图2.png

到此,spring session的简单使用和测试就已经完成了。网上对于这块的资料很杂,写法也有很多种,这里只是使用了其中一种来进行测试。

参考

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring MVC
    • 示例应用
      • 测试&问题
        • 参考
        相关产品与服务
        云数据库 MongoDB
        腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档