面向对象之路

    xiaoxiao2021-03-25  91

    仿struts读取配置文件,完成如下要求: 

    0. 读取配置文件struts.xml   1. 根据actionName找到相对应的class , 例如LoginAction,   通过反射实例化(创建对象)据parameters中的数据,调用对象的setter方法, 例如parameters中的数据                          是 ("name"="test" ,  "password"="1234") ,  那就应该调用 setName和setPassword方法 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" 3. 通过反射找到对象的所有getter方法(例如 getMessage),  通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message":  "登录成功"} ,  放到View对象的            parameters 4. 根据struts.xml中的 <result> 配置,以及execute的返回值,  确定哪一个jsp,放到View对象的jsp字段中。

    自己的思路不清晰,代码杂乱不堪,完全是想一点写一点。

    现将刘老师TDD实现思路及面向对象大法整理如下:

       public class ConfigurationTest { Configuration cfg=new Configuration("struts.xml"); @Test public void testGetClassName() { String clzName=cfg.getClassName("login"); Assert.assertEquals("domain.LoginAction", clzName); clzName = cfg.getClassName("logout"); Assert.assertEquals("domain.LogoutAction", clzName); }     @Test public void testResultView(){ String jsp=cfg.getResultView("login","success"); Assert.assertEquals("/jsp/homepage.jsp",jsp); } }

    一个用来读取配置文件并将class转换成其静态内部类,然后通过静态内部类的属性对应上类名。

    public class Configuration { Map<String,ActionConfig> actions = new HashMap<>(); public Configuration(String fileName) { String packageName = this.getClass().getPackage().getName(); packageName = packageName.replace('.', '/'); InputStream is = this.getClass().getResourceAsStream("/" + packageName + "/" + fileName); parseXML(is); try { is.close(); } catch (IOException e) { throw new ConfigurationException(e); } } private void parseXML(InputStream is){ SAXBuilder builder = new SAXBuilder();   try {   Document doc = builder.build(is); Element root = doc.getRootElement(); for(Element actionElement : root.getChildren("action")){ String actionName = actionElement.getAttributeValue("name"); String clzName = actionElement.getAttributeValue("class"); ActionConfig ac = new ActionConfig(actionName, clzName); for(Element resultElement : actionElement.getChildren("result")){ String resultName = resultElement.getAttributeValue("name"); String viewName = resultElement.getText().trim(); ac.addViewResult(resultName, viewName); } this.actions.put(actionName, ac); } } catch (JDOMException e) { throw new ConfigurationException(e); } catch (IOException e) { throw new ConfigurationException(e); }     } public String getClassName(String action) { ActionConfig ac = this.actions.get(action); if(ac == null){ return null; } return ac.getClassName(); } public String getResultView(String action, String resultName) { ActionConfig ac = this.actions.get(action); if(ac == null){ return null; } return ac.getViewName(resultName); } private static class ActionConfig{ String name; String clzName; Map<String,String> viewResult = new HashMap<>(); public ActionConfig(String actionName, String clzName) { this.name = actionName; this.clzName = clzName; } public String getClassName(){ return clzName; } public void addViewResult(String name, String viewName){ viewResult.put(name, viewName); } public String getViewName(String resultName){ return viewResult.get(resultName); } } }

    TDD加对象的职责划分,用一个工具类来处理反射。

    public class ReflectionUtilTest { @Test public void testGetSetterMethod() throws Exception{ String name="domain.LoginAction"; Class<?> clz=Class.forName(name); List<Method>methods =ReflectionUtil.getSetterMethods(clz); Assert.assertEquals(2, methods.size()); List<String> expectedNames=new ArrayList<>(); expectedNames.add("setName"); expectedNames.add("setPassword"); Set<String> acctualNames=new HashSet<>(); for(Method m:methods){ acctualNames.add(m.getName()); } Assert.assertTrue(acctualNames.containsAll(expectedNames)); }     @Test     public void testSetParameters() throws Exception{     String name="domain.LoginAction";     Class<?>clz=Class.forName(name);     Object o=clz.newInstance();     Map<String,String>params=new HashMap<String,String>();     params.put("name", "test");     params.put("password", "1234");         ReflectionUtil.setParameters(o,params);         Field f=clz.getDeclaredField("name");     f.setAccessible(true);     Assert.assertEquals("test", f.get(o));         f=clz.getDeclaredField("password");     f.setAccessible(true);     Assert.assertEquals("1234", f.get(o));     }     @Test     public void testGetGetterMethod()throws Exception{     String name="domain.LoginAction";     Class<?>clz=Class.forName(name);     List<Method>methods=ReflectionUtil.getGetterMethods(clz);         Assert.assertEquals(3, methods.size());     List<String>expectedNames=new ArrayList<>();     expectedNames.add("getMessage");     expectedNames.add("getName");     expectedNames.add("getPassword");     Set<String> acctualNames=new HashSet<>(); for(Method m:methods){ acctualNames.add(m.getName()); } Assert.assertTrue(acctualNames.containsAll(expectedNames));     }     @Test     public void testGetParamters() throws Exception{     String name="domain.LoginAction";     Class<?> clz=Class.forName(name);     LoginAction action=(LoginAction) clz.newInstance();     action.setName("test");     action.setPassword("123456");         Map<String,Object> params=ReflectionUtil.getParamterMap(action);     Assert.assertEquals(3, params.size());         Assert.assertEquals(null, params.get("message"));     Assert.assertEquals("test", params.get("name"));     Assert.assertEquals("123456", params.get("password"));     } }

    工具类用来封装对象的get、set方法,来对对象的属性值的射入和获取。

    public class ReflectionUtil { public static List<Method> getSetterMethods(Class<?> clz) { return getMethods(clz, "set"); } private static List<Method> getMethods(Class<?> clz, String startWithName) { List<Method> methods = new ArrayList<>(); for (Method m : clz.getDeclaredMethods()) { if (m.getName().startsWith(startWithName)) { methods.add(m); } } return methods; } public static void setParameters(Object o, Map<String, String> params) { List<Method> methods = getSetterMethods(o.getClass()); for (String name : params.keySet()) { String methodName = "set" + name; for (Method m : methods) { if (m.getName().equalsIgnoreCase(methodName)) { try { m.invoke(o, params.get(name)); } catch (Exception e) { e.printStackTrace(); } } } } } public static List<Method> getGetterMethods(Class<?> clz) { return getMethods(clz, "get"); } public static Map<String, Object> getParamterMap(Object o) { Map<String, Object> params = new HashMap<>(); List<Method> methods = getGetterMethods(o.getClass()); for (Method m : methods) { String methodName = m.getName(); String name = methodName.replaceFirst("get", "").toLowerCase(); try { Object value = m.invoke(o); params.put(name, value); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return params; } }

    最后用来实现上述要求的方法简单如斯:

    public class Struts { private final static Configuration cfg = new Configuration("struts.xml");        public static View runAction(String actionName, Map<String,String> parameters) {     String clzName = cfg.getClassName(actionName);         if(clzName == null){     return null;     }     try {         Class<?> clz = Class.forName(clzName);     Object action = clz.newInstance(); ReflectionUtil.setParameters(action, parameters); Method m = clz.getDeclaredMethod("execute"); String resultName = (String)m.invoke(action); Map<String,Object> params = ReflectionUtil.getParamterMap(action); String resultView = cfg.getResultView(actionName, resultName); View view = new View(); view.setParameters(params); view.setJsp(resultView); return view; } catch (Exception e) { e.printStackTrace(); }     return null;     }     }

    附:<?xml version="1.0" encoding="UTF-8"?> <struts>     <action name="login" class="domain.LoginAction">         <result name="success">/jsp/homepage.jsp</result>         <result name="fail">/jsp/showLogin.jsp</result>     </action>     <action name="logout" class="domain.LogoutAction">     <result name= "success">/jsp/welcome.jsp</result>     <result name= "error">/jsp/error.jsp</result>     </action> </struts>

    转载请注明原文地址: https://ju.6miu.com/read-21166.html

    最新回复(0)