专栏首页腾讯云数据库(TencentDB)Spring MVC使用redis共享session
原创

Spring MVC使用redis共享session

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配置文件
<?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目录下:

<?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的连接配置,如下:

<?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,也就是搜索页面控制器的包。因此所有的页面控制器都需要放到该包下面。如:

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命令),报错为:
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的放置在一起)

<?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

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

图2.png

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

参考

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 即将写入MySQL源码的官方bug解决之路

    | 作者 周信静,毕业于浙江大学,目前在CDB/CynosDB数据库内核团队参与TXSQL云数据库内核研发工作,参与了热点行更新以及一系列性能优化工作,并修复...

    腾讯云数据库 TencentDB
  • 云开发数据库又增新技能!

    点击上方蓝字关注我们吧 开篇彩蛋 由于近期小程序·云开发将上线付费功能(付费功能针对非基础资源配额,基础资源配额仍可免费使用)。为了给开发者更充足的时间进行调...

    腾讯云数据库 TencentDB
  • 最佳实践 | 腾讯HTAP数据库TBase助力某省核心IT架构升级

    点击▲关注 腾讯云数据库 数据存储和处理是一个古老而重要的技术,从远古时期的结绳记事到古人的文本记事,再到计算机诞生后的各种系统,直到E.F.Codd提出关系...

    腾讯云数据库 TencentDB
  • SSM整合的前后端流程,已提供相关代码(二)(小白必看)

    一天不写程序难受
  • 图书管理系统(二)整合 SSM,你学会了么

    上一篇博客中,我们讲了 ?如何搭建项目框架结构。搭建好了最基本的目录结构后,那么我们就可以对 SSM 进行整合了,接下来具体介绍下如何进行整合。

    村雨遥
  • 猿蜕变17——一文掌握SSM框架搭建姿势

    看过之前的蜕变系列文章,相信你对SpringMVC 、Spring、 Mybatis有了一些应用上的感性认识。但是都还是单个使用,并没有放到一起来使用,今天我们...

    山旮旯的胖子
  • Spring、Spring MVC、MyBatis 整合文件配置详解

    大家好,我是你们的导师,我每天都会在这里给大家分享一些干货内容(当然了,周末也要允许老师休息一下哈)。上次老师跟大家分享了MySQL详细知识点的知识,今天跟大家...

    用户5224393
  • Activiti学习——Activiti与Spring集成

    与Spring集成 基础准备 目录结构 ? 相关jar包 Activiti的相关jar包  Activiti依赖的相关jar包  Spring的相关jar包  ...

    庞小明
  • springmvc 最简化配置

    一、新建maven webapp项目 http://blog.csdn.net/jxq0816/article/details/76063973

    week
  • spring开发_JDBC操作MySQL数据库_使用xml配置事务管理

    http://www.cnblogs.com/hongten/archive/2012/03/09/java_spring_jdbc.html

    Hongten

扫码关注云+社区

领取腾讯云代金券