标签:
最近遇到个问题,一个简单的spring mvc的项目,但是经常被刷子刷,恶意暴力破解通信协议,不断尝试登陆系统,为了方便实时统计请求量和请求返回码的分布情况。最简单的逻辑:不断有人错误登陆,当次数多了,说明有问题了,有人在恶意刷我们的系统。
那么这个问题的一个重要环节就是统计所有请求的返回码,方便离线大数据的同学分析,怎么记录返回码呢?总不能每次都定义一个log,在每个return里进行log.info吧。
returnMap.put("result", "500");
returnMap.put("msg", "数据库查询出错");
errorLogger.error("500,数据库查询出错", e);
return returnMap;
这种方式太恶心了,冗余代码一坨一坨的。
目前本人想到的方式是通过自定义注解和aop来进行统计return的返回码。比如:一天有20%的请求成功,80%是失败,这样也方便我们分析。
做法如下:
自定义注解:在需要统计的方法上加这个统计注解
package com.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author
*/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ControllerMetric {
String description() default "";
AspectReturnTypeEnum type() default AspectReturnTypeEnum.String;
String returnCode() default "result";
}
注解返回值的类型Enum:
package com.annotation;
/**
* @author
* </br>
* 用于在controller层拦截的时候定义的返回类型
* 在ControllerAspect里会对不同的返回类型做不同 的处理。
*/
public enum AspectReturnTypeEnum {
Map,
String,
JSON,
XML
}
定义的AOP切面:
package com.aop;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.annotation.ControllerMetric;
/**
* @author
*/
@Aspect
@Component
public class ControllerAspect {
private static final Logger logger = LoggerFactory.getLogger(ControllerAspect.class);
@Pointcut("@annotation( com.annotation.ControllerMetric)")
public void controllerAspect() {
}
@Around("controllerAspect()&&@annotation(log)")
public Object doCountMetric(ProceedingJoinPoint pjp, ControllerMetric log) throws Throwable {
logger.debug("enter doCountMetric ProceedingJoinPoint " + log.type() + "," + log.returnCode());
Object[] args = pjp.getArgs();
HttpServletRequest req = (HttpServletRequest) args[0];
System.out.println("The request uri for this ProceedingJoinPoint is : " + req.getRequestURI());
Object object = pjp.proceed();
switch (log.type()) {
case Map:
Map ret = (java.util.Map) object;
System.out.println(ret);
break;
default:
}
logger.debug("leave doCountMetric ProceedingJoinPoint");
return object;
}
}
在Controller中用法
@Controller
@RequestMapping("/sdk/mobService/device")
/**
* 可信设备相关的controller
* @author liuxiaoming
*
*/
public class EquipmentController {
private static Logger mobLog = LoggerFactory.getLogger("mobLog");
private static Logger errorLogger = LoggerFactory.getLogger(EquipmentController.class);
@Autowired
EquipmentServiceImpl equipmentServiceImpl;
@Autowired
MobUtil mobUtil;
@RequestMapping("/bd")
@ResponseBody
@ControllerMetric
public Map<String, String> bdDevice(HttpServletRequest request,
HttpServletResponse response) {
Map<String, String> returnMap = new HashMap<String, String>();
return returnMap
}
通过这种形式,所有的返回码都会被拦截,然后可以用一个日志去记录,我这里是直接输出了。
spring项目如何统计所有请求的返回码--项目安全防刷统计
标签:
原文地址:http://my.oschina.net/91jason/blog/525802