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两个注 ...
随机推荐
- JDBC driver for MySQL连接提示"The connection property 'zeroDateTimeBehavior' acceptable values are: 'CONVERT_TO_NULL', 'EXCEPTION' or 'ROUND'. The value 'convertToNull' is not acceptable."解决方案
1.使用了8.0以上版本的JDBC driver for MySQL,降回5.x版本. 2.不对JDBC driver for MySQL降级.修改数据库连接字符串,添加serverTimezone属 ...
- java源码中的注解
spring框架源码中充满了注解,如果对注解不是很了解,阅读源码就寸步难行,下面我们来看看annotation.https://blog.csdn.net/briblue/article/detail ...
- B - Tree Recovery
Little Valentine liked playing with binary trees very much. Her favorite game was constructing rando ...
- 从composer上在本地创建一个项目
在想要创建项目的目录下,输入以下代码
- rails 杂记 - erb 中的 link_to 的 ActiveRecord 与 render 中的 partial
路由及路由参数 <%= link_to 'My Blog', {controller: 'articles', demo: "lidsi"}, class: "bl ...
- html5与css 1. web标准及组成
学习目标 1.本专业介绍.HTML相关概念,HTML发展历史 2.WEB标准,W3C/WHATWG/ECMA相关概念 3.相关软件的应用以及站点的创建 4.HTML基本结构和HTML语法 5.HTML ...
- 【Java线程安全】锁
Java都有哪些锁? synchronized 和 reentranlock是最常见的,其中前者又JVM提供实现,后者有专门对应的java.util.concurrent包提供:同时后者功能更加丰富. ...
- ubuntu下openssh升级
因客户漏扫扫描出来openssh及openssl存在漏洞,现升级为官方最新版 这里选择编译安装 去官网下载: openssl-1.0.2o.tar.gz openssh7.7.1 zlib-1.2.1 ...
- python_str 字符串的所有方法
# _Author:huang# date: 2017/11/28 # 字符串 '''print("hello" * 3)print("hello world" ...
- SIM800C 连接服务器
AT+CIPSTART=TCP,域名,端口号 OK 只返回OK,这种情况,说明域名的服务器出错了,OK表示格式正确,但是实际上的TCP是没有连接上的. 测试库服务器出错的时候,就是这种情况 实际连上了 ...