From 41acf07fb209b78fe453a9789cd8fdb477676e59 Mon Sep 17 00:00:00 2001
From: jacky <1271620150@qq.com>
Date: Sat, 4 Mar 2017 12:07:36 +0800
Subject: [PATCH] Work02 Commit

---
 group09/1271620150/Work02/.classpath          |   8 +
 group09/1271620150/Work02/.gitignore          |   1 +
 group09/1271620150/Work02/.project            |  17 ++
 .../src/com/coderising/array/ArrayUtil.java   | 199 +++++++++++++++
 .../com/coderising/array/ArrayUtilTest.java   |  62 +++++
 .../coderising/litestruts/ActionClass.java    |  60 +++++
 .../coderising/litestruts/LoginAction.java    |  39 +++
 .../src/com/coderising/litestruts/Struts.java | 227 ++++++++++++++++++
 .../com/coderising/litestruts/StrutsTest.java |  49 ++++
 .../src/com/coderising/litestruts/View.java   |  23 ++
 .../src/com/coderising/litestruts/struts.xml  |  11 +
 .../litestruts/util/StringUtil.java           | 102 ++++++++
 .../coderising/litestruts/util/XmlUtil.java   | 109 +++++++++
 13 files changed, 907 insertions(+)
 create mode 100644 group09/1271620150/Work02/.classpath
 create mode 100644 group09/1271620150/Work02/.gitignore
 create mode 100644 group09/1271620150/Work02/.project
 create mode 100644 group09/1271620150/Work02/src/com/coderising/array/ArrayUtil.java
 create mode 100644 group09/1271620150/Work02/src/com/coderising/array/ArrayUtilTest.java
 create mode 100644 group09/1271620150/Work02/src/com/coderising/litestruts/ActionClass.java
 create mode 100644 group09/1271620150/Work02/src/com/coderising/litestruts/LoginAction.java
 create mode 100644 group09/1271620150/Work02/src/com/coderising/litestruts/Struts.java
 create mode 100644 group09/1271620150/Work02/src/com/coderising/litestruts/StrutsTest.java
 create mode 100644 group09/1271620150/Work02/src/com/coderising/litestruts/View.java
 create mode 100644 group09/1271620150/Work02/src/com/coderising/litestruts/struts.xml
 create mode 100644 group09/1271620150/Work02/src/com/coderising/litestruts/util/StringUtil.java
 create mode 100644 group09/1271620150/Work02/src/com/coderising/litestruts/util/XmlUtil.java

diff --git a/group09/1271620150/Work02/.classpath b/group09/1271620150/Work02/.classpath
new file mode 100644
index 000000000..9b2ed0d52
--- /dev/null
+++ b/group09/1271620150/Work02/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+	<classpathentry kind="lib" path="lib/dom4j-1.6.1.jar"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/group09/1271620150/Work02/.gitignore b/group09/1271620150/Work02/.gitignore
new file mode 100644
index 000000000..ae3c17260
--- /dev/null
+++ b/group09/1271620150/Work02/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/group09/1271620150/Work02/.project b/group09/1271620150/Work02/.project
new file mode 100644
index 000000000..fc557efe1
--- /dev/null
+++ b/group09/1271620150/Work02/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Work02</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/group09/1271620150/Work02/src/com/coderising/array/ArrayUtil.java b/group09/1271620150/Work02/src/com/coderising/array/ArrayUtil.java
new file mode 100644
index 000000000..8f620875f
--- /dev/null
+++ b/group09/1271620150/Work02/src/com/coderising/array/ArrayUtil.java
@@ -0,0 +1,199 @@
+package com.coderising.array;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public class ArrayUtil {
+	
+	/**
+	 * 给定一个整形数组a , 对该数组的值进行置换
+		例如： a = [7, 9 , 30, 3]  ,   置换后为 [3, 30, 9,7]
+		如果     a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7]
+	 * @param origin
+	 * @return
+	 */
+	public  void  reverseArray(int[] origin){
+		int n = origin.length;
+		int temp  =0;
+		int halfLength = origin.length/2;
+		for (int i = 0; i < halfLength; i++) {
+			temp= origin[i];
+			origin[i] = origin[n-i-1];
+			origin[n-i-1] = temp;
+		}
+	}
+	
+	/**
+	 * 现在有如下的一个数组：   int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}   
+	 * 要求将以上数组中值为0的项去掉，将不为0的值存入一个新的数组，生成的新数组为：   
+	 * {1,3,4,5,6,6,5,4,7,6,7,5}  
+	 * @param oldArray
+	 * @return
+	 */
+	
+	public int[] removeZero(int[] oldArray){
+		ArrayList<Integer> list  = new ArrayList<>();
+		for (int i = 0; i < oldArray.length; i++) {
+			if(oldArray[i]!=0){
+				list.add(oldArray[i]);
+			}
+		}
+		int[] new_array = new int[list.size()];
+		for(int i=0;i<list.size();i++){
+			new_array[i]=list.get(i);
+		}
+		
+		return new_array;
+	}
+	
+	/**
+	 * 给定两个已经排序好的整形数组， a1和a2 ,  创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素， 并且仍然是有序的
+	 * 例如 a1 = [3, 5, 7,8]   a2 = [4, 5, 6,7]    则 a3 为[3,4,5,6,7,8]    , 注意： 已经消除了重复
+	 * @param array1
+	 * @param array2
+	 * @return
+	 */
+	
+	public int[] merge(int[] array1, int[] array2) {
+		Set<Integer> set = new HashSet<Integer>();
+		for (int i = 0; i < array1.length; i++) {
+			set.add(array1[i]);
+		}
+		for (int i = 0; i < array2.length; i++) {
+			set.add(array2[i]);
+		}
+		Iterator<Integer> i = set.iterator();
+		int[] arrays = new int[set.size()];
+		int num = 0;
+		while (i.hasNext()) {
+			int a = (Integer) i.next();
+			arrays[num++] = a;
+		}
+		Arrays.sort(arrays);
+		return arrays;
+	}
+	/**
+	 * 把一个已经存满数据的数组 oldArray的容量进行扩展， 扩展后的新数据大小为oldArray.length + size
+	 * 注意，老数组的元素在新数组中需要保持
+	 * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为
+	 * [2,3,6,0,0,0]
+	 * @param oldArray
+	 * @param size
+	 * @return
+	 */
+	public int[] grow(int [] oldArray,  int size){
+		int[] new_array = new int[oldArray.length+size];
+		for (int i = 0; i < oldArray.length; i++) {
+			new_array[i] = oldArray[i];
+		}
+		return new_array;
+	}
+	
+	/**
+	 * 斐波那契数列为：1，1，2，3，5，8，13，21......  ，给定一个最大值， 返回小于该值的数列
+	 * 例如， max = 15 , 则返回的数组应该为 [1，1，2，3，5，8，13]
+	 * max = 1, 则返回空数组 []
+	 * @param max
+	 * @return
+	 */
+	public int[] fibonacci(int max){
+		ArrayList<Integer> list  = new ArrayList<>();
+		int a=1,b=1;
+		list.add(a);
+		list.add(b);
+		for(int c=0;c<max;){
+			list.add(c);
+			c=a+b;
+			a=b;
+			b=c;
+			
+		}
+		int[] array = new int[list.size()];
+		for(int i =0;i<list.size();i++){
+			array[i] = list.get(i);
+		}
+		return array;
+	}
+	
+	/**
+	 * 返回小于给定最大值max的所有素数数组
+	 * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19]
+	 * @param max
+	 * @return
+	 */
+	public int[] getPrimes(int max){
+		ArrayList<Integer> prime = new ArrayList<Integer>();
+        for(int i = 2 ; i < max ;i++){
+            boolean sign = true;
+            for(int j = 2 ; j < i ;j++){
+                if(i%j == 0){
+                    sign = false;
+                    continue;
+                }
+            }
+            if(sign){
+                prime.add(i);
+            }
+        }
+        int[] array = new int[prime.size()];
+		for(int i =0;i<prime.size();i++){
+			array[i] = prime.get(i);
+		}
+		return array;
+	}
+	
+	/**
+	 * 所谓“完数”， 是指这个数恰好等于它的因子之和，例如6=1+2+3
+	 * 给定一个最大值max， 返回一个数组， 数组中是小于max 的所有完数
+	 * @param max
+	 * @return
+	 */
+	public int[] getPerfectNumbers(int max){
+		ArrayList<Integer> perfect = new ArrayList<Integer>();
+        for(int i = 1 ; i < max ;i++){
+            boolean sign = false;
+            for(int j = 1, k=0; j<i; j++){
+                if(i%j==0){
+                	k=k+j;
+                }
+                if(i==k){
+                	sign = true;
+                }
+            }
+            if(sign){
+            	perfect.add(i);
+            }
+            
+        }
+        int[] array = new int[perfect.size()];
+		for(int i =0;i<perfect.size();i++){
+			array[i] = perfect.get(i);
+		}
+		return array;
+	}
+	
+	/**
+	 * 用seperator 把数组 array给连接起来
+	 * 例如array= [3,8,9], seperator = "-"
+	 * 则返回值为"3-8-9"
+	 * @param array
+	 * @param s
+	 * @return
+	 */
+	public String join(int[] array, String seperator){
+		StringBuilder builder = new StringBuilder();
+		for (int i = 0; i < array.length; i++) {
+			builder.append(array[i]);
+			if(i<array.length-1){
+				builder.append(seperator);
+			}
+		}
+		return builder.toString();
+	}
+	
+	
+
+}
\ No newline at end of file
diff --git a/group09/1271620150/Work02/src/com/coderising/array/ArrayUtilTest.java b/group09/1271620150/Work02/src/com/coderising/array/ArrayUtilTest.java
new file mode 100644
index 000000000..98d8a7012
--- /dev/null
+++ b/group09/1271620150/Work02/src/com/coderising/array/ArrayUtilTest.java
@@ -0,0 +1,62 @@
+package com.coderising.array;
+
+
+import java.util.Arrays;
+
+import org.junit.Test;
+
+public class ArrayUtilTest {
+	
+	private ArrayUtil util = new ArrayUtil();
+
+	@Test
+	public void testReverseArray() {
+		int[] a = new int[]{7, 9 , 30, 3};
+		int[] b = new int[]{7, 9, 30, 3, 4};
+		util.reverseArray(a);
+		util.reverseArray(b);
+		System.out.println(Arrays.toString(a));
+		System.out.println(Arrays.toString(b));
+	}
+	
+	@Test
+	public void testRemoveZero(){
+		int[] a = new int[]{1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5};
+		System.out.println(Arrays.toString(util.removeZero(a)));
+	}
+
+	@Test
+	public void testMerge(){
+		int[] a = new int[]{3, 5, 7,8};
+		int[] b = new int[]{4, 5, 6,7};
+		System.out.println(Arrays.toString(util.merge(a, b)));
+	}
+	
+	@Test
+	public void testGrow(){
+		int[] a = new int[]{2,3,6};
+		System.out.println(Arrays.toString(util.grow(a, 3)));
+	}
+	
+	@Test
+	public void testFibonacci(){
+		System.out.println(Arrays.toString(util.fibonacci(15)));
+	}
+	
+	@Test
+	public void tsetGetPrimes(){
+		System.out.println(Arrays.toString(util.getPrimes(23)));
+	}
+	
+	@Test
+	public void testGetPerfectNumbers(){
+		System.out.println(Arrays.toString(util.getPerfectNumbers(25)));
+		
+	}
+	
+	@Test
+	public void testJoin(){
+		int[] a = new int[]{3,8,9};
+		System.out.println(util.join(a, "-"));
+	}
+}
diff --git a/group09/1271620150/Work02/src/com/coderising/litestruts/ActionClass.java b/group09/1271620150/Work02/src/com/coderising/litestruts/ActionClass.java
new file mode 100644
index 000000000..34ddb9c9a
--- /dev/null
+++ b/group09/1271620150/Work02/src/com/coderising/litestruts/ActionClass.java
@@ -0,0 +1,60 @@
+package com.coderising.litestruts;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.dom4j.Element;
+
+public class ActionClass<E> {
+	/**
+	 * 类名
+	 */
+	private String className;
+	/**
+	 * 返回结果页面
+	 */
+	private String result;
+	/**
+	 * 临时存储Action下的所有result结点
+	 */
+	private List<Element> elements = new ArrayList<Element>();
+
+	/**
+	 * 要调用的Action本身
+	 */
+	private Object action;
+
+	public Object getAction() {
+		return action;
+	}
+
+	public void setAction(Object action) {
+		this.action = action;
+	}
+
+	public String getClassName() {
+		return className;
+	}
+
+	public void setClassName(String className) {
+		this.className = className;
+	}
+
+
+	public String getResult() {
+		return result;
+	}
+
+	public void setResult(String result) {
+		this.result = result;
+	}
+
+	public List<Element> getElements() {
+		return elements;
+	}
+
+	public void setElements(List<Element> elements) {
+		this.elements = elements;
+	}
+
+}
\ No newline at end of file
diff --git a/group09/1271620150/Work02/src/com/coderising/litestruts/LoginAction.java b/group09/1271620150/Work02/src/com/coderising/litestruts/LoginAction.java
new file mode 100644
index 000000000..ed2436ce4
--- /dev/null
+++ b/group09/1271620150/Work02/src/com/coderising/litestruts/LoginAction.java
@@ -0,0 +1,39 @@
+package com.coderising.litestruts;
+
+/**
+ * 这是一个用来展示登录的业务类， 其中的用户名和密码都是硬编码的。
+ * @author jacky
+ *
+ */
+public class LoginAction{
+    private String name ;
+    private String password;
+    private String message;
+
+    public String getName() {
+        return name;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public String execute(){
+            if("test".equals(name) && "1234".equals(password)){
+                this.message = "login successful";
+                return "success";
+            }
+            this.message = "login failed,please check your user/pwd";
+            return "fail";
+    }
+
+    public void setName(String name){
+        this.name = name;
+    }
+    public void setPassword(String password){
+        this.password = password;
+    }
+    public String getMessage(){
+        return this.message;
+    }
+}
\ No newline at end of file
diff --git a/group09/1271620150/Work02/src/com/coderising/litestruts/Struts.java b/group09/1271620150/Work02/src/com/coderising/litestruts/Struts.java
new file mode 100644
index 000000000..2162de7ab
--- /dev/null
+++ b/group09/1271620150/Work02/src/com/coderising/litestruts/Struts.java
@@ -0,0 +1,227 @@
+package com.coderising.litestruts;
+
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.dom4j.Attribute;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+
+import com.coderising.litestruts.util.StringUtil;
+import com.coderising.litestruts.util.XmlUtil;
+
+
+
+
+
+
+public class Struts {
+	
+	/**
+	 * struts.xml默认类路径
+	 */
+	public static final String STRUTS_XML_FILE = "struts.xml";
+
+    public View runAction(String actionName, Map<String,String> parameters) {
+
+        /*
+         
+		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字段中。
+        
+        */
+    	View view = null;
+    	if(StringUtil.isNotBlank(actionName)){
+            ActionClass clas = getActionClass(actionName);  
+            Object action = setActionValues(clas, parameters);
+            clas.setAction(action);
+            view = setResultValue(clas);
+    	}
+    
+    	return view;
+    }
+
+
+	private View setResultValue(ActionClass clas) {
+		Map<String, Object> params = new HashMap<String, Object>();
+		View view = new View();
+		Object obj = invokeAction(clas);
+		Field[] fields = obj.getClass().getDeclaredFields();
+		Method[] methods = obj.getClass().getMethods();
+		// 判断某个字段是否有get方法，如果有，则将其设置在request中
+		for (Field field : fields) {
+			String fieldName = field.getName();
+			String upperFirstLetter = fieldName.substring(0, 1).toUpperCase();
+			// 获得和属性对应的getXXX()方法的名字
+			String getMethodName = "get" + upperFirstLetter
+					+ fieldName.substring(1);
+			// 获得和属性对应的getXXX()方法
+			for (Method method : methods) {
+				if (StringUtil.equals(getMethodName, method.getName())) {
+					field.setAccessible(true);
+					try {
+						params.put(field.getName(), field.get(obj));
+					} catch (IllegalArgumentException e) {
+						e.printStackTrace();
+					} catch (IllegalAccessException e) {
+						e.printStackTrace();
+					}
+				}
+			}
+
+		}
+		view.setParameters(params);
+		view.setJsp(clas.getResult());
+		return view;
+	}
+
+
+	private Object invokeAction(ActionClass actionClass) {
+		try {
+			Object obj = actionClass.getAction();
+			Class clas = obj.getClass();
+			Method method = clas.getMethod("execute", null);
+			String result = (String) method.invoke(obj, null);
+			this.setInvokeResult(result, actionClass);
+			actionClass.setAction(obj);
+			return obj;
+		} catch (InvocationTargetException e) {
+			e.printStackTrace();
+			throw new RuntimeException("出现InvocationTargetException异常:"
+					+ e.getMessage());
+		} catch (SecurityException e) {
+			e.printStackTrace();
+			throw new RuntimeException("出现SecurityException异常:"
+					+ e.getMessage());
+		} catch (NoSuchMethodException e) {
+			e.printStackTrace();
+			throw new RuntimeException("出现NoSuchMethodException异常:"
+					+ e.getMessage());
+		} catch (IllegalAccessException e) {
+			e.printStackTrace();
+			throw new RuntimeException("出现IllegalAccessException异常:"
+					+ e.getMessage());
+		} catch (IllegalArgumentException e) {
+			e.printStackTrace();
+			throw new RuntimeException("出现IllegalArgumentException异常:"
+					+ e.getMessage());
+		}
+	}
+
+
+	private void setInvokeResult(String result, ActionClass actionClass) {
+		List<Element> elements = actionClass.getElements();
+		for (Element elem : elements) {
+			Attribute name = XmlUtil.getAttributeByName(elem, "name");
+			if (StringUtil.equals(result, name.getText())) {
+				actionClass.setResult(elem.getText());
+				return;
+			}
+		}
+		throw new RuntimeException("请确定在xml配置文件中是否有名叫 [" + result
+				+ "]　的返回类型结点 ");
+		
+	}
+
+
+	@SuppressWarnings("unchecked")
+	private Object setActionValues(ActionClass actionClass, Map<String, String> params) {
+		try {
+			// 得到Action的Class,并根据无参构造函数生成一个Action对象
+			Class clas = Class.forName(actionClass.getClassName());
+			Object obj = clas.newInstance();
+
+			if (params != null && params.size() > 0) {
+				Iterator<String> it = params.keySet().iterator();
+				while (it.hasNext()) {
+					String key = it.next();
+					String value = params.get(key);
+					String upperFirstLetter = key.substring(0, 1).toUpperCase();
+					// 获得和属性对应的setXXX()方法的名字
+					String setMethodName = "set" + upperFirstLetter
+							+ key.substring(1);
+					Method method = null;
+					// 看看该页面提交的参数名中,是否在Action有set方法
+					try {
+						method = clas.getMethod(setMethodName,
+								new Class[] { String.class });
+					} catch (NoSuchMethodException e) {
+						System.out.println("警告 " + actionClass.getClassName()
+								+ "." + setMethodName + "("
+								+ String.class.getName() + ") 不存在");
+					}
+					if (method != null) {
+						// 如果有set方法,就调用set方法,进行赋值操作
+						method.invoke(obj, new String[] { value });
+					}
+				}
+			}
+			return obj;
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+		} catch (InvocationTargetException e) {
+			e.printStackTrace();
+		} catch (SecurityException e) {
+			e.printStackTrace();
+		} catch (InstantiationException e) {
+			e.printStackTrace();
+		} catch (IllegalAccessException e) {
+			e.printStackTrace();
+		} catch (IllegalArgumentException e) {
+			e.printStackTrace();
+		}
+		throw new RuntimeException("出现未知异常");
+	}
+
+
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	private ActionClass getActionClass(String actionName) {
+		// 得到struts.xml类路径
+		InputStream is = this.getClass().getResourceAsStream(STRUTS_XML_FILE);
+		try {
+			Document doc = XmlUtil.getDocument(is);
+			Element root = XmlUtil.getRoot(doc);
+			// 得到所有的action结点
+			List<Element> actions = XmlUtil.getElementsByName(root, "action");
+			if (actions != null && actions.size() > 0) {
+				for (Element elem : actions) {
+					// 判断某个<result>结点元素的name属性是否与传递过来的actionName相等,如果相等那么将其method属性取出
+					Attribute att = XmlUtil.getAttributeByName(elem, "name");
+					if (StringUtil.equals(att.getText(), actionName)) {
+						Attribute cls = XmlUtil.getAttributeByName(elem, "class");
+						List<Element> results = XmlUtil.getElementsByName(elem, "result");
+						ActionClass actionClass = new ActionClass();
+						actionClass.setClassName(cls.getText());
+						actionClass.setElements(results);
+						return actionClass;
+					}
+				}
+			}
+		} catch (DocumentException e) {
+			e.printStackTrace();
+			throw new RuntimeException("struts.xml 不存在或有误");
+		}
+		throw new RuntimeException("找不到名称为 [" + actionName + "] 的Action映射");
+	}
+
+}
\ No newline at end of file
diff --git a/group09/1271620150/Work02/src/com/coderising/litestruts/StrutsTest.java b/group09/1271620150/Work02/src/com/coderising/litestruts/StrutsTest.java
new file mode 100644
index 000000000..cd946ddf2
--- /dev/null
+++ b/group09/1271620150/Work02/src/com/coderising/litestruts/StrutsTest.java
@@ -0,0 +1,49 @@
+package com.coderising.litestruts;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+
+
+
+
+public class StrutsTest {
+	
+	Struts struts = new Struts();
+
+	@Test
+	public void testLoginActionSuccess() {
+		
+		String actionName = "login";
+        
+		Map<String,String> params = new HashMap<String,String>();
+        params.put("name","test");
+        params.put("password","1234");
+        
+        
+        View view  = struts.runAction(actionName,params);        
+        
+        Assert.assertEquals("/jsp/homepage.jsp", view.getJsp());
+        Assert.assertEquals("login successful", view.getParameters().get("message"));
+        System.out.println(view.getJsp());
+        System.out.println(view.getParameters().get("message"));
+	}
+
+	@Test
+	public void testLoginActionFailed() {
+		String actionName = "login";
+		Map<String,String> params = new HashMap<String,String>();
+        params.put("name","test");
+        params.put("password","123456"); //密码和预设的不一致
+        
+        View view  = struts.runAction(actionName,params);        
+        
+        Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp());
+        Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message"));
+        System.out.println(view.getJsp());
+        System.out.println(view.getParameters().get("message"));
+	}
+}
\ No newline at end of file
diff --git a/group09/1271620150/Work02/src/com/coderising/litestruts/View.java b/group09/1271620150/Work02/src/com/coderising/litestruts/View.java
new file mode 100644
index 000000000..9024d7215
--- /dev/null
+++ b/group09/1271620150/Work02/src/com/coderising/litestruts/View.java
@@ -0,0 +1,23 @@
+package com.coderising.litestruts;
+
+import java.util.Map;
+
+public class View {
+	private String jsp;
+	private Map parameters;
+	
+	public String getJsp() {
+		return jsp;
+	}
+	public View setJsp(String jsp) {
+		this.jsp = jsp;
+		return this;
+	}
+	public Map getParameters() {
+		return parameters;
+	}
+	public View setParameters(Map parameters) {
+		this.parameters = parameters;
+		return this;
+	}
+}
\ No newline at end of file
diff --git a/group09/1271620150/Work02/src/com/coderising/litestruts/struts.xml b/group09/1271620150/Work02/src/com/coderising/litestruts/struts.xml
new file mode 100644
index 000000000..4c6eeabbd
--- /dev/null
+++ b/group09/1271620150/Work02/src/com/coderising/litestruts/struts.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<struts>
+    <action name="login" class="com.coderising.litestruts.LoginAction">
+        <result name="success">/jsp/homepage.jsp</result>
+        <result name="fail">/jsp/showLogin.jsp</result>
+    </action>
+    <action name="logout" class="com.coderising.litestruts.LogoutAction">
+    	<result name="success">/jsp/welcome.jsp</result>
+    	<result name="error">/jsp/error.jsp</result>
+    </action>
+</struts>
\ No newline at end of file
diff --git a/group09/1271620150/Work02/src/com/coderising/litestruts/util/StringUtil.java b/group09/1271620150/Work02/src/com/coderising/litestruts/util/StringUtil.java
new file mode 100644
index 000000000..c6ca4e3d7
--- /dev/null
+++ b/group09/1271620150/Work02/src/com/coderising/litestruts/util/StringUtil.java
@@ -0,0 +1,102 @@
+﻿package com.coderising.litestruts.util;
+
+public class StringUtil {
+
+	/**
+	 * 判断是否为空字符串
+	 * 
+	 * @param str
+	 *            要判断的字符串
+	 * @return 如果不为空返回true
+	 */
+	public static boolean isNotBlank(String str) {
+		return (str != null && !"".equals(str)) ? true : false;
+	}
+
+	/**
+	 * 判断是否为空字符串
+	 * 
+	 * @param str
+	 *            要判断的字符串
+	 * @return 如果为空返回true
+	 */
+	public static boolean isBlank(String str) {
+		return !isNotBlank(str);
+	}
+
+	/**
+	 * 判断是否为空字符串(包括空格)
+	 * 
+	 * @param str
+	 *            要判断的字符串
+	 * @return 如果不为空返回true
+	 */
+	public static boolean isNotEmpty(String str) {
+		return (str != null && !"".equals(str.trim())) ? true : false;
+	}
+
+	/**
+	 * 判断是否为空字符串(包括空格)
+	 * 
+	 * @param str
+	 *            要判断的字符串
+	 * @return 如果为空返回true
+	 */
+	public static boolean isEmpty(String str) {
+		return !isNotEmpty(str);
+	}
+
+	/**
+	 * 字符串比较
+	 * 
+	 * @param src
+	 * @param des
+	 * @return
+	 */
+	public static boolean equals(String src, String des) {
+		if (src == null)
+			return (des == null ? true : false);
+		if (des == null)
+			return (src == null ? true : false);
+		return src.equals(des);
+	}
+
+	/**
+	 * 将String数组变成","号间隔的字符串
+	 * 
+	 * @param str
+	 *            要判断的字符串
+	 * @return 如果为空返回true
+	 */
+	public static String StringArrayToString(String[] str) {
+		StringBuilder sb = new StringBuilder();
+		if (str != null && str.length > 0) {
+			for (String s : str) {
+				if (s != null) {
+					sb.append(s + ",");
+				}
+			}
+			if (sb.length() == 0)
+				return "";
+			return sb.substring(0, sb.length() - 1).toString();
+		}
+		return str[0];
+	}
+
+	/**
+	 * 判断URL后缀是否为.action,如果是的话，提取actionName
+	 * 
+	 * @param servletPath
+	 *            request.getServletPath()
+	 * @return actionName
+	 */
+	public static String parseServletPath(String servletPath) {
+		if (null != servletPath && !"".equals(servletPath)) {
+			if (servletPath.contains(".action")) {
+				return servletPath.substring(servletPath.lastIndexOf("/") + 1,
+						servletPath.indexOf(".action"));
+			}
+		}
+		return "";
+	}
+}
diff --git a/group09/1271620150/Work02/src/com/coderising/litestruts/util/XmlUtil.java b/group09/1271620150/Work02/src/com/coderising/litestruts/util/XmlUtil.java
new file mode 100644
index 000000000..62bd7686d
--- /dev/null
+++ b/group09/1271620150/Work02/src/com/coderising/litestruts/util/XmlUtil.java
@@ -0,0 +1,109 @@
+﻿package com.coderising.litestruts.util;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.List;
+
+import org.dom4j.Attribute;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+
+public class XmlUtil {
+	/**
+	 * 根据Xml文件生成Document对象
+	 * 
+	 * @param file
+	 *            xml文件路径
+	 * @return Document对象
+	 * @throws DocumentException
+	 */
+	public static Document getDocument(File file) throws DocumentException {
+		SAXReader xmlReader = new SAXReader();
+		return xmlReader.read(file);
+	}
+
+	/**
+	 * 根据输入流生成Document对象
+	 * 
+	 * @param is
+	 *            输入流
+	 * @return Document对象
+	 * @throws DocumentException
+	 */
+	public static Document getDocument(InputStream is) throws DocumentException {
+		SAXReader xmlReader = new SAXReader();
+		return xmlReader.read(is);
+	}
+
+	/**
+	 * 根据Document得到根结点
+	 * 
+	 * @param doc
+	 *            Document目录
+	 * @return 根结点
+	 */
+	public static Element getRoot(Document doc) {
+		return doc.getRootElement();
+	}
+
+	/**
+	 * 取出当前结点下的所有子结点
+	 * 
+	 * @param root
+	 *            当前结点
+	 * @return 一组Element
+	 */
+	public static List<Element> getElements(Element root) {
+		return root.elements();
+	}
+
+	/**
+	 * 根据元素名称返回一组Element
+	 * 
+	 * @param root
+	 *            当前结点
+	 * @param name
+	 *            要返回的元素名称
+	 * @return 一组Element
+	 */
+	public static List<Element> getElementsByName(Element root, String name) {
+		return root.elements(name);
+	}
+
+	/**
+	 * 根据元素名称返回一个元素(如果有多个元素的话，只返回第一个)
+	 * 
+	 * @param root
+	 *            当前结点
+	 * @param name
+	 *            要返回的元素名称
+	 * @return 一个Element元素
+	 */
+	public static Element getElementByName(Element root, String name) {
+		return root.element(name);
+	}
+
+	/**
+	 * 根据当前元素,返回该元素的所有属性
+	 * 
+	 * @param root
+	 *            当前结点
+	 * @return 当前结点的所有属性
+	 */
+	public static List<Attribute> getAttributes(Element root) {
+		return root.attributes();
+	}
+
+	/**
+	 * 根据属性名称,返回当前元素的某个属性
+	 * 
+	 * @param root
+	 *            当前结点
+	 * @return 当前结点的一个属性
+	 */
+	public static Attribute getAttributeByName(Element root, String name) {
+		return root.attribute(name);
+	}
+}
