干货--Redis+Spring+Struts2实现网站计算器应用项目案例

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介:

有关redis的介绍我就不说了,可以参看我前几篇文章,redis快速入门
首先来看一下redis的应用场景
这里写图片描述

下面是我这个项目的的运行的场景截图
这里写图片描述

这是我们经常在各博客见到的顶和踩的画面,对于这种场景,我们用非关系型数据库来操作是非常不方便地,不光是查询不方便(写sql语句),而且在高并发的时候,可能会使系统假死,所以redis就派上用场了,它属于非关系型数据库,它直接操作内存,非常快速。
下面直接看代码
首先看看所需的包
除了Spring和Struts2所需的包外 还需连接redis的包 这里是spring-data-redis
这里写图片描述

这里写图片描述

本项目是模拟用户实现顶和踩的功能

所以先创一个实体类User

package com.yc.beans;

public class User {
    private int ding;//顶
    private int cai;//踩


    public int getCai() {
        return cai;
    }

    public void setCai(int cai) {
        this.cai = cai;
    }

    public int getDing() {
        return ding;
    }

    public void setDing(int ding) {
        this.ding = ding;
    }

}

因为是spring+Struts2一起,所以要改web.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:web="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" id="WebApp_9" version="2.4">


  <!-- spring的配置文件的路径,   -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:applicationContext*.xml</param-value>
  </context-param>
  <!-- 配置spring的上下文临听器:  当应用程序一加载到服务器上时,就会调用这个  ContextLoaderListerner, 这个临听器会读取contextConfigLocation配置的spring配置文件,完成
       spring容器的初始化.

     -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- struts2的前端过滤器 -->
  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>


  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

首先看一下客户端请求页面 index.jsp

<%@ page
    language="java"
    contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta
    http-equiv="Content-Type"
    content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style>
#head {
    font-family: cursive;
    font-size: 25px;
    color: orange;
    cursor: pointer;
}

#content {height =300px;
    font-family: cursive;
    font-size: 20px;
}

.ding {
    border: 1px solid blue;
    height: 60px;
    width: 70px;
    margin-left: 150px; padding-left10px;
    float: left;
    background: #FFF;
}

.ding img {
    display: inline-block;
    margin-top: 15px;
    margin-left: 10px;
    cursor: pointer;
}

.sding {
    float: left;
    margin-top: 16px;
    font-family: cursive;
    text-decoration: underline;
}
</style>
<script src="js/jquery-1.11.3.js"></script>
<script type="text/javascript">
    //当这个页面加载完毕 则给 loginbtn绑定单击事件
    $(function() {
        $.ajax({
            type : "POST",
            url : "User_Find.action",
            dataType : 'JSON',
            success : function(data) {
                if (data.code == 1) {
                    $("#num").text(data.obj.ding);
                    $("#numcai").text(data.obj.cai);
                } else {
                    alert(data);
                }
            }

        });
    });
    function addDing() {

        $.ajax({
            type : "POST",
            url : "User_Ding.action",
            dataType : 'JSON',
            success : function(data) {
                if (data.code == 1) {
                    $("#num").text(data.obj.ding)
                } else {
                    alert(data);
                }
            }

        });
    }

function addCai(){
        $.ajax({
            type:"POST",
            url:"User_Cai.action",
            dataType:'JSON',
            success: function(data){
                if(data.code==1){
                    $("#numcai").text(data.obj.cai);
                }else{
                    alert(data);
                }
            }

        });
    }
</script>
</head>

<body>
    <center>
        <div style="background: #0F0; height: 400px; width: 600px;">
            <table
                CELLPADDING="0"
                border="1px"
                bordercolor="yellow"
                height="400px"
                width="600px">
                <tr>
                    <th
                        id="head"
                        align="left"
                        height="50px"
                        colspan="3">年度最热门博客</th>
                </tr>
                <tr id="content">

                    <td
                        height="200"
                        colspan="3">都说飞得越高,摔得越惨,但是我想看看我到底会摔得有多惨,落地了,只要没死,那么爬起来,每走一步都是向上! <br>
                        </br>
                        时间并不会真的帮我们解决什么问题,它只是把原来怎么也想不通的问题,变得不再重要了。
                        </td>
                </tr>
                <tr>
                    <td colspan="3">
                        <div class="ding">
                            <span class="sding"></span><img
                                alt="tup"
                                src="images/ding.gif"
                                onclick="addDing()"><span id="num"></span>
                        </div>
                        <div class="ding">
                            <span class="sding"></span><img
                                alt="tup"
                                src="images/cai.gif" onclick="addCai()"><span id="numcai"></span>
                        </div>
                    </td>
                </tr>
            </table>
        </div>
    </center>

</body>



</html>

它发请求到UserAction,请后台传递数据用JSON
所以再看看Struts.xml,

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <!-- 关闭动态方法调用 actionid!方法名.action -->
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <!-- 启用开发模式 -->
    <constant name="struts.devMode" value="true" />
    <!-- action的创建由spring来完成,而不由struts完成. -->
    <constant name="struts.objectFactory" value="spring" />

    <package name="default" namespace="/" extends="json-default">

      <action name="User_*" class="userAction" method="{1}">
        <result name="success" type="json">
                <param name="root">
                    jsonModel
                </param>
            </result>
      </action>
    </package>

</struts>

再看UserAction之前,我们先看看一个帮助类

package com.yc.utils;
import java.io.Serializable;
public class JsonModel implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = -7830500053112045585L;
    private Integer code;
    private String message;
    private Object obj;
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public Object getObj() {
        return obj;
    }
    public void setObj(Object obj) {
        this.obj = obj;
    }



}

通过这个帮助类将数据转为JSON数据发给前台,具体看后面的代码

我们连接redis服务都是通过spring来完成的,所以我们看看spring 的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 启用注解解析器 -->
    <context:annotation-config />
    <!-- 因为采用了混合解析方式( 有一部分配置在xml中,有一部分在java类中,所以要让spring的注解解析器去扫描包 -->
    <context:component-scan base-package="com.yc" />
    <!-- 启用aspectj的注解方式的代理 -->
    <aop:aspectj-autoproxy />

    <!-- 创建redis工厂 -->
    <bean id="jedisFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="localhost" />
        <property name="port" value="6379" />
        <property name="usePool" value="true" />
    </bean>

    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisFactory" />
        <property name="keySerializer">  
            <bean  
                class="org.springframework.data.redis.serializer.StringRedisSerializer" />  
        </property>  
        <property name="valueSerializer">  
            <bean  
                class="org.springframework.data.redis.serializer.StringRedisSerializer" />  
        </property>
    </bean>

    <bean id="springRedisClientImpl" class="com.yc.redis.spring.clients.SpringRedisClientImpl">
        <property name="redisTemplate" ref="redisTemplate" />
    </bean>

</beans>

这样我们就可以来操作redis数据库了

再看看操作redis的帮助类,,它里面封装了我们一些基本的操作redis的方法

package com.yc.redis.spring.clients;

import java.util.Set;

public interface SpringRedisClient {
    /**
     * 存
     * @param key
     * @param value
     */
    public void setKey( String key,  String value);
    /**
     * 根据键取值
     * @param key
     * @return
     */
    public Object getKey( String key);
    /**
     * 自增
     * @param key
     */
    public void incr( String key);
    /**
     * 在上一个元素的左边存
     * @param key
     * @param value
     */
    public void lPush( String key, String value);
    /**
     * 查看是否有这个键
     * @param key
     * @return
     */
    public boolean checkKey( String key);
    /**
     * 按键取
     * @param key
     * @return
     */
    public Object lIndex( String key);
    /**
     * 求长度
     * @param key
     * @return
     */
    public Long lLength( String key);
    /**
     * 从上一个元素的左边取值
     * @param key
     * @return
     */
    public String lPop( String key);
    /**
     * 按正则表达式匹配的键取值
     * @param pattern
     * @return
     */
    public Set<String> getKeys( String pattern);


}

看看它的实现,里面通过spring注入了一个RedisTemplate,这在spring的配置文件里面已经注册了,这样就可以访问redis数据库了

package com.yc.redis.spring.clients;

import java.io.Serializable;
import java.util.Set;

import org.springframework.data.redis.core.RedisTemplate;

public class SpringRedisClientImpl implements SpringRedisClient,Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = -4213002642362857373L;
    private RedisTemplate redisTemplate;

    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void setKey(String key, String value) {
        this.redisTemplate.opsForValue().set(key, value);
    }

    @Override
    public Object getKey(String key) {
        return this.redisTemplate.opsForValue().get(key);
    }

    @Override
    public void incr(String key) {
        this.redisTemplate.opsForValue().increment(key, 1);
    }

    @Override
    public void lPush(String key, String value) {
        this.redisTemplate.opsForList().leftPush(key, value);
    }

    @Override
    public boolean checkKey(String key) {
        return this.redisTemplate.hasKey(key);
    }

    @Override
    public Object lIndex(String key) {
        return this.redisTemplate.opsForList().index(key, 0);
    }

    @Override
    public Long lLength(String key) {
        return this.redisTemplate.opsForList().size(key);
    }

    @Override
    public String lPop(String key) {
        return (String) this.redisTemplate.opsForList().leftPop(key);
    }

    @Override
    public Set<String> getKeys(String pattern) {
        return this.redisTemplate.keys(pattern);
    }

}

