案列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