이 기사는 문자 메시지를 보내는 두 번째 부분입니다. 여기에서 문자 메시지를 동일한 사용자에게 (휴대 전화 번호 및 IP에 따라) 보내는 빈도를 제한하는 방법을 소개합니다.
1. 세션을 사용하십시오
웹 프로그램 인 경우 세션에서 마지막으로 전송 된 시간을 기록 할 수도 있지만 우회 할 수 있습니다. 가장 간단한 것은 브라우저 또는 클리어 캐시 및 세션을 표시 할 수있는 기타 데이터를 직접 다시 시작하여 세션의 레코드를 우회 할 수 있습니다. 많은 사람들이 컴퓨터에서 전문가가 아니지만 이것을 배우지 못했습니다. 그러나 보내는 주파수를 제한하는 이유는 "SMS 폭탄", 즉 누군가 문자 메시지를 휴대 전화 번호로 보낼 수 있고 자주 자주 요청하는 것입니다. 그러므로이 사람은이 지식을 이해할 수 있습니다.
다음으로 "글로벌"데이터 제한을 사용하여 동일한 사용자에게 주파수를 전송합니다. "준비"를 먼저 해보자.
2. 인터페이스 및 엔티티 클래스를 정의하십시오
우리가 필요한 엔티티 클래스는 다음과 같습니다.
smsentity.java
공개 수업 smsentity {개인 정수 ID; 개인 문자열 모바일; 개인 문자열 IP; 개인 정수 유형; 개인 날짜 시간; 개인 문자열 CARTCHA; // 생성자 메소드를 생략하고 getter and setter 메소드}필터링 인터페이스는 다음과 같습니다.
smsfilter.java
public interface smsfilter { / *** 필터 초기화* / void init ()는 예외를 던집니다. /*** 문자 메시지를 보낼 수 있는지 확인하십시오. * @param smsentity 전송 될 문자 메시지의 내용 * @return을 보내면 보내면 true를 반환합니다. 그렇지 않으면 false */ boolean 필터 (smsentity smsentity); / *** 필터 파괴*/ void destroy ();}3. 메인 코드
전송 빈도를 제한하려면 특정 휴대 전화 번호 (IP)와 문자 메시지를 마지막으로 보낸 시간을 기록해야합니다. 지도가 완료되기에 매우 적합합니다. 여기서는 먼저 ConcurrentMap을 사용하여 구현합니다.
주파수 필터 .java
공개 클래스 주파수 필터는 smsfilter { / *** 송신 간격, 단위 : milliseconds* / private long sendinterval; private concurrentMap <string, long> sendAddressMap = new ConcurrEthashMap <> (); // 일부 쓸모없는 코드 생략 @override public boolean filter (smsentity smsentity) {if (setsendtime (smsentity.getMobile ()) && setSendTime (smsentity.getIP ())) {return true; } false를 반환합니다. } /*** 보내는 시간을 현재 시간으로 수정합니다. * 마지막 전송의 시간 간격이 {@link #sendinterval}보다 큰 경우 보내는 시간을 현재 시간으로 설정하십시오. 그렇지 않으면 내용이 수정되지 않습니다. * * @param id 전송 시간이 현재 시간으로 성공적으로 수정되면 휴대 전화 번호 또는 ip * @return을 보내면 true가 반환됩니다. 그렇지 않으면 false */ private boolean setsendtime (string id) {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); }}여기서 주요 논리는 SetSendTime 메소드 에서 구현됩니다.
25-28 행 : 먼저, 사용자가 처음으로 SMS를 보낸다고 가정하면 현재 시간을 SendAdDressMap에 넣어야합니다. Putifabsent가 NULL을 반환하면 사용자가 실제로 SMS를 처음으로 보내고 현재 시간을지도에 넣고 보낼 수 있음을 의미합니다.
30-33 행 : 사용자가 처음으로 SMS를 보내지 않는 경우 SMS를 전송하는 시간과 현재 간격이 전송 시간 간격보다 작습니다. 전송 시간 간격보다 적은 경우 보낼 수 없습니다.
35 행 : 시간 간격이 충분히 크면 전송 시간을 현재 시간으로 설정해야합니다.
1) 그런 다음 25-35 행을 반복하여 절대적으로 정확한지 확인할 수 있습니다.
2) "26-35 행의 실행"에 대한 이론적 시간은 "보내기 간격"보다 클 수 있지만 확률은 얼마입니까? 기본적으로 무시할 수 있습니다.
이 코드는 주파수 제한을 구현하지만 "in"이지만 "out"만 있으면 SendAddressMap이 차지하는 내용이 OutOfMemoryError 예외가 생성 될 때까지 점점 커지고 커집니다. 다음으로 만료 된 데이터를 정기적으로 정리하기 위해 코드를 추가합니다.
4. 만료 된 데이터 정리
주파수 필터 .java
/*** 위의 코드를 기반으로 다음 코드를 추가하십시오*/public class frequencyfilter는 smsfilter {private long cleanmapinterval; 개인 타이머 타이머 = 새 타이머 ( "SMS_FREQUENCY_FILTER_CLEAR_DATA_THREAD"); @override public void init () {timer.schedule (new Timertask () {@override public void run () {cleansendaddressmap ();}}, cleanmapinterval, cleanmapinterval); } / *** sendAddressmap* / private void cleansendAddressMap () {long currentTime = System.CurrentTimeMillis (); Long ExpireSendTime = CurrentTime -SendInterVal; for (문자열 키 : sendAddressMap.keyset ()) {long sendtime = sendAddressMap.get (key); if (sendtime <expiresendTime) {sendAddressMap.remove (키, SendTime); }}} @override public void destrove () {timer.cancel (); }}이 프로그램은 복잡하지 않습니다. 타이머를 시작하고 CleansendAddressMap 메서드를 실행하여 CleanMapinterval의 밀리 초마다 만료 된 데이터를 정리하십시오.
CleanSendAddressMap 메소드는 먼저 현재 시간을 가져오고 현재 시간을 기준으로 시간 값을 얻습니다.이 시간이 지나면 모든 문자 메시지가 전송되면 SMS는 다시 보낼 수 없습니다. 그런 다음 전체 맵 에서이 시간 값보다 작은 값으로 모든 키 값 쌍을 삭제하십시오.
물론 위의 코드를 추가 한 후 초기 코드에는 또 다른 버그가 있습니다. 마지막 줄 SendAddressMap.replace (ID, SendTime, CurrentTime)가 실행되지 않으면 반드시 다른 스레드가 대체되었을 필요는 없지만 청소 스레드가 데이터를 삭제했을 수도 있습니다. 따라서 SetSendTime 메서드의 마지막 몇 줄을 수정해야합니다.
주파수 필터 .java
private boolean setsendtime (string id) {// 이전 코드를 생략하면 if (sendaddressmap.replace (id, sendtime, currenttime)) {return true; } return sendAddressmap.putifabsent (id, currenttime) == null;}교체가 여기에서 성공하면 True를 직접 반환하십시오.
교체가 성공하지 못하면 다른 스레드가 먼저 교체되었을 수 있습니다 (첫 번째 경우). 또한 청소 된 실에 의해 삭제되었을 수도 있습니다 (두 번째 경우). 청소 된 스레드에 의해 먼저 삭제되었을 수도 있고 다른 스레드는 새로운 시간 값을 삽입했을 수도 있습니다 (세 번째 경우).
이 시점에서 보내는 시간을 제한하는 코드가 완료됩니다. 물론이 프로그램에는 작은 버그 또는 "기능"이 있습니다.
"192.168.0.1"이있는 고객이 "12345678900"휴대 전화 번호로 문자 메시지를 보내라고 요청한 다음 "192.168.0.2"IP가있는 컴퓨터의 SendInterval 내에서 "12345678900"에 문자 메시지를 보내도록 요청합니다. 그런 다음 문자 메시지가 전송되지 않으며 휴대 전화 번호의 마지막 시간 "12345678900"이 현재 시간으로 설정됩니다.
5. 사용의 예
아래는 이전 기사 와이 기사에서 코드를 통합하는 방법을 보여주는 서버 계층을 제공합니다.
smsservice.java
공개 수업 smsservice {private SMS SMS; 개인 목록 <SMSFilter> 필터; 개인 속성 템플릿; // 일부 코드는 생략됩니다/*** 검증 코드 보내기** @param smsentity 문자 메시지를 보내기위한 기본 데이터* @return 제출이 성공하면 0을 반환하십시오. 그렇지 않으면 다른 값을 반환합니다. */ public int sendcaptcha (smsentity smsentity) {for (smsfilter 필터 : 필터) {if (! filter.filter (smsentity)) {return 1; }} if (smsentity.register_type.equals (smsentity.getType ())) {sendRegistersms (smsentity); } else {return 2; } 반환 0; } / *** 문자 메시지 보내기위한 등록 검증 코드 보내기** @param smsentity 기본 데이터* / private void sendRegistersms (smsentity smsentity) {sms.sendMessage (smsentity.getMobile (), template.getProperty ( "register"). smsentity.getcaptcha ( "{captcha}"); }}그런 다음 이전 기사에서 설정 방법을 통해 "주파수 필터 및 Asyncsmsimpl을"Inject ".
위의 내용은이 기사에 관한 모든 것입니다. 모든 사람들이 Java 프로그래밍을 배우는 것이 도움이되기를 바랍니다.