例子还是之前的例子。仍然是对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不能为空!
*/

Spring笔记 #02# 利用切面和注解校验方法参数的更多相关文章

  1. Spring笔记02(3种加载配置文件的方式)

    1.不使用Spring的实例: 01.Animal接口对应的代码: package cn.pb.dao; /** * 动物接口 */ public interface Animal { //吃饭 St ...

  2. Spring——原理解析-利用反射和注解模拟IoC的自动装配

    解析Spring的IoC容器基于注解实现的自动装配(自动注入依赖)的原理 1.本文案例 使用注解和反射机制来模拟Spring中IoC的自动装配功能 定义两个注解:@Component,用来标注组件:@ ...

  3. Spring原理解析-利用反射和注解模拟IoC的自动装配

  4. Spring+SpringMVC+Mybatis 利用AOP自定义注解实现可配置日志快照记录

    http://my.oschina.net/ydsakyclguozi/blog/413822

  5. Spring中声明式事务的注解@Transactional的参数的总结(REQUIRED和REQUIRES_NEW的与主方法的回滚问题)

    一.事务的传播行为1.介绍 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播.例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行.2.属性 事务的传播行为可以由传 ...

  6. 【VB6笔记-02】从Command中获取链接参数

    Public Sub GetParameters() Dim Para As String Para = Command$() gstrUserID = GetCommandPara(Para, ) ...

  7. Spring笔记02_注解_IOC

    目录 Spring笔记02 1. Spring整合连接池 1.1 Spring整合C3P0 1.2 Spring整合DBCP 1.3 最终版 2. 基于注解的IOC配置 2.1 导包 2.2 配置文件 ...

  8. Spring 笔记1

    1.在java开发领域,Spring相对于EJB来说是一种轻量级的,非侵入性的Java开发框架,曾经有两本很畅销的书<Expert one-on-one J2EE Design and Deve ...

  9. Spring中的@Valid 和 @Validated注解你用对了吗

    1.概述 本文我们将重点介绍Spring中 @Valid和@Validated注解的区别 . 验证用户输入是否正确是我们应用程序中的常见功能.Spring提供了@Valid和@Validated两个注 ...

随机推荐

  1. 如何用AJax提交name[]数组?

    https://www.cnblogs.com/junzilan/p/5424120.html

  2. Xcode - 因为证书问题经常报的那些错

    1.确认下证书是不是开发证书,如果是发布证书就会出现这样的提示. 2.证书失效了,去开发者中心重新生成一个. 3.包标识符不与描述文件包含的包标识符不一致,按照它的提示换一下就好了,最好不要点 Fix ...

  3. 前端页面展示MySQL数据并实现前后端互动

    前端页面使用H-ui框架  后端使用flask框架  数据库使用mysql  连接数据库通过pymysql实现 前端代码如下 <html lang="en"> < ...

  4. error_match问题

    当nginx的sendfile处于on的情况下,在docker的环境下修改js文件会出现error_match的问题,应该要在nginx的配置中把sendfile设为off

  5. 14:CSS3 渐变(gradient)与 过度(transition)、CSS3 的2D动画

    14:CSS3 渐变 CSS3 渐变(gradient)可以让你在两个或多个指定的颜色之间显示平稳的过渡. 以前,你必须使用图像来实现这些效果,现在通过使用 CSS3 的渐变(gradients)即可 ...

  6. 补充:MySQL修改表

  7. JavaScript基础知识(DOM)

    获取元素的方法 要操作谁,就要先获取谁: 获取元素 1.document.getElementById:通过ID名来获取元素 兼容性: 在IE8以下,会默认把name属性当做id来获取: docume ...

  8. vivado/FPGA 使用小纪

    1.使用FPGA做为外部控制器的总线译码时,将总线时钟接在全局时钟脚上(MRCC),就算接在了局部时钟(SRCC)上,也要通过BUFG转为全局时钟走线,否则会因为local clk到各部分的时延较大引 ...

  9. 【RabbitMQ】工作模式介绍

    一.前言 之前,笔者写过< CentOS 7.2 安装 RabbitMQ> 这篇文章,今天整理一下 RabbitMQ 相关的笔记便于以后复习. 二.模式介绍 在 RabbitMQ 官网上提 ...

  10. iOS 微信打开第三方应用(Universal Links 和 URL Schemes)

    一.前言 项目中时常有这种需求, 是通过链接跳转到应用内部,现在iOS主流的方案有两个 Schema: 常用在于一个应用跳转到另一个应用内部,属于应用间的跳转.当然ios9以下,网页可以通过schem ...