首先看看业务层,定义了三个接口方法,分别是顶,踩和刷新时查找顶和踩的数量

package com.yc.service;
public interface UserService {
    public String Ding();
    public String Cai() ;
    public String[] Find() ;
}


下面看它的实现类

package com.yc.service.impl;

import java.io.Serializable;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import com.yc.redis.spring.clients.SpringRedisClientImpl;
import com.yc.service.UserService;

import redis.clients.jedis.Jedis;
@Service("userServiceImpl")
public class UserServiceImpl implements UserService ,Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 1304876423677235894L;
    @Autowired
    private SpringRedisClientImpl springRedisClientImpl;//通过spring注入

    @Override
    public String Ding() {
        springRedisClientImpl.incr("User:ding");
        String num=(String) springRedisClientImpl.getKey("User:ding");
        return num;
    }


    public SpringRedisClientImpl getSpringRedisClientImpl() {
        return springRedisClientImpl;
    }


    public void setSpringRedisClientImpl(SpringRedisClientImpl springRedisClientImpl) {
        this.springRedisClientImpl = springRedisClientImpl;
    }

    @Override
    public String Cai() {
        springRedisClientImpl.incr("User:cai");
        String num=(String) springRedisClientImpl.getKey("User:cai");
        return num;
    }

    @Override
    public String[] Find() {
        String s[]=new String[2];
        s[0]= (String) springRedisClientImpl.getKey("User:ding");
        s[1]= (String) springRedisClientImpl.getKey("User:cai");
        return s;
    }
}


最后大家可以看UserAction类了

package com.yc.web.actions;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.opensymphony.xwork2.ActionSupport;
import com.yc.beans.User;
import com.yc.service.UserService;
import com.yc.service.impl.UserServiceImpl;
import com.yc.utils.JsonModel;
import com.yc.utils.JsonModel;

import redis.clients.jedis.Jedis;
@Controller("userAction")
public class UserAction extends ActionSupport {

    /**
     * 
     */
    private static final long serialVersionUID = 1825223373127715747L;
    private JsonModel jsonModel = new JsonModel();
    @Autowired
    private UserServiceImpl userServiceImpl;


    public JsonModel getJsonModel() {
        return jsonModel;
    }

    public void setJsonModel(JsonModel jsonModel) {
        this.jsonModel = jsonModel;
    }

    public String Ding() {
        User user = new User();
        String num = userServiceImpl.Ding();
        if (num != null && !"".equals(num)) {
            user.setDing(Integer.parseInt(num));
            jsonModel.setCode(1);
            jsonModel.setObj(user);
        }
        return SUCCESS;
    }

    public String Cai() {
        User user = new User();
        String num = userServiceImpl.Cai();
        if (num != null && !"".equals(num)) {
            user.setCai(Integer.parseInt(num));
            jsonModel.setCode(1);
            jsonModel.setObj(user);
        }
        return SUCCESS;
    }

    public String Find() {
        User user = new User();
        System.out.println(userServiceImpl);
        String num[] = userServiceImpl.Find();
        user.setDing(Integer.parseInt(num[0]));
        user.setCai(Integer.parseInt(num[1]));
        jsonModel.setCode(1);
        jsonModel.setObj(user);
        return SUCCESS;

    }
}

这样所有的代码就都已经分析完了,搭建好redis服务后,就可以跑了,
整个项目的代码有需要的朋友可以下载
http://download.csdn.net/detail/tanggao1314/9487851

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
9天前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
21 2
|
11天前
|
NoSQL Java API
springboot项目Redis统计在线用户
通过本文的介绍,您可以在Spring Boot项目中使用Redis实现在线用户统计。通过合理配置Redis和实现用户登录、注销及统计逻辑,您可以高效地管理在线用户。希望本文的详细解释和代码示例能帮助您在实际项目中成功应用这一技术。
22 3
|
13天前
|
消息中间件 NoSQL Java
Spring Boot整合Redis
通过Spring Boot整合Redis,可以显著提升应用的性能和响应速度。在本文中,我们详细介绍了如何配置和使用Redis,包括基本的CRUD操作和具有过期时间的值设置方法。希望本文能帮助你在实际项目中高效地整合和使用Redis。
32 1
|
1月前
|
设计模式 前端开发 Java
Spring MVC——项目创建和建立请求连接
MVC是一种软件架构设计模式,将应用分为模型、视图和控制器三部分。Spring MVC是基于MVC模式的Web框架,通过`@RequestMapping`等注解实现URL路由映射,支持GET和POST请求,并可传递参数。创建Spring MVC项目与Spring Boot类似,使用`@RestController`注解标记控制器类。
34 1
Spring MVC——项目创建和建立请求连接
|
1月前
|
Java 关系型数据库 MySQL
Maven——创建 Spring Boot项目
Maven 是一个项目管理工具,通过配置 `pom.xml` 文件自动获取所需的 jar 包,简化了项目的构建和管理过程。其核心功能包括项目构建和依赖管理,支持创建、编译、测试、打包和发布项目。Maven 仓库分为本地仓库和远程仓库,远程仓库包括中央仓库、私服和其他公共库。此外,文档还介绍了如何创建第一个 SpringBoot 项目并实现简单的 HTTP 请求响应。
121 1
Maven——创建 Spring Boot项目
|
1月前
|
缓存 NoSQL Java
Spring Boot与Redis:整合与实战
【10月更文挑战第15天】本文介绍了如何在Spring Boot项目中整合Redis,通过一个电商商品推荐系统的案例,详细展示了从添加依赖、配置连接信息到创建配置类的具体步骤。实战部分演示了如何利用Redis缓存提高系统响应速度,减少数据库访问压力,从而提升用户体验。
72 2
|
1月前
|
Java Apache Maven
Java/Spring项目的包开头为什么是com?
本文介绍了 Maven 项目的初始结构,并详细解释了 Java 包命名惯例中的域名反转规则。通过域名反转(如 `com.example`),可以确保包名的唯一性,避免命名冲突,提高代码的可读性和逻辑分层。文章还讨论了域名反转的好处,包括避免命名冲突、全球唯一性、提高代码可读性和逻辑分层。最后,作者提出了一个关于包名的问题,引发读者思考。
Java/Spring项目的包开头为什么是com?
|
18天前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
32 0
|
2月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
1月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
166 2
下一篇
无影云桌面