例子还是之前的例子。仍然是对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. linux shell下16进制 “\uxxxx” unicode to UTF-8中文

    问题出现背景: 项目中有个通过ip获取归属地城市需求,我是直接通过新浪的ip归属查询接口来获取的.我使用的是shell脚本调用 RESULT=$(curl -s 'http://int.dpool.s ...

  2. java基础---->String中replace和replaceAll方法

    这里面我们分析一下replace与replaceAll方法的差异以及原理. replace各个方法的定义 一.replaceFirst方法 public String replaceFirst(Str ...

  3. Timeline Storyteller 现已加入自定义图表库

    前言 下载地址: https://store.office.com/en-us/app.aspx?assetid=WA104381136&sourcecorrid=328f5e2b-e973- ...

  4. proxy_set_header Host 所引发的凶案

    背景介绍:新搭建了一套测试环境.slb为2.2.2.2,由于应用的特殊性,需要走 test.aaa.com.cn 域名,而该域名在老的测试服务器1.1.1.1有两个不能迁移的服务也在使用,故想出对策, ...

  5. 解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)错误

    我调这个bug调了一天多,在网上搜索的检查namespace,package等,都没有错.错误提示是没有找到xml文件,我就纳闷了,为什么找不到呢?后来才发现,原来是resource中奇怪的目录为题, ...

  6. 怎么下载geventwebsocket

    pip install gevent-websocket sudo pip install gevent-websocket

  7. 11.1 vue(2)

    2018-11-1 19:41:00 2018年倒数第二个月! 越努力越幸运!!!永远不要高估自己! python视频块看完了!还有30天吧就结束了! 今天老师讲的vue 主要是看官网文档 贴上连接  ...

  8. vue重要项目的参考

    https://github.com/PanJiaChen/vue-element-admin vue项目参考  重点 https://github.com/opendigg/awesome-gith ...

  9. JavaScript原型、闭包、继承和原型链等等总结

    参考:http://www.cnblogs.com/wangfupeng1988/tag/%E5%8E%9F%E5%9E%8B%E9%93%BE/

  10. 使用 intro.js 库

    使用 render() { const reducer = this.props.testReducer; return ( <React.Fragment> <button dat ...