溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

redis制作計(jì)數(shù)器的方法

發(fā)布時(shí)間:2020-06-12 12:34:46 來(lái)源:億速云 閱讀:293 作者:Leah 欄目:編程語(yǔ)言

這篇文章將為大家詳細(xì)講解有關(guān)redis制作計(jì)數(shù)器的方法,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

用redis來(lái)存儲(chǔ)下單計(jì)數(shù),每天當(dāng)?shù)谝粋€(gè)用戶下單時(shí),在redis中創(chuàng)建兩個(gè)map對(duì)象,20170314_pz_ip_order_count 用來(lái)儲(chǔ)存20170314 這天的ip 下單計(jì)數(shù),map的key是ip地址,20170314_pz_user_order_count 用來(lái)存儲(chǔ)20170314這天的用戶下單計(jì)數(shù) map對(duì)象的key是用戶id.

1.redis依賴包

     <dependency>   
        <groupId>org.springframework.data</groupId>   
        <artifactId>spring-data-redis</artifactId>   
        <version>1.4.0.RELEASE</version>   
    </dependency>   

    <dependency>   
        <groupId>redis.clients</groupId>   
        <artifactId>jedis</artifactId>   
        <version>2.5.1</version>   
    </dependency>

ps:用于開始導(dǎo)入的clieant的jar包1.4  版本比較低,所以導(dǎo)致redis連不上,所以redis還是要看服務(wù)端的版本,選擇對(duì)應(yīng)的client

2.spring配置

<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">  
<property name="maxTotal" value="${redis.maxTotal}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>

<bean id="connectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="usePool" value="${redis.usePool}"></property>
<property name="hostName" value="${redis.host}" />
<property name="port" value="${redis.port}" />
<property name="password" value="${redis.password}" />
<property name="timeout" value="${redis.timeout}" />
<constructor-arg index="0" ref="poolConfig" />
</bean>

<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">   
    <property name="connectionFactory"   ref="connectionFactory" />   
</bean>

ps:高版本的poolConfig配置屬性有所變更,比如之前maxAcive 變?yōu)?maxTotal 

3.編碼

package com.pz998.rpc.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

public abstract class AbstractBaseRedisService<K, V>{
@Autowired  
protected RedisTemplate<K, V> redisTemplate;

    /**  
     * 設(shè)置redisTemplate  
     * @param redisTemplate the redisTemplate to set  
     */   
    public void setRedisTemplate(RedisTemplate<K, V> redisTemplate) {   
        this.redisTemplate = redisTemplate;   
    }   

    /**  
     * 獲取 RedisSerializer  
     * <br>------------------------------<br>  
     */   
    protected RedisSerializer<String> getRedisSerializer() {   
        return redisTemplate.getStringSerializer();   
    }   

}

package com.pz998.rpc.service.impl;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.stereotype.Service;

import com.pz998.rpc.common.utils.Contents;
import com.pz998.rpc.service.RequestCountRpcService;
@Service("requestCountRpcService")
public class RequestCountRpcServiceImpl extends AbstractBaseRedisService<String, Object> implements RequestCountRpcService{

public void ipCount(String ip, Integer count) { 
    String curDate = DateFormatUtils.format(new Date(), "yyyyMMdd"); 
    String key = curDate+Contents.IP_LIMIT_KEY_SUFFIX; 
    Integer oldCount = get(key,ip); 
    oldCount = oldCount+count; 
    add(key, ip,oldCount); 
} 

public void userCount(String userId, Integer count) { 
    String curDate = DateFormatUtils.format(new Date(), "yyyyMMdd"); 
    String key = curDate+Contents.USER_LIMIT_KEY_SUFFIX; 
    Integer oldCount = get(key,userId); 
    oldCount = oldCount+count; 
    add(key,userId,oldCount); 

} 

public void clear(String key, String hashKey){ 
    redisTemplate.opsForHash().delete(key, hashKey); 
} 

public void add(String key, String hashKey, Integer count) { 
    String countStr = count==null?"0":count.toString(); 
    redisTemplate.opsForHash().put(key,hashKey, countStr); 
    redisTemplate.expire(key, 24*60*2, TimeUnit.MINUTES); 
} 

public Integer get(String key, String hashKey) { 
    String val = (String)redisTemplate.opsForHash().get(key, hashKey); 
    if(StringUtils.isEmpty(val)){ 
        return 0; 
    } 

    return Integer.parseInt(val); 
} 

}

4.攔截器配置

<mvc:interceptors> 
     <mvc:interceptor> 
        <mvc:mapping path="/**"/>  
        <bean class="com.pz998.app.service.interceptor.SecurityInterceptor"> 
            <property name="ipLimitCount" value="10"></property> 
            <property name="userLimitCount" value="5"></property> 
            <property name="methodSet"> 
                <set> 
                    <value>submitJjqhOrder</value> 
                    <value>submitYymyOrder</value> 
                    <value>submitJypzOrder</value> 
                    <value>submitGhpzOrder</value> 
                    <value>submitDqbgOrder</value> 
                </set> 
            </property> 
        </bean> 
    </mvc:interceptor> 
    <!-- 當(dāng)設(shè)置多個(gè)攔截器時(shí),先按順序調(diào)用preHandle方法,然后逆序調(diào)用每個(gè)攔截器的postHandle和afterCompletion方法 -->  
</mvc:interceptors>

ps:將具體攔截的業(yè)務(wù)方法methodSet,ip限制的閥值ipLimitCount,user閥值userLimitCount 作為攔截器的屬性進(jìn)行注入,這樣增強(qiáng)了配置靈活性

5.攔截器編寫

package com.pz998.app.service.interceptor;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.pz998.rpc.common.model.vo.ResponseVoRpc;
import com.pz998.rpc.common.utils.Contents;
import com.pz998.rpc.service.RequestCountRpcService;

public class SecurityInterceptor implements HandlerInterceptor{

private RequestCountRpcService requestCountRpcService; 

private Integer ipLimitCount = 10; 
private Integer userLimitCount = 5; 

private Set<String> methodSet; 

public String getRemoteHost(javax.servlet.http.HttpServletRequest request){ 
    String ip = request.getHeader("x-forwarded-for"); 
    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ 
        ip = request.getHeader("Proxy-Client-IP"); 
    } 
    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ 
        ip = request.getHeader("WL-Proxy-Client-IP"); 
    } 
    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){ 
        ip = request.getRemoteAddr(); 
    } 
    return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip; 
} 

@Override 
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
        throws Exception { 
    String customerId = request.getParameter("customerId"); 
    String mn = request.getParameter("mn"); 
    if(StringUtils.isEmpty(mn)){ 
        return true; 
    }  
    if(!methodSet.contains(mn)){ 
        return true;  
    }  
    ServletContext servletContext = request.getServletContext();  
    WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);               
    requestCountRpcService = (RequestCountRpcService)ctx.getBean("requestCountRpcService" );  
    String host = getRemoteHost(request); 

    ResponseVoRpc responseVoRpc = new ResponseVoRpc(); 
    if(isLimitIp(host)){ 
        PrintWriter out = null; 
        try { 
            out = response.getWriter(); 
            response.setContentType("application/json;charset=UTF-8");   
            response.setHeader("Cache-Control", "no-cache");   

            responseVoRpc.setCode(ResponseVoRpc.CODE_COMMON_FAILED); 
            responseVoRpc.setCodeMsg("同一ip下單過(guò)多,已被限制"); 
            out.write(JSON.toJSONString(responseVoRpc)); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        }finally{ 
            if(out != null) 
                out.close(); 
        } 

        return false; 
    } 

    if(isLimitUser(customerId)){ 
        PrintWriter out = null; 
        try { 
            out = response.getWriter(); 
            response.setContentType("application/json;charset=UTF-8");   
            response.setHeader("Cache-Control", "no-cache");   

            responseVoRpc.setCode(ResponseVoRpc.CODE_COMMON_FAILED); 
            responseVoRpc.setCodeMsg("同一用戶下單過(guò)多,已被限制"); 
            out.write(JSON.toJSONString(responseVoRpc)); 
        } catch (IOException e) { 
            e.printStackTrace(); 
        }finally{ 
            if(out != null) 
                out.close(); 
        } 
        return false; 
    } 

    requestCountRpcService.ipCount(host, 1); 
    requestCountRpcService.userCount(customerId, 1); 
    return true; 
} 

private boolean isLimitUser(String urseId) { 
    String key = DateFormatUtils.format(new Date(), "yyyyMMdd")+Contents.USER_LIMIT_KEY_SUFFIX; 
    Integer count = requestCountRpcService.get(key, urseId); 
    if(count>=userLimitCount){ 
        return true; 
    } 
    return false; 
} 

private boolean isLimitIp(String host) { 
    String key = DateFormatUtils.format(new Date(), "yyyyMMdd")+Contents.IP_LIMIT_KEY_SUFFIX; 
    Integer count = requestCountRpcService.get(key, host); 
    if(count>=ipLimitCount){ 
        return true; 
    } 
    return false; 
} 

@Override 
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 
        ModelAndView modelAndView) throws Exception { 
    // TODO Auto-generated method stub 

} 

@Override 
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 
        throws Exception { 
    // TODO Auto-generated method stub 

} 

public Integer getIpLimitCount() { 
    return ipLimitCount; 
} 

public void setIpLimitCount(Integer ipLimitCount) { 
    this.ipLimitCount = ipLimitCount; 
} 

public Integer getUserLimitCount() { 
    return userLimitCount; 
} 

public void setUserLimitCount(Integer userLimitCount) { 
    this.userLimitCount = userLimitCount; 
} 

public Set<String> getMethodSet() { 
    return methodSet; 
} 

public void setMethodSet(Set<String> methodSet) { 
    this.methodSet = methodSet; 
} }

 以上便是redis制作計(jì)數(shù)器的方法,雖然從篇幅上看很復(fù)雜,但是示例代碼非常詳細(xì)且容易理解,如果想了解更多相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI