我们有这样一个要求,在设置Bean属性的时候,要检查设置内容是否含有fuck和shit这样的脏话,如果有的话,则进行过滤(使用一个简单的算法把脏话变成新的字符),如果没有,则正常设置,如果使用传统方法,首先需要定义一个脏话过滤接口,然后实现这个接口,再设计一个工程类返回这个实现类的实例,在每一个set方法中都调用检查方法,这样不仅会增加代码量,而且给维护带来了噩梦般的体验,我们如果使用AOP的思想进行设计,就显得代码很简洁,很干净
本文模拟一个编写Blog文章的场景
BlogPositng 这是一个Blog Entity 的接口,其中设置blog body的方法
package
ch7.BlogFilter;
public interface BlogPosting ... {
public String getBody();
public void setBody(String body);
}
public interface BlogPosting ... {
public String getBody();
public void setBody(String body);
}
BlogPostingImpl是BlogPosting接口的实现类,也就是我们的domain对象
package
ch7.BlogFilter;
public class BlogPostingImpl implements BlogPosting ... {
private String body;
public String getBody() ...{
return this.body;
}
public void setBody(String body) ...{
this.body=body;
}
}
public class BlogPostingImpl implements BlogPosting ... {
private String body;
public String getBody() ...{
return this.body;
}
public void setBody(String body) ...{
this.body=body;
}
}
BlogManager是blog管理类,通过这个类的set方法设置blog body,这个类也是我们需要通知的类
package
ch7.BlogFilter;
public class BlogManager ... {
private BlogPosting blogPosting;
public BlogPosting getBlogPosting() ...{
return blogPosting;
}
public void setBlogPosting(BlogPosting blogPosting) ...{
this.blogPosting = blogPosting;
}
}
public class BlogManager ... {
private BlogPosting blogPosting;
public BlogPosting getBlogPosting() ...{
return blogPosting;
}
public void setBlogPosting(BlogPosting blogPosting) ...{
this.blogPosting = blogPosting;
}
}
OnscenityFilter是脏话过滤类的接口
package
ch7.BlogFilter;
public interface OnscenityFilter ... {
//判断是否有脏话存在
public boolean containObscenities(String data);
//把脏话进行数据替换
public String obfuscateObscenities(String data);
}
public interface OnscenityFilter ... {
//判断是否有脏话存在
public boolean containObscenities(String data);
//把脏话进行数据替换
public String obfuscateObscenities(String data);
}
ListBasedObscenityFilter是OnscenityFilter的实现类
package
ch7.BlogFilter;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class ListBasedObscenityFilter implements OnscenityFilter ... {
private List obscenitites=null; //脏话列表,由Spring注入,写在配置文件中
private Pattern obsecenityPattern=null; //脏话匹配的正则表达式
public List getObscenitites() ...{
return obscenitites;
}
public void setObscenitites(List obscenitites) ...{
this.obscenitites = obscenitites;
buildRegex();
}
//编译正则表达式
private void buildRegex()...{
StringBuffer sb=new StringBuffer();
int size=obscenitites.size();
for (int i = 0; i <size; i++) ...{
if(i!=0)...{
sb.append("|");
}
sb.append("(");
sb.append(obscenitites.get(i));
sb.append(")");
}
obsecenityPattern =Pattern.compile(sb.toString(),Pattern.CASE_INSENSITIVE);
}
public Pattern getObsecenityPattern() ...{
return obsecenityPattern;
}
public void setObsecenityPattern(Pattern obsecenityPattern) ...{
this.obsecenityPattern = obsecenityPattern;
}
//判断有无脏话
public boolean containObscenities(String data) ...{
Matcher m=obsecenityPattern.matcher(data);
return m.find();
}
//脏话替换
public String obfuscateObscenities(String data) ...{
Matcher m=obsecenityPattern.matcher(data);
StringBuffer out=new StringBuffer(data.length());
while(m.find())...{
if(m.group(0)!=null)...{
m.appendReplacement(out, rot13(m.group(0)));
}
}
return out.toString();
}
//ROT13算法
private String rot13(String in)...{
char[] chars=in.toCharArray();
for(int x=0;x<chars.length;x++)...{
char c=chars[x];
if(c>='a' && c<='m')...{
c+=13;
}
else if(c>='n' && c<='z')...{
c-=13;
}
else if(c>='A' && c<='M')...{
c+=13;
}
else if(c>='N' && c<='Z')...{
c-=13;
}
chars[x]=c;
}
return new String(chars);
}
}
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class ListBasedObscenityFilter implements OnscenityFilter ... {
private List obscenitites=null; //脏话列表,由Spring注入,写在配置文件中
private Pattern obsecenityPattern=null; //脏话匹配的正则表达式
public List getObscenitites() ...{
return obscenitites;
}
public void setObscenitites(List obscenitites) ...{
this.obscenitites = obscenitites;
buildRegex();
}
//编译正则表达式
private void buildRegex()...{
StringBuffer sb=new StringBuffer();
int size=obscenitites.size();
for (int i = 0; i <size; i++) ...{
if(i!=0)...{
sb.append("|");
}
sb.append("(");
sb.append(obscenitites.get(i));
sb.append(")");
}
obsecenityPattern =Pattern.compile(sb.toString(),Pattern.CASE_INSENSITIVE);
}
public Pattern getObsecenityPattern() ...{
return obsecenityPattern;
}
public void setObsecenityPattern(Pattern obsecenityPattern) ...{
this.obsecenityPattern = obsecenityPattern;
}
//判断有无脏话
public boolean containObscenities(String data) ...{
Matcher m=obsecenityPattern.matcher(data);
return m.find();
}
//脏话替换
public String obfuscateObscenities(String data) ...{
Matcher m=obsecenityPattern.matcher(data);
StringBuffer out=new StringBuffer(data.length());
while(m.find())...{
if(m.group(0)!=null)...{
m.appendReplacement(out, rot13(m.group(0)));
}
}
return out.toString();
}
//ROT13算法
private String rot13(String in)...{
char[] chars=in.toCharArray();
for(int x=0;x<chars.length;x++)...{
char c=chars[x];
if(c>='a' && c<='m')...{
c+=13;
}
else if(c>='n' && c<='z')...{
c-=13;
}
else if(c>='A' && c<='M')...{
c+=13;
}
else if(c>='N' && c<='Z')...{
c-=13;
}
chars[x]=c;
}
return new String(chars);
}
}
前置通知,当传入对象是BlogPosting的一个实例时,进行脏话判断和处理
package
ch7.BlogFilter;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class ObscenityFileterAdvise implements MethodBeforeAdvice ... {
private OnscenityFilter onscenityFilter;
public OnscenityFilter getOnscenityFilter() ...{
return onscenityFilter;
}
public void setOnscenityFilter(OnscenityFilter onscenityFilter) ...{
this.onscenityFilter = onscenityFilter;
}
public void before(Method method, Object[] object, Object target)
throws Throwable ...{
for(int x=0;x<object.length;x++)...{
if(object[0] instanceof BlogPosting)...{
BlogPosting arg=(BlogPosting)object[x];
//如果body中有脏话,则进行过滤修改处理
if(onscenityFilter.containObscenities(arg.getBody()))...{
arg.setBody(onscenityFilter.obfuscateObscenities(arg.getBody()));
}
}
}
}
}
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class ObscenityFileterAdvise implements MethodBeforeAdvice ... {
private OnscenityFilter onscenityFilter;
public OnscenityFilter getOnscenityFilter() ...{
return onscenityFilter;
}
public void setOnscenityFilter(OnscenityFilter onscenityFilter) ...{
this.onscenityFilter = onscenityFilter;
}
public void before(Method method, Object[] object, Object target)
throws Throwable ...{
for(int x=0;x<object.length;x++)...{
if(object[0] instanceof BlogPosting)...{
BlogPosting arg=(BlogPosting)object[x];
//如果body中有脏话,则进行过滤修改处理
if(onscenityFilter.containObscenities(arg.getBody()))...{
arg.setBody(onscenityFilter.obfuscateObscenities(arg.getBody()));
}
}
}
}
}
配置文件:
<?
xml version="1.0" encoding="UTF-8"
?>
< beans
xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" >
< bean id ="advise" class ="ch7.BlogFilter.ObscenityFileterAdvise" >
< property name ="onscenityFilter" >
< bean class ="ch7.BlogFilter.ListBasedObscenityFilter" >
< property name ="obscenitites" >
<!-- 设置脏话列表 -->
< list >
< value > fuck </ value >
< value > shit </ value >
</ list >
</ property >
</ bean >
</ property >
</ bean >
< bean id ="blog" class ="org.springframework.aop.framework.ProxyFactoryBean" >
< property name ="interceptorNames" >
< list >
< value > advise </ value >
</ list >
</ property >
< property name ="target" >
< bean class ="ch7.BlogFilter.BlogManager" ></ bean >
</ property >
<!-- 我们代理的是BlogManager类,所以要设置此属性为true -->
< property name ="proxyTargetClass" >
< value > true </ value >
</ property >
</ bean >
</ beans >
< beans
xmlns ="http://www.springframework.org/schema/beans"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" >
< bean id ="advise" class ="ch7.BlogFilter.ObscenityFileterAdvise" >
< property name ="onscenityFilter" >
< bean class ="ch7.BlogFilter.ListBasedObscenityFilter" >
< property name ="obscenitites" >
<!-- 设置脏话列表 -->
< list >
< value > fuck </ value >
< value > shit </ value >
</ list >
</ property >
</ bean >
</ property >
</ bean >
< bean id ="blog" class ="org.springframework.aop.framework.ProxyFactoryBean" >
< property name ="interceptorNames" >
< list >
< value > advise </ value >
</ list >
</ property >
< property name ="target" >
< bean class ="ch7.BlogFilter.BlogManager" ></ bean >
</ property >
<!-- 我们代理的是BlogManager类,所以要设置此属性为true -->
< property name ="proxyTargetClass" >
< value > true </ value >
</ property >
</ bean >
</ beans >
测试代码:
package
ch7.BlogFilter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test ... {
/** *//**
* @param args
*/
public static void main(String[] args) ...{
ApplicationContext context=new ClassPathXmlApplicationContext("ch7/BlogFilter/applicationContext.xml");
BlogManager blogManager=(BlogManager)context.getBean("blog");
BlogPostingImpl blog=new BlogPostingImpl();
blog.setBody("shit! you must be fuck");
blogManager.setBlogPosting(blog);
System.out.println(blogManager.getBlogPosting().getBody());
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test ... {
/** *//**
* @param args
*/
public static void main(String[] args) ...{
ApplicationContext context=new ClassPathXmlApplicationContext("ch7/BlogFilter/applicationContext.xml");
BlogManager blogManager=(BlogManager)context.getBean("blog");
BlogPostingImpl blog=new BlogPostingImpl();
blog.setBody("shit! you must be fuck");
blogManager.setBlogPosting(blog);
System.out.println(blogManager.getBlogPosting().getBody());
}
}
结果:
fuvg! you must be shpx 可以看到,脏话已经被处理过了