zoukankan      html  css  js  c++  java
  • Spring笔记 #02# 利用切面和注解校验方法参数

    例子还是之前的例子。仍然是对mage进行法术攻击时的咒语进行校验,不过略微提高了扩展性。

    应用示例

    1、在.properties文件中定义参数格式(正则):

    sp1=^\D*hello\D*$
    sp2=^\D*world\D*$

    2、对需要检查格式的方法参数进行注解,注解中传入的参数需要与.properties文件中的定义相对应:

    package sample.spring.iocbasis.hero;
    
    import sample.spring.iocbasis.annotation.CheckFormat;
    
    public interface Mage {
        
        void attack(@CheckFormat("sp1") String sp1, @CheckFormat("sp2")String sp2);
    }
    package sample.spring.iocbasis.annotation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.PARAMETER)
    public @interface CheckFormat {
        String value();
    }
    注解.java

    3、定义切面:

    package sample.spring.iocbasis.weapon;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.reflect.MethodSignature;
    import sample.spring.iocbasis.annotation.CheckFormat;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.Parameter;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    import java.util.regex.Pattern;
    
    public class MagicBook implements Weapon {
    
        private static final Logger LOGGER = LogManager.getLogger();
    
        private static int count = 0;
    
        private int no = ++count;
    
        private static Map<String, Pattern> map = new HashMap<>();
    
        static {
            // 把.properties文件里的键值对读到内存里
            Properties prop = new Properties();
            String filename = "\easy-validator.properties";
            try (InputStream input = MagicBook.class.getClassLoader().getResourceAsStream(filename)){
                if (input == null) {
                    throw new RuntimeException("Sorry, unable to find " + filename);
                }
                prop.load(input);
                Enumeration<?> e = prop.propertyNames();
                while (e.hasMoreElements()) {
                    String key = (String) e.nextElement();
                    String value = prop.getProperty(key);
                    map.put(key, Pattern.compile(value));
                }
            } catch (IOException e) {
                throw new RuntimeException("An exception occurred while reading " + filename, e);
            }
        }
    
        public void magicLimit(ProceedingJoinPoint jp) {
            try {
                LOGGER.info("{}试图发动一次魔法攻击,正在检查咒语格式 ...", jp.getThis());
                // 获取参数对象以便获得注解值
                MethodSignature signature = (MethodSignature) jp.getSignature();
                Parameter[] parameters = signature.getMethod().getParameters();
                // 获取参数值
                Object[] args = jp.getArgs();
                // 逐个参数进行判断
                for (int i = 0; i != args.length; ++i) {
                    if (args[i] instanceof String) {
                        // 获取参数对应格式名(默认即为参数名)
                        String formatName = parameters[i].getAnnotation(CheckFormat.class).value();
                        String arg = (String) args[i];
                        // 非空检查
                        if (StringUtils.isBlank(arg)) {
                            LOGGER.info("{}不能为空!", formatName);
                            return;
                        } else {
                            Pattern pattern = map.get(formatName);
                            // 程序员要确保格式已经定义
                            if (pattern == null) throw new RuntimeException(formatName + "格式未定义");
                            // 格式检查
                            if (!pattern.matcher(arg).matches()) {
                                LOGGER.info("{}格式不正确!", formatName);
                                return;
                            }
                        }
                    }
                }
                // 所有字符串检查通过才放行
                jp.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    
        @Override
        public void attack() {
    
        }
    
        @Override
        public String toString() {
            return "MagicBook{" +
                    "no=" + no +
                    '}';
        }
    }

    4、在IOC容器的配置文件中应用切面:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <bean id="magicBook" class="sample.spring.iocbasis.weapon.MagicBook"/>
    
        <aop:config>
            <aop:aspect ref="magicBook">
                <aop:pointcut id="mageAttack"
                              expression="execution(* sample.spring.iocbasis.hero.Mage.*(..))" />
                <aop:around pointcut-ref="mageAttack" method="magicLimit" />
            </aop:aspect>
        </aop:config>
    </beans>

    5、测试切面:

    package sample.spring.iocbasis;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import sample.spring.iocbasis.hero.Mage;
    
    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("\spring\config.xml");
            Mage mage = context.getBean("mage", Mage.class);
            mage.attack("hello", "world.");
            mage.attack("hlo", "worl.");
            mage.attack("hello", "        ");
        }
    }
    /*
    output=
    MageImpl{no=1}试图发动一次魔法攻击,正在检查咒语格式 ...
    MageImpl{no=1}用MagicBook{no=1}发起了一次攻击
    MageImpl{no=1}试图发动一次魔法攻击,正在检查咒语格式 ...
    sp1格式不正确!
    MageImpl{no=1}试图发动一次魔法攻击,正在检查咒语格式 ...
    sp2不能为空!
     */
  • 相关阅读:
    HDU 1874 畅通工程续(dijkstra)
    HDU 2112 HDU Today (map函数,dijkstra最短路径)
    HDU 2680 Choose the best route(dijkstra)
    HDU 2066 一个人的旅行(最短路径,dijkstra)
    关于测评机,编译器,我有些话想说
    测评机的优化问题 时间控制
    CF Round410 D. Mike and distribution
    数字三角形2 (取模)
    CF Round410 C. Mike and gcd problem
    CF Round 423 D. High Load 星图(最优最简构建)
  • 原文地址:https://www.cnblogs.com/xkxf/p/10340965.html
Copyright © 2011-2022 走看看