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不能为空!
     */
  • 相关阅读:
    RabbitMQ内存爆出
    SQL Server特殊用法笔记
    C# 实现一个可取消的多线程操作 示例
    js 下载图片与下载文件的方式一样;保存至本地 ASP.NET 方式
    ajaxfileupload.js的简单使用
    Wince 6.0适用 .NET 使用HttpRequest的Post上传文件,服务端的Web API接收Post上传上来的文件 代码
    C# .csv文件转为Excel格式;Excel格式转换为.csv
    将汉字转换为拼音
    检查汉子字符
    初学JQuery笔记
  • 原文地址:https://www.cnblogs.com/xkxf/p/10340965.html
Copyright © 2011-2022 走看看