`
txidol
  • 浏览: 54538 次
  • 性别: 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);
    }
}

分享到:
评论

相关推荐

    02_张孝祥09年Struts视频_文件上传单元

    所讲解的内容非常丰富和深入,总结张孝祥老师多年的心得体会,包含了许多鲜为人知的struts...课程信息量虽然很大,但绝对不是语法罗列式的泛泛而谈,而是用struts去解决各种实际应用的问题,是面向就业和实际开发的。

    struts中的tree文件

    这是在struts当中应用很好的一个技术,可以使管理的文档层次分明的罗列下来,亲,不信你可以试一下!tree02.jsp

    罗列图标带字.rar

    【标题】"罗列图标带字.rar"是一个压缩文件,很可能包含了多个带有文字标识的图标资源。这种类型的文件在IT行业中通常用于软件开发、网页设计、用户界面(UI)设计等领域,其中图标是视觉元素,而文字则提供了附加的...

    实用圆形并列罗列PPT图形.pptx

    2. **信息组织**:在圆形并列罗列中,信息通常按照逻辑顺序或者重要性进行分布,如从外向内、从上至下等,确保观众能按部就班地接收信息。每个圆形部分可以代表一个独立的观点、步骤、数据点或者类别,通过颜色、...

    奔跑剪影项目罗列PPT图形.rar

    标题中的“奔跑剪影项目罗列PPT图形.rar”表明这是一个关于PPT设计的资源包,其中包含了与运动、活力或动态主题相关的剪影图形,适用于制作演示文稿时使用。这种类型的图形通常用于表现活力、进步或者团队合作等概念...

    go语言设计模式

    结构型设计模式,如适配器模式、桥接模式、组合模式、装饰器模式等,展示了如何构建灵活的类结构来适应需求的变化。行为型设计模式,如责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、观察者模式、状态...

    模式分类(Pattern Classification)第二版英文答案

    书中的“目录”详细罗列了全书的十个章节,每个章节都包含了一系列的习题及其解答。这些解答不仅涉及计算过程,而且往往还提供了理论知识的应用,帮助读者更深入地理解和掌握模式分类的理论与实践。由于文档信息不...

    罗列IP地址的一个应用

    "罗列IP地址的一个应用"指的是创建一个程序,能够列举出特定网络环境中所有的IP地址。在这个项目中,我们看到涉及到的文件主要是VC++(Visual C++)开发环境下的源代码文件,如`.cpp`和`.h`文件,这表明程序是用C++...

    问号问题要点罗列PPT模板.rar

    在IT行业中,PPT(PowerPoint)是一种广泛使用的演示文稿制作工具,尤其在商务会议、教学、报告和产品展示等场景中。"问号问题要点罗列PPT模板"显然是一个专门设计用于帮助用户整理和展示问题及解决方案的模板。这种...

    总项分项罗列说明PPT模板.rar

    在实际应用中,"总项分项罗列说明PPT模板.pptx"可能包含预设的样式、颜色方案、图形元素和布局,以确保整个演示文稿的视觉一致性。用户只需根据自己的需求填充内容,调整模板中的文字和图片,即可快速创建一份专业且...

    文件板夹项目罗列PPT模板.pptx

    【描述】"文件板夹项目罗列PPT模板"强调了创意在未来的成功中的核心地位,特别是在基础教育中,教师可以利用这种工具激发学生的创新思维。这表明,无论是教育界还是企业界,创新思维的培养都是至关重要的,而有效的...

    树形三项项目罗列PPT图形.rar

    标题中的“树形三项项目罗列PPT图形.rar”表明这是一个关于使用PPT(PowerPoint)制作的,呈现树状结构来展示三个项目的演示文稿。这种类型的图形通常用于组织和展示信息,使得层次清晰、逻辑分明,尤其适用于管理、...

    树形三项项目罗列PPT图形.pptx

    在"树形三项项目罗列PPT图形.pptx"这个文件中,我们可以看到一个具体的实例,它利用了树形结构来展示三个主要概念或项目的层次关系。 树形图是一种视觉表示层次结构的方法,常用于数据组织、项目管理、流程分析等...

    五项并列罗列PPT图形素材.rar

    五项并列罗列PPT图形素材下载。

    享元、解释器、职责链、装饰模式

    看了上面奖金计算的问题,所幸我们只是来学习设计模式,并不是真的要去实现整个奖金计算体系的业务,因此也没有必要把所有的计算业务都罗列在这里,为了后面演示的需要,简化一下,演示用的奖金计算体系如下: ...

    服务业商业模式构建和创新方法比较研究

    商业模式研究的发展经历了从最初的概念提出,到要素罗列,再到详细描述,直至构建商业模式本体,并最终将商业模式应用于不同系统的五个阶段。商业模式的研究经历了不断深化和细化的过程,不同阶段的研究为理解商业...

    解决办法方案罗列PPT图形.rar

    2. **视觉元素**:图形是PPT中增强信息传递的重要工具。例如,流程图可清晰展示解决问题的步骤,图表可以直观地表示数据变化,而概念图则有助于表达复杂的关系。 3. **颜色搭配**:选择对比度适中的颜色方案能提高...

    windows系统自动罗列各级目录下的文件名.bat

    windows系统自动罗列各级目录下的文件名(树形罗列)

    西南 04j515 室内装饰

    根据给定的信息,“西南 04j515 室内装饰”似乎是一份与室内装饰设计相关的标准或规范文档,通常这类文档会提供一系列关于室内装饰材料选择、施工工艺、设计规范等方面的指导建议和技术标准。然而,由于提供的具体...

Global site tag (gtag.js) - Google Analytics