【装饰模式】罗列Struts2中的那些装饰类

来源:互联网 发布:java语言程序设计基础篇 编辑:程序博客网 时间:2024/05/16 07:14

这篇并不讲装饰模式的原理,只是罗列Struts2中使用的一些装饰类,总结在一起提供欣赏借鉴。


案列1  StrutsRequestWrapper


首先回忆下Servlet中针对ServletRequest的装饰类ServletRequestWrapper

public class ServletRequestWrapper implements ServletRequest {    private ServletRequest request;    public ServletRequestWrapper(ServletRequest request) {        if (request == null) {            throw new IllegalArgumentException("Request cannot be null");        }        this.request = request;    }    public ServletRequest getRequest() {        return this.request;    }        public Object getAttribute(String name) {        return this.request.getAttribute(name);    }    //还有很多方法省略}

HttpServletRequest的装饰类HttpServletRequestWrapper

public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest {    public HttpServletRequestWrapper(HttpServletRequest request) {        super(request);    }    private HttpServletRequest _getHttpServletRequest() {        return (HttpServletRequest) super.getRequest();    }    public Cookie[] getCookies() {        return this._getHttpServletRequest().getCookies();    }       //还有很多方法省略}

Struts中因为数据存储的位置发生变化了,获取数据的方法变化了,所以造了一个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

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接口都长这样

public interface TypeConverter{    public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType);}
Struts中装饰类

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中的实现类

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

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接口 

public interface NullHandler{    public Object nullMethodResult(Map context, Object target, String methodName, Object[] args);    public Object nullPropertyValue(Map context, Object target, Object property);}
Ognl实现类

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接口
public interface NullHandler{    public Object nullMethodResult(Map<String, Object> context, Object target, String methodName, Object[] args);        public Object nullPropertyValue(Map<String, Object> context, Object target, Object property);}
Struts实现类  //可以自由扩展改变Nullhandler的实现类,如Struts的InstantiatingNullHandler解决级联时出现null值的情况

public class OgnlNullHandlerWrapper implements ognl.NullHandler {    private NullHandler wrapped;        public OgnlNullHandlerWrapper(NullHandler target) {        this.wrapped = target;    }        public Object nullMethodResult(Map context, Object target,            String methodName, Object[] args) {        return wrapped.nullMethodResult(context, target, methodName, args);    }    public Object nullPropertyValue(Map context, Object target, Object property) {        return wrapped.nullPropertyValue(context, target, property);    }}