Este artículo es la segunda parte del envío de mensajes de texto. Aquí presentamos cómo limitar la frecuencia de enviar mensajes de texto al mismo usuario (según el número de teléfono móvil y la IP).
1. Use la sesión
Si se trata de un programa web, también es posible grabar la última vez que se envía en la sesión, pero se puede pasar por alto. Lo más simple es reiniciar directamente el navegador o borrar caché y otros datos que pueden marcar la sesión, por lo que los registros en la sesión se pueden pasar por alto. Aunque muchas personas no son profesionales en las computadoras y no han aprendido. Pero debemos tener en cuenta que la razón para limitar la frecuencia de envío es evitar "bombas SMS", es decir, alguien solicita maliciosamente y con frecuencia enviar mensajes de texto a un número de teléfono móvil. Por lo tanto, esta persona puede entender este conocimiento.
A continuación, utilizamos el límite de datos "global" para enviar frecuencia al mismo usuario. Hagamos un trabajo de "preparación" primero.
2. Definir las interfaces y las clases de entidad
Las clases de entidad que necesitamos son las siguientes:
Smsentity.java
clase pública SMSEntity {ID de entero privado; móvil de cadena privada; IP de cadena privada; tipo entero privado; hora de fecha privada; Captcha de cadena privada; // omitir el método del constructor y los métodos getter y setter}La interfaz de filtrado es la siguiente:
Smsfilter.java
interfaz pública Smsfilter { / *** Inicializar el filtro* / void init () lanza excepción; /*** Determine si se puede enviar el mensaje de texto. * @param smsentity El contenido del mensaje de texto que se enviará * @return si se puede enviar, devolverá verdadero, de lo contrario devolverá el filtro falso */ boolean (smsentity smsentity); / *** destruir el filtro*/ void destruye ();}3. Código principal
Para limitar la frecuencia de envío, debe grabar un determinado número de teléfono móvil (IP) y la hora de la última vez que envió un mensaje de texto. Es muy adecuado para que el mapa se complete. Aquí primero usamos ConcurrentMap para implementarlo:
Frecuenciafilter.java
clase pública FrequencyFilter implementa smsfilter { / *** Enviar intervalo, unidad: MilliseConds* / Private Long SendInterval; Private concurrentMap <String, long> sendAddressMap = new Concurrenthashmap <> (); // algún código inútil omitido @Override public Boolean Filter (smsentity smsEntity) {if (setsendtime (smsentity.getMobile ()) && setSendtime (smsentity.getip ()) {return true; } return false; } /*** Modifique la hora de envío a la hora actual. * Si el intervalo de tiempo del último enviado es mayor que {@link #SendInterval}, establezca el tiempo de envío a la hora actual. De lo contrario, no se modificará contenido. * * @param ID Enviar número de móvil o IP * @return Si la hora de envío se modifica correctamente a la hora actual, devolverá verdadero. De lo contrario, devolverá falso */ private boolean setSendTime (ID de cadena) {Long CurrentTime = System.CurrentTimemillis (); Long Sendtime = sendAddressMap.putifabsent (id, currenttime); if (sendtime == null) {return true; } Long NextCansendTime = sendtime + sendInterval; if (currentTime <nextCansendTime) {return false; } return sendAddressMap.replace (id, sendtime, currenttime); }}Aquí, la lógica principal se implementa en el método setsendtime :
Líneas 25-28: Primero, suponiendo que el usuario envíe un SMS por primera vez, luego la hora actual debe ponerse en el SendAddressMap. Si Putifabsent devuelve nulo, significa que el usuario está enviando un SMS por primera vez, y la hora actual se ha puesto en el mapa, y se puede enviar.
Líneas 30-33: Si el usuario no envía un SMS por primera vez, entonces es necesario determinar si el tiempo y el intervalo actual de enviar el SMS la última vez y el intervalo de tiempo son menores que el intervalo de tiempo de envío. Si es menos que el intervalo de tiempo de envío, entonces no se puede enviar.
Línea 35: si el intervalo de tiempo es lo suficientemente grande, entonces debe intentar establecer el tiempo de envío a la hora actual.
1) Luego puede repetir las líneas 25-35 para asegurarse de que sean absolutamente correctas.
2) También puede pensar directamente que no se puede enviar, porque aunque el tiempo teórico para la "ejecución de las líneas 26-35" puede ser mayor que el "intervalo de envío", ¿cuánto es la probabilidad? Básicamente se puede ignorar.
Este código implementa la limitación de frecuencia, pero si solo hay "en" pero no "fuera", entonces el contenido ocupado por SendAddressMap se hará cada vez más grande hasta que se genere una excepción de MemoryError. A continuación, agregaremos el código para limpiar los datos caducados regularmente.
4. Limpiar datos caducados
Frecuenciafilter.java
/*** Según el código anterior, agregue el siguiente código*/clase pública FrequencyFilter implementa smsfilter {private long cleanMapInterval; Temporizador de temporizador privado = new Timer ("SMS_FREQUENCY_FILTER_CLEAR_DATA_THREAD"); @Override public void init () {timer.schedule (new TimerTask () {@Override public void run () {CleanSendAdDressMap ();}}, CleanMapInterval, CleanMapInterval); } / *** Eliminar todos los datos caducados en SendAddressMap* / private void CleanSendAddressMap () {Long CurrentTime = System.CurrentTimemillis (); Long expiresendtime = currenttime - sendInterval; for (clave de cadena: sendAddressMap.KeySet ()) {long sendtime = sendAddressMap.get (clave); if (sendtime <expiresendtime) {sendAddressMap.remove (clave, sendtime); }}} @Override public void destruye () {timer.cancel (); }}Este programa no es complicado. Inicie un temporizador y ejecute el método CleanSendAdDressMap cada milisegundos de CleanMapInterval para limpiar los datos caducados.
El método CleanSendAdDressMap primero obtiene la hora actual y obtiene un valor de tiempo basado en la hora actual: todos los mensajes de texto se envían después de este tiempo, SMS no se puede volver a enviar nuevamente. Luego elimine todos los pares de valor clave con un valor más pequeño que este valor de tiempo de todo el mapa.
Por supuesto, después de agregar el código anterior, el código inicial tiene otro error: cuando la última línea sendAddressMap.replace (ID, SendTime, CurrentTime) no se ejecuta, no es necesariamente que se hayan reemplazado otros hilos, pero también es posible que el hilo de limpieza haya eliminado los datos. Por lo tanto, necesitamos modificar las últimas líneas del método setsendtime:
Frecuenciafilter.java
privado boolean setSendTime (ID de cadena) {// omitir el código anterior if (sendAddressMap.replace (id, sendtime, currentTime)) {return true; } return sendAddressMap.putifabsent (id, currenttime) == null;}Si el reemplazo es exitoso aquí, regrese verdadero directamente.
Si el reemplazo no tiene éxito, entonces puede ser que otros hilos se hayan reemplazado primero (en el primer caso); También puede ser que hayan sido eliminados por el hilo limpiado (en el segundo caso); Incluso puede ser que hayan eliminado primero el hilo limpio, y otros hilos han insertado valores de tiempo nuevos (en el tercer caso).
En este punto, se completa el código que limita el tiempo de envío. Por supuesto, este programa tiene un pequeño error o "característica":
Si un cliente con IP "192.168.0.1" solicita enviar un mensaje de texto al número de teléfono móvil "12345678900", y luego solicita enviar un mensaje de texto al número de teléfono móvil "12345678900" dentro de SendIinterval en la máquina con IP "192.168.0.2". Entonces el mensaje de texto no se enviará, y la última vez del número de teléfono móvil "12345678900" se establece en la hora actual.
5. Ejemplos de uso
A continuación proporcionamos una capa de servidor para mostrar cómo integrar el código en el artículo anterior y este artículo:
Smsservice.java
clase pública SMSService {SMS privado SMS; Lista privada <SmsFilter> Filtros; Plantilla de propiedades privadas; // Se omiten algunos códigos/*** Enviar código de verificación** @param SmSentity Basic Data para enviar mensajes de texto* @return Si el envío es exitoso, devuelva 0. De lo contrario, devuelva otros valores. */ public int sendCaptcha (smsentity smsentity) {for (smsfilter filtre: filtros) {if (! filter.filter (smsentity)) {return 1; }} if (smsentity.register_type.equals (smsentity.gettype ())) {sendregistersms (smsentity); } else {return 2; } return 0; } / *** Enviar código de verificación de registro** @Param SmSentity Data básico para enviar mensajes de texto* / private void sendregistersms (smsEntity smsEntity) {sms.sendMessage (smsEntity.getMobile (), template.getProperty ("Registro"). Reemplazar ("{Captcha}", smsEntity.getCaptCaptCaptCap. }}Luego, "inyectar" Frecuencia Filter y AsyncSmsImpl en el artículo anterior a través del método establecido.
Lo anterior se trata de este artículo, espero que sea útil para todos aprender la programación de Java.