装饰器模式在Struts2中的应用

公孙俭
2023-12-01

案列2 StrutsRequestWrapper
public class StrutsRequestWrapper extends HttpServletRequestWrapper {

/** 
 * The constructor 
 * @param req The request 
 */  
public StrutsRequestWrapper(HttpServletRequest req) {  
    super(req);  
}  

/** 
 * Gets the object, looking in the value stack if not found 
 * 
 * @param s The attribute key 
 */  
public Object getAttribute(String s) {  
    if (s != null && s.startsWith("javax.servlet")) {  
        // don't bother with the standard javax.servlet attributes, we can short-circuit this  
        // see WW-953 and the forums post linked in that issue for more info  
        return super.getAttribute(s);  
    }  

    ActionContext ctx = ActionContext.getContext();  
    Object attribute = super.getAttribute(s);  
    if (ctx != null) {  
        if (attribute == null) {  
            boolean alreadyIn = false;  
            Boolean b = (Boolean) ctx.get("__requestWrapper.getAttribute");  
            if (b != null) {  
                alreadyIn = b.booleanValue();  
            }  

            // note: we don't let # come through or else a request for  
            // #attr.foo or #request.foo could cause an endless loop  
            if (!alreadyIn && s.indexOf("#") == -1) {  
                try {  
                    // If not found, then try the ValueStack  
                    ctx.put("__requestWrapper.getAttribute", Boolean.TRUE);  
                    ValueStack stack = ctx.getValueStack();  
                    if (stack != null) {  
                        attribute = stack.findValue(s);  
                    }  
                } finally {  
                    ctx.put("__requestWrapper.getAttribute", Boolean.FALSE);  
                }  
            }  
        }  
    }  
    return attribute;  
}  

}

案列2 OgnlContext

在Ognl(ognl,jar)中有一个OgnlContext类,实现了Map接口,在创建时,使用Map构造,并内部维护该Map
[java] view plain copy
public class OgnlContext extends Object implements Map
{
private static Map RESERVED_KEYS = new HashMap(11);
private Map _values = new HashMap(23);
private int _localReferenceCounter = 0;
private Map _localReferenceMap = null;
public OgnlContext(Map values)
{
super();
this._values = values;
}
public Map getValues()
{
return _values;
}
public void setValues(Map value) {
for(Iterator it = value.keySet().iterator(); t.hasNext();) {
Object k = it.next();
_values.put(k, value.get(k));
}
}
//省略了非常多属性和方法…
}
案列3 OgnlTypeConverterWrapper
案列2其实只是Ognl中的,下面的两个案列比较神奇,实现的接口是ognl中的接口,但实际构造传参是Struts自己的接口类,不过这两个接口方法是一模一样的。这种方式屏蔽了原始的默认实现,且有利于Struts自己及用户扩展功能。
Ognl 和 Struts 中的TypeConverter接口都长这样
[java] view plain copy
public interface TypeConverter
{
public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType);
}
Struts中装饰类
[java] view plain copy
public class OgnlTypeConverterWrapper implements ognl.TypeConverter { //接口实现是ognl接口

private TypeConverter typeConverter;//实际传参是Struts自己的接口内  

public OgnlTypeConverterWrapper(TypeConverter conv) {  
    if (conv == null) {  
        throw new IllegalArgumentException("Wrapped type converter cannot be null");  
    }  
    this.typeConverter = conv;  
}  

public Object convertValue(Map context, Object target, Member member,    //他们有完全一样的方法  
        String propertyName, Object value, Class toType) {  
    return typeConverter.convertValue(context, target, member, propertyName, value, toType);  
}  

public TypeConverter getTarget() {  
    return typeConverter;  
}  

}
Struts中的实现类
[java] view plain copy
public class DefaultTypeConverter implements TypeConverter {

public Object convertValue(Map<String, Object> context, Object target, Member member,  
        String propertyName, Object value, Class toType) {  
    return convertValue(context, value, toType);  
}  

public TypeConverter getTypeConverter( Map<String, Object> context )  
{  
    Object obj = context.get(TypeConverter.TYPE_CONVERTER_CONTEXT_KEY);  
    if (obj instanceof TypeConverter) {  
        return (TypeConverter) obj;  

    // for backwards-compatibility  
    } else if (obj instanceof ognl.TypeConverter) {  
        return new XWorkTypeConverterWrapper((ognl.TypeConverter) obj);  
    }  
    return null;   
}  

public Object convertValue(Object value, Class toType) {  
    Object result = null;  

    if (value != null) {  
        /* If array -> array then convert components of array individually */  
        if (value.getClass().isArray() && toType.isArray()) {  
            Class componentType = toType.getComponentType();  

            result = Array.newInstance(componentType, Array  
                    .getLength(value));  
            for (int i = 0, icount = Array.getLength(value); i < icount; i++) {  
                Array.set(result, i, convertValue(Array.get(value, i),  
                        componentType));  
            }  
        } else {  
            if ((toType == Integer.class) || (toType == Integer.TYPE))  
                result = Integer.valueOf((int) longValue(value));  
            if ((toType == Double.class) || (toType == Double.TYPE))  
                result = new Double(doubleValue(value));  
            if ((toType == Boolean.class) || (toType == Boolean.TYPE))  
                result = booleanValue(value) ? Boolean.TRUE : Boolean.FALSE;  
            if ((toType == Byte.class) || (toType == Byte.TYPE))  
                result = Byte.valueOf((byte) longValue(value));  
            if ((toType == Character.class) || (toType == Character.TYPE))  
                result = new Character((char) longValue(value));  
            if ((toType == Short.class) || (toType == Short.TYPE))  
                result = Short.valueOf((short) longValue(value));  
            if ((toType == Long.class) || (toType == Long.TYPE))  
                result = Long.valueOf(longValue(value));  
            if ((toType == Float.class) || (toType == Float.TYPE))  
                result = new Float(doubleValue(value));  
            if (toType == BigInteger.class)  
                result = bigIntValue(value);  
            if (toType == BigDecimal.class)  
                result = bigDecValue(value);  
            if (toType == String.class)  
                result = stringValue(value);  
            if (Enum.class.isAssignableFrom(toType))  
                result = enumValue((Class<Enum>)toType, value);  
        }  
    } else {  
        if (toType.isPrimitive()) {  
            result = primitiveDefaults.get(toType);  
        }  
    }  
    return result;  
}  

public static double doubleValue(Object value) throws NumberFormatException {  
    if (value == null)  
        return 0.0;  
    Class c = value.getClass();  
    if (c.getSuperclass() == Number.class)  
        return ((Number) value).doubleValue();  
    if (c == Boolean.class)  
        return ((Boolean) value).booleanValue() ? 1 : 0;  
    if (c == Character.class)  
        return ((Character) value).charValue();  
    String s = stringValue(value, true);  
    return (s.length() == 0) ? 0.0 : Double.parseDouble(s);  
}  

public static String stringValue(Object value, boolean trim) {  
    String result;  

    if (value == null) {  
        result = NULL_STRING;  
    } else {  
        result = value.toString();  
        if (trim) {  
            result = result.trim();  
        }  
    }  
    return result;  
}  
//省略了许多其他方法  

}
XWorkConverter类,继续扩展装饰TypeConverter,这里采用Struts注入方式,从而实现自定义TypeConverter
[java] view plain copy
public class XWorkConverter extends DefaultTypeConverter {

protected HashMap<Class, Map<String, Object>> mappings = new HashMap<Class, Map<String, Object>>(); // action  
protected HashSet<Class> noMapping = new HashSet<Class>(); // action  
protected HashMap<String, TypeConverter> defaultMappings = new HashMap<String, TypeConverter>();  // non-action (eg. returned value)  
protected HashSet<String> unknownMappings = new HashSet<String>();     // non-action (eg. returned value)  

private TypeConverter defaultTypeConverter;  
private ObjectFactory objectFactory;  
private FileManager fileManager;  
private boolean reloadingConfigs;  

protected XWorkConverter() {  
}  

@Inject  
public void setObjectFactory(ObjectFactory factory) {  
    this.objectFactory = factory;  
    // note: this file is deprecated  
    loadConversionProperties("xwork-default-conversion.properties");  

    loadConversionProperties("xwork-conversion.properties");  
}  

@Inject  //注入方法  
public void setDefaultTypeConverter(XWorkBasicConverter conv) {  
    this.defaultTypeConverter = conv;  
}  

//省略许多方法和属性...  

}
配置:xwork-conversion.properties Java类包中的ClassName-conversion.properties 以及注解方式的声明

案列4 OgnlNullhandlerWrapper

同案列3方式 Ognl接口
[java] view plain copy
public interface NullHandler
{
public Object nullMethodResult(Map context, Object target, String methodName, Object[] args);

public Object nullPropertyValue(Map context, Object target, Object property);  

}
Ognl实现类
[java] view plain copy
public class ObjectNullHandler implements NullHandler
{
/* NullHandler interface */
public Object nullMethodResult(Map context, Object target, String methodName, Object[] args)
{
return null;
}

public Object nullPropertyValue(Map context, Object target, Object property)  
{  
    return null;  
}  

}
Struts接口
[java] view plain copy
public interface NullHandler
{
public Object nullMethodResult(Map

 类似资料: