这个是本人关于自定义注解第二篇文章,在很多时候,我们往往通过注解定义自己的拦截器来,做一些过滤的工作,这个时候采用切面和异常捕获处理往往可以达到非常好的预期,下面我示例一个某个IP访问次数限定的例子:
控制器代码:
package com.AnnotationTest;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
//import org.springframework.web.bind.annotation.RestController;
@Controller
public class MyController {
@RequestMapping("/index")
@ResponseBody
public String index(HttpServletRequest request) {
runner.Run(request);
return "this is my index";
}
@Autowired
private TestRunner runner;
}
异常处理器代码:
package com.AnnotationTest;
public class RequestExpection extends RuntimeException{
private static final long serialVersionUID = -9139373255867078110L;
public RequestExpection()
{
super("HTTP请求超出设定的限制");
}
public RequestExpection(String message)
{
super(message);
}
}
访问限制器注解类:
package com.AnnotationTest;
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;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestLimitAnnotation {
public int LimitNum() default 5;
public String IP() default "127.0.0.1";
}
package com.AnnotationTest;
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;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestLimitAnnotation {
public int LimitNum() default 5;
public String IP() default "127.0.0.1";
}
访问切面函数:
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class RequestLimitContract {
private Map<String, Integer> redisTemplate=new HashMap<String,Integer>();
//@Pointcut("within(@com.AnnotationTest.RequestLimitAnnotation *)")
//void cut() {};
@Before("within(@org.springframework.stereotype.Service *) && @annotation(limit)")
public void requestLimit(final JoinPoint joinPoint, RequestLimitAnnotation limit) throws Exception {
try
{
Object[] args = joinPoint.getArgs();
HttpServletRequest req = null;
for(int i = 0; i < args.length; ++i)
{
if(args[i] instanceof HttpServletRequest)
{
req = (HttpServletRequest) args[i];
}
}
if(req == null)
{
throw new Exception("方法中缺失HttpServletRequest参数");
}
String ip = req.getLocalAddr();
if(redisTemplate.get(ip) == null)
{
redisTemplate.put(ip,1);
}else{
redisTemplate.put(ip,redisTemplate.get(ip)+1);
}
int count = redisTemplate.get(ip);
if(count > limit.LimitNum())
{
throw new RequestExpection();
}
}
catch(Exception e)
{
throw e;
}
}
}
注解使用处:
package com.AnnotationTest;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Service;
@Service
public class TestRunner {
@RequestLimitAnnotation(LimitNum=3)
//@SelfAnnotation
public void Run(HttpServletRequest request)
{
System.out.println("MyController is Run");
}
}
上面示例中描述,如果访问次数超过3次则抛出异常,防止用户再次访问。