公司Vac方法过滤器使用到反射机制,读取xml配置文件过滤用户访问的方法名是否合法。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
@SuppressWarnings("unchecked")
Map<Object, Object> requestData = (Map<Object, Object>) httpRequest.getAttribute("requestData");
String methodName = (String) requestData.get(METHOD);
//获得bean的配置
String beanName = mapProtocol.get(methodName).get(BEAN);
// 去除.符号
methodName = getMethod(methodName);
//从spring context中获得bean
Object instance = getContext(filterConfig).getBean(beanName);
Class<? extends Object> clazz = instance.getClass();
Object resultContent = null;
try {
Method method = clazz
.getDeclaredMethod(methodName, getParamTypes());
Map params = removeSysParams(requestData);
resultContent = method.invoke(instance, params);
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof BusinessException) {
BusinessException serviceExp = (BusinessException) e
.getTargetException();
Assert.throwBPException(serviceExp.getMessageKey(),
serviceExp.getMessage());
}
e.printStackTrace();
Assert.throwBPException(INVOCATION_TARGET_EXP, e);
} catch (NoSuchMethodException e) {
e.printStackTrace();
Assert.throwBPException(ILLEGAL_ARGUMENT_EXP, e);
}
catch (IllegalAccessException e) {
e.printStackTrace();
Assert.throwBPException(ILLEGAL_ARGUMENT_EXP, e);
}
Enumeration enumeration = httpRequest.getAttributeNames();
while (enumeration.hasMoreElements()) {
String name = enumeration.nextElement().toString();
httpRequest.removeAttribute(name);
}
httpRequest.setAttribute(RESPONSEDATA, resultContent);
}
下面是Method类的源代码及说明:
- packagejava.lang.reflect;
- importsun.reflect.MethodAccessor;
- importsun.reflect.Reflection;
- /**
- *
- *描述方法的类
- *
- *注意使用反射的方式是首先通过
- *Class.getMethod(Stringname,Class[]parameterTypes)获得一个Method对象
- *String表示方法名,parameterTypes表示参数列表中的每个参数对应的类型,这时先获得
- *Class对象中Method对象,与实际的操作对象无关,然后调用此方法,是通过Method.(Objectobj,Object[]args)
- *这里obj指调用方法的对象,args表示每个参数对应的值
- *
- *例子,一下两种方式的效果是一样的(当然性能不同)
- *Stringost="lqtest";
- *Stringnst=ost.substring(2,6);
- *
- *Stringost2="lqtest";
- *Class[]types={int.class,int.class};
- *Methodmed=String.class.getMethod("substring",types);
- *Object[]values={newInteger(2),newInteger(6)};
- *Stringnst2=(String)med.invoke(ost2,values);
- *
- *使用反射一切都是变化的,类名,方法名,参数列表,都是变量,而不是写死的,他们
- *在运行时才知道具体值,而不是编译期
- *
- *commentbyliqiang
- *
- *@authorKennethRussell
- *@authorNakulSaraiya
- */
- publicfinal
- classMethodextendsAccessibleObjectimplementsMember{
- //定义此方法的类对象
- privateClassclazz;
- privateintslot;
- //方法名,从1.4开始它变成intern的形式
- privateStringname;
- //返回类型
- privateClassreturnType;
- //参数列表
- privateClass[]parameterTypes;
- //异常列表
- privateClass[]exceptionTypes;
- //方法的描述符
- privateintmodifiers;
- //处理方法的实际对象
- privatevolatileMethodAccessormethodAccessor;
- //如果当前对象是通过拷贝得到的,则root指向拷贝前的对象
- privateMethodroot;
- //调用对象的安全检查的缓存,保存上一个通过检查的调用对象,如果当前的调用对象
- //不是上一个调用对象则做安全检查
- privatevolatileClasssecurityCheckTargetClassCache;
- //构造函数
- Method(ClassdeclaringClass,
- Stringname,
- Class[]parameterTypes,
- ClassreturnType,
- Class[]checkedExceptions,
- intmodifiers,
- intslot)
- {
- this.clazz=declaringClass;
- this.name=name;
- this.parameterTypes=parameterTypes;
- this.returnType=returnType;
- this.exceptionTypes=checkedExceptions;
- this.modifiers=modifiers;
- this.slot=slot;
- }
- //通过本对象的数据生成一个新对象
- Methodcopy(){
- //通过本对象的数据生成一个新对象
- Methodres=newMethod(clazz,name,parameterTypes,returnType,
- exceptionTypes,modifiers,slot);
- //新对象的root指向原对象
- res.root=this;
- //新对象与原对象公用一个MethodAccessor
- res.methodAccessor=methodAccessor;
- returnres;
- }
- //返回声明此函数的类
- publicClassgetDeclaringClass(){
- returnclazz;
- }
- //返回方法名
- publicStringgetName(){
- returnname;
- }
- //返回描述符
- publicintgetModifiers(){
- returnmodifiers;
- }
- //取得返回类型
- publicClassgetReturnType(){
- returnreturnType;
- }
- //返回参数列表
- publicClass[]getParameterTypes(){
- returncopy(parameterTypes);
- }
- //返回异常列表
- publicClass[]getExceptionTypes(){
- returncopy(exceptionTypes);
- }
- //判断obj是否与当前方法对象相等
- publicbooleanequals(Objectobj){
- if(obj!=null&&objinstanceofMethod){//如果是方法对象
- //转型
- Methodother=(Method)obj;
- //定义此方法的类和方法名相等
- if((getDeclaringClass()==other.getDeclaringClass())
- &&(getName()==other.getName())){
- /*Avoidunnecessarycloning*/
- Class[]params1=parameterTypes;
- Class[]params2=other.parameterTypes;
- //比较参数列表
- if(params1.length==params2.length){
- for(inti=0;i<params1.length;i++){
- if(params1[i]!=params2[i])
- returnfalse;
- }
- returntrue;
- }
- }
- }
- returnfalse;
- }
- //返回hashCode
- publicinthashCode(){
- returngetDeclaringClass().getName().hashCode()^getName().hashCode();
- }
- //方法对象的字符串表示
- publicStringtoString(){
- try{
- StringBuffersb=newStringBuffer();
- intmod=getModifiers();
- if(mod!=0){
- //标志符
- sb.append(Modifier.toString(mod)+"");
- }
- //注意它这里用的是Field方法中显示类的名字,这个方法显示数组类型跟Class.getName()不同
- //添加返回类型
- sb.append(Field.getTypeName(getReturnType())+"");
- //添加类名
- sb.append(Field.getTypeName(getDeclaringClass())+".");
- //添加方法名
- sb.append(getName()+"(");
- //参数列表
- Class[]params=parameterTypes;//avoidclone
- for(intj=0;j<params.length;j++){
- sb.append(Field.getTypeName(params[j]));
- if(j<(params.length-1))
- sb.append(",");
- }
- sb.append(")");
- //异常列表
- Class[]exceptions=exceptionTypes;//avoidclone
- if(exceptions.length>0){
- sb.append("throws");
- for(intk=0;k<exceptions.length;k++){
- sb.append(exceptions[k].getName());
- if(k<(exceptions.length-1))
- sb.append(",");
- }
- }
- returnsb.toString();
- }catch(Exceptione){
- return"<"+e+">";
- }
- }
- /**
- *
- *注意使用反射的方式是首先通过
- *Class.getMethod(Stringname,Class[]parameterTypes)获得一个Method对象
- *String表示方法名,parameterTypes表示参数列表中的每个参数对应的类型,这时先获得
- *Class对象中Method对象,与实际的操作对象无关,然后调用此方法,是通过Method.(Objectobj,Object[]args)
- *如果调用的方法是static的则obj对象为null,如果方法没有参数,则args的长度为0或为null
- *如果返回值是原始类型则返回它的封装类,如果返回值是void则返回null
- */
- publicObjectinvoke(Objectobj,Object[]args)
- throwsIllegalAccessException,IllegalArgumentException,
- InvocationTargetException
- {
- if(!override){
- if(!Reflection.quickCheckMemberAccess(clazz,modifiers)){
- //获得调用对象的Class对象
- Classcaller=Reflection.getCallerClass(1);
- ClasstargetClass=((obj==null||!Modifier.isProtected(modifiers))
- ?clazz
- :obj.getClass());
- //调用此操作的对象或方法调用作用的对象与缓存不同,则做安全检查
- if(securityCheckCache!=caller||
- targetClass!=securityCheckTargetClassCache){
- Reflection.ensureMemberAccess(caller,clazz,obj,modifiers);
- securityCheckCache=caller;
- //通过安全检查的调用对象,缓存它供下次调用时使用
- securityCheckTargetClassCache=targetClass;
- }
- }
- }
- if(methodAccessor==null)acquireMethodAccessor();
- returnmethodAccessor.invoke(obj,args);
- }
- //如果此对象是由copy生成的,则对象与生成此对象的对象使用同一个MethodAccessor
- privatevoidacquireMethodAccessor(){
- MethodAccessortmp=null;
- if(root!=null)tmp=root.getMethodAccessor();
- if(tmp!=null){
- methodAccessor=tmp;
- return;
- }
- //不是由copy得来创建MethodAccessor对象
- tmp=reflectionFactory.newMethodAccessor(this);
- setMethodAccessor(tmp);
- }
- //返回MethodAccessor对象
- MethodAccessorgetMethodAccessor(){
- returnmethodAccessor;
- }
- //设置MethodAccessor对象
- voidsetMethodAccessor(MethodAccessoraccessor){
- methodAccessor=accessor;
- if(root!=null){//如果此对象是由copy的来
- //递归调用其上级
- root.setMethodAccessor(accessor);
- }
- }
- //生成一个新的Class数组并将原数组内容考到新数组中
- staticClass[]copy(Class[]in){
- intl=in.length;
- if(l==0)
- returnin;
- Class[]out=newClass[l];
- for(inti=0;i<l;i++)
- out[i]=in[i];
- returnout;
- }
- }