Spring boot自定义注解拦截器

时间:2021-11-15 20:35:47

    这个是本人关于自定义注解第二篇文章,在很多时候,我们往往通过注解定义自己的拦截器来,做一些过滤的工作,这个时候采用切面和异常捕获处理往往可以达到非常好的预期,下面我示例一个某个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次则抛出异常,防止用户再次访问。