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不能为空!
*/
Spring笔记 #02# 利用切面和注解校验方法参数的更多相关文章
- Spring笔记02(3种加载配置文件的方式)
1.不使用Spring的实例: 01.Animal接口对应的代码: package cn.pb.dao; /** * 动物接口 */ public interface Animal { //吃饭 St ...
- Spring——原理解析-利用反射和注解模拟IoC的自动装配
解析Spring的IoC容器基于注解实现的自动装配(自动注入依赖)的原理 1.本文案例 使用注解和反射机制来模拟Spring中IoC的自动装配功能 定义两个注解:@Component,用来标注组件:@ ...
- Spring原理解析-利用反射和注解模拟IoC的自动装配
- Spring+SpringMVC+Mybatis 利用AOP自定义注解实现可配置日志快照记录
http://my.oschina.net/ydsakyclguozi/blog/413822
- Spring中声明式事务的注解@Transactional的参数的总结(REQUIRED和REQUIRES_NEW的与主方法的回滚问题)
一.事务的传播行为1.介绍 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播.例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行.2.属性 事务的传播行为可以由传 ...
- 【VB6笔记-02】从Command中获取链接参数
Public Sub GetParameters() Dim Para As String Para = Command$() gstrUserID = GetCommandPara(Para, ) ...
- Spring笔记02_注解_IOC
目录 Spring笔记02 1. Spring整合连接池 1.1 Spring整合C3P0 1.2 Spring整合DBCP 1.3 最终版 2. 基于注解的IOC配置 2.1 导包 2.2 配置文件 ...
- Spring 笔记1
1.在java开发领域,Spring相对于EJB来说是一种轻量级的,非侵入性的Java开发框架,曾经有两本很畅销的书<Expert one-on-one J2EE Design and Deve ...
- Spring中的@Valid 和 @Validated注解你用对了吗
1.概述 本文我们将重点介绍Spring中 @Valid和@Validated注解的区别 . 验证用户输入是否正确是我们应用程序中的常见功能.Spring提供了@Valid和@Validated两个注 ...
随机推荐
- 离屏Canvas — 使用Web Worker提高你的Canvas运行速度
离屏Canvas — 使用Web Worker提高你的Canvas运行速度 原文链接: developers.google.com 现在因为有了离屏Canvas,你可以不用在你的主线程中绘制图像了! ...
- 深入理解 Java 虚拟机之学习笔记(3)
垃圾回收(Garbage Collection,GC ),GC的历史其实比Java久远,1960年诞生与MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.当Lisp还在胚胎时期时,人们 ...
- Logistic 最大熵 朴素贝叶斯 HMM MEMM CRF 几个模型的总结
朴素贝叶斯(NB) , 最大熵(MaxEnt) (逻辑回归, LR), 因马尔科夫模型(HMM), 最大熵马尔科夫模型(MEMM), 条件随机场(CRF) 这几个模型之间有千丝万缕的联系,本文首先会 ...
- 用TreeSet生成不重复自动排序随机数组
随机数组就是在指定长度的数组中用随机数字为每个元素赋值,常用于不确定数值的环境,如拼图游戏需要随机数组来打乱图片顺序.可是同时也存在问题,就是随机数的重复问题,这个问题常常被忽略. TreeSet类的 ...
- ajaxFileUpload只能上传一次,和上传同名图片不能上传等bug问题
createUploadForm: function (id, fileElementId) { //create form var formId = 'jUploadForm' + id; var ...
- Gym 101981I - Magic Potion - [最大流][2018-2019 ACM-ICPC Asia Nanjing Regional Contest Problem I]
题目链接:http://codeforces.com/gym/101981/attachments There are n heroes and m monsters living in an isl ...
- Compile pam with pam_cracklib.so
pam_cracklib.so is dependent on libcrack.so. Configure command will search libcrack.so. If it didn't ...
- Spring Enable* 注解
Spring提供了一系列以Enable开头的注解,这些注解本质上是激活Spring的某些管理功能.比如,EnableWebMvc. 这个注解引入了MVC框架在Spring 应用中需要用到的所有bean ...
- [Day10]继承、抽象类
1.继承:在一个现有类的基础上去构建一个新的类,构建出来的新类被称为子类,现有类被称作父类,子类会自动拥有父类所有可继承的属性和方法. 2.继承的格式 : class 子类 extends 父类{} ...
- 与HTTP关系密切的三个协议:IP,TCP,DNS
IP(网际协议): 位于网络层 通常易混淆的是“IP”和“IP地址”,单独讲“IP”是指一种协议名称 IP协议的作用是将各种数据包传送给对方.而要保证确实传送到对方那里,则需要满足各类条件. 其中两个 ...