注記インタフェースべき乗等の重量防止を実現

20785 ワード

一、需要

二、ソースコード解析
    spring AOP、      、spring EL   、redis   、java     

1.注記
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NoReSubmit {


    /**
     *           ( )
     *
     * @return
     */
    int waiting() default 3;


    /**
     *      ,        ,            
     *
     * @return
     */
    int error() default 1006;


    /**
     *     ,     redis key  
     *
     * @return
     */
    String prefix() default "noReSubmit";

    /**
     *         
     *
     * @return
     */
    String[] keys();

}

2.AOP
@Aspect
@Component
public class NoReSubmitAspect {

    @Resource
    private ExtendJedisService extendJedisService;

    /**
     *    
     */
    @Pointcut("@annotation(com.cxp.common.annotation.NoReSubmit)")
    public void pointcut() {
    }

    /**
     *      
     *
     * @param joinPoint
     */
    @Before("pointcut()")
    public void joinPoint(JoinPoint joinPoint) {
        //         
        Object[] args = joinPoint.getArgs();
        //       
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        //     
        Method method = methodSignature.getMethod();
        //      
        String methodName = method.getName();
        //       
        Parameter[] parameters = method.getParameters();
        //       
        NoReSubmit noReSubmit = method.getAnnotation(NoReSubmit.class);
        //         
        int waiting = noReSubmit.waiting();
        int error = noReSubmit.error();
        String prefix = noReSubmit.prefix();
        String[] keys = noReSubmit.keys();
        //    springEL        
        ExpressionParser parser = new SpelExpressionParser();
        //           
        EvaluationContext context = new StandardEvaluationContext();
        //                   
        for (int i = 0; i < parameters.length; i++) {
            if (args[i] != null) {
            	//         
                context.setVariable(parameters[i].getName(), args[i]);
            }
        }
        //     key    ,   key
        StringBuffer noReSubmitKey = new StringBuffer(prefix + ":" + methodName);
        for (int i = 0; i < keys.length; i++) {
        	//     
            Expression expression = parser.parseExpression(keys[i]);
            noReSubmitKey.append(":" + expression.getValue(context));
        }
        //   redis      ,     
        boolean bool = extendJedisService.setnx(noReSubmitKey.toString(), System.currentTimeMillis() + "", waiting);
        if (!bool) {
            throw new BusinessException(ErrorCode.getErrorCode(error));
        }
    }
}

3.方法使用
	@NoReSubmit(prefix = "prepare", keys = {"#TopicPO.interactBO.interactId", "#TopicPO.userBO.userId"}, waiting = 3 * 60 * 60)
    public ResultData prepare(@RequestBody TopicPO topicPO) {
        log.info("    TopicPO={}", TopicPO);
        return new ResultData();
    }

keyの定義はspring EL式の規則に従い、解析が便利で、springの@Cacheable注釈を参照することができ、spring EL解析を使用することもできます.三、踏み込み穴1.json解析でkeyを解析したい(以前はkey定義がこのフォーマットではなかった)と使い始めたが、解析方法を自分で書くのは面倒で効率が悪い、最後にグループ内の長兄が@Cacheable実装案を推薦し、後にソースコードを見るとspring EL実装、最終的にこの方式を採用した.もう一つのjava 8の問題は、java 8がパラメータ名を取得し、通常は何を書いているのか、私のようにtopicPOですが、反射したダイナミックエージェントから出てくるパラメータ名はarg 0、arg 1...、だから私のここ:
context.setVariable(parameters[i].getName(), args[i]);

入れたsetの変数名はarg 0で、解析中に注釈に書いてあるkeyが見つかりません.ローカルideaはデフォルトで書き込みメソッド名にコンパイルされ、環境にパブリッシュされても有効ではありません.解决方法:(私が使っている第1種)1.pomファイルに注釈を付けてその構成、コンパイルすればOK、
		<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF8</encoding>
                    <!-- java8              ,     arg0,arg1... -->
                    <compilerArgument>-parameters</compilerArgument>
                </configuration>
            </plugin>

2.springで持参した取得方法名
//       
    LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();

3.コンパイルにjavac-parametersパラメータを加えると、ローカルでも環境でもjenkins配置四、ネット上で注釈を通じて重い問題を解決することがあります.参考にしたことがありますが、私の既存業務にはあまり適切ではありません.だから、自分で1つ作りましょう.多くの知識を学びましょう.aopが深まり、ダイナミックエージェントが深まり、spring ELが勉強します.その後,多くの解析でspring ELが用いられていることが分かった.