cxf+spring开发(三)--- 限制固定Ip地址对接口的访问次数

需求:在cxf+spring环境下,针对某个接口,限制Ip地址对其访问次数,超过一定访问次数后抛出异常。

1.此Ip地址是经过拦截器被允许访问的;

2.同一IP地址对接口的访问次数不能超过两次。

备注:有关web.xml,服务器端、客户端配置文件,数据库工具类,简单输出示例,请参考前面写过的cxf+spring开发(一)和cxf+spring开发(二)

 

一、自定义超过最大访问次数异常

/**
 * 自定义超出最大访问限制异常
 *
 */
public class OutOfAccNumException extends Exception{

	public OutOfAccNumException(String msg) {
		super(msg);
	}
	
}

​

 

 

二、连接池处理

         operatelock方法的参数有两个,第一个可传入Ip地址,第二个是操作类型,进入接口中方法就加一,方法执行结束就减一。定义一个hashmap变量统计同一Ip地址的访问次数,超过最大限制就抛出自定义异常。

import java.util.HashMap;
import java.util.Map;

/**
 * 连接池处理
 *
 */
public class ALock {
    
    public static String COUNT_TYPE_ADD = "COUNT_ADD";//访问数加一
    public static String COUNT_TYPE_SUB = "COUNT_SUB";//访问数减一
    private static int maxNum = 2;//最大允许访问数
    private static Map<String, Integer> cateCount = new HashMap<String, Integer>();
    
    /**
     * 线程处理
     * @param cateAcc
     *            访问名
     * @param countType
     *            OPT_ADD/OPT_SUB
     * @throws OutOfAccNumException
     *            访问次数超过限制
     */
    public static synchronized void operatelock(String cateAcc, String countType)
            throws OutOfAccNumException{
        int currentCount = 0;
        
        if (cateCount.get(cateAcc) != null) {
//            System.out.println(cateCount.get(cateAcc));
            currentCount = Integer.parseInt(cateCount.get(cateAcc).toString());
//            System.out.println("执行map.get操作:当前访问数:" + currentCount);
//            System.out.println(Integer.parseInt(cateAcc));
//            System.out.println(Integer.parseInt("9"));
        }
        if (COUNT_TYPE_ADD.equals(countType)) {
            if (currentCount >= maxNum) {
                System.out.println("已达最大访问数:" + currentCount);
                System.out.println(Thread.currentThread().getName());
                cateCount.put(cateAcc, Integer.valueOf(++currentCount));
                throw new OutOfAccNumException("已达最大访问数," + Thread.currentThread().getName()
                        + "拒绝继续访问");
    
            }else {
                currentCount++;
                System.out.println("执行add操作:当前访问数:" + currentCount);
                cateCount.put(cateAcc, Integer.valueOf(currentCount));  
            }
                
        }else if (COUNT_TYPE_SUB.equals(countType)) {
                currentCount--;
                System.out.println("执行sub操作:当前访问数:" + currentCount);
                cateCount.put(cateAcc, Integer.valueOf(currentCount));                            
            
        }
        
    }

}

​

 

二、获取Ip地址

        此处不同于上一篇博文Ip拦截器中的Ip获取方式,直接获取客户端请求的Ip地址,方便后续的传参。

import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

import org.apache.cxf.jaxws.context.WebServiceContextImpl;

/**
 * 获取Ip地址
 *
 */
public class GetIpAddr {

	public static String getWSRemoteIP()
    {
    	WebServiceContext wscontext = new WebServiceContextImpl();
    	MessageContext mc = wscontext.getMessageContext();

    	HttpServletRequest request = (HttpServletRequest)(mc.get(MessageContext.SERVLET_REQUEST));

    	String remortAddress = request.getRemoteAddr();
    	
    	if("127.0.0.1".equals(remortAddress)) {
	    	try {
	    		remortAddress = InetAddress.getLocalHost().getHostAddress();
			} catch (UnknownHostException e) {
				return "";
			}

        }
    	return remortAddress;
    }
}


​


三、定义限制访问次数的抽象类

/**
 * 定义抽象类
 *
 */
public abstract class UseOperFactory {

//	private String accName;
	public static String COUNT_TYPE_ADD = "COUNT_ADD";//访问数加一
	public static String COUNT_TYPE_SUB = "COUNT_SUB";//访问数减一
	private String s;
	
	public UseOperFactory(String string) {
		this.s = string;
	}
	
	public void useLock() {
		
		try {
			System.out.println("现在正在访问的Ip是:"+ GetIpAddr.getWSRemoteIP());
			ALock.operatelock(GetIpAddr.getWSRemoteIP(), COUNT_TYPE_ADD);
//		    System.out.println("Hello," + s);
			doWork();
			Thread.sleep(1000*10);
		} catch (OutOfAccNumException e1) {
			System.err.println(e1.getMessage());
			e1.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			//释放资源
			try {
				ALock.operatelock(GetIpAddr.getWSRemoteIP(), COUNT_TYPE_SUB);
			} catch (OutOfAccNumException e) {
				e.printStackTrace();
			}				
		}
	}
	
	public abstract void doWork();
}

​

 

四、修改接口实现类(接口见cxf+spring开发(一))

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import javax.jws.WebService;

/**
 * 实现接口
 */


@WebService(endpointInterface = "com.yolanda.cxfTest.AInterface")
public class AImpl implements AInterface {
    public static String COUNT_TYPE_ADD = "COUNT_ADD";//访问数加一
    public static String COUNT_TYPE_SUB = "COUNT_SUB";//访问数减一
    
    public void print(String s) {
        UseOperFactory uof = new UseOperFactory(s) {
            
            public void doWork() {
                System.out.println("Hello," + s);
                
            }
        };
        
        uof.useLock();
    }

        

    public String printAll(List<AEntity> aEntities) {

        String aString = "list:\n";
        for (AEntity aEntity : aEntities) {
            aString += "name:" + aEntity.getName() + "," + "age:"
                    + aEntity.getAge() + "\n";
            // count.decrementAndGet();
        }
        return aString;
    }

}

 

 

五、客户端测试文件

         创建固定线程数量的线程池进行测试。

import java.util.List;
import javax.jws.WebService;

/**
 * 实现接口
 */


@WebService(endpointInterface = "com.yolanda.cxfTest.AInterface")
public class AImpl implements AInterface {
	public static String COUNT_TYPE_ADD = "COUNT_ADD";//访问数加一
	public static String COUNT_TYPE_SUB = "COUNT_SUB";//访问数减一
	
	public void print(String s) {
		UseOperFactory uof = new UseOperFactory(s) {
			
			public void doWork() {
				System.out.println("Hello," + s);
				
			}
		};
		
		uof.useLock();
	}

		

	public String printAll(List<AEntity> aEntities) {

		String aString = "list:\n";
		for (AEntity aEntity : aEntities) {
			aString += "name:" + aEntity.getName() + "," + "age:"
					+ aEntity.getAge() + "\n";
			// count.decrementAndGet();
		}
		return aString;
	}

}

 

 

 

 

 

 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值