`
txidol
  • 浏览: 52260 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

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

 
阅读更多

这篇并不讲装饰模式的原理,只是罗列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);
    }
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics