diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/DownloadThread.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/DownloadThread.java new file mode 100644 index 0000000000..79cb9d5246 --- /dev/null +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/DownloadThread.java @@ -0,0 +1,37 @@ +package com.github.FelixCJF.coding2017.coderising.download; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; + +import com.github.FelixCJF.coding2017.coderising.download.api.Connection; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + + public DownloadThread( Connection conn, int startPos, int endPos){ + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + } + public void run(){ + System.out.println("下载开始"); + try { + byte[] buff = conn.read(startPos, endPos); + //创建一个可随机写入文件 + RandomAccessFile randomAccessFile = new RandomAccessFile(new File("G:/"), "rwd"); + randomAccessFile.seek(startPos); + randomAccessFile.write(buff, 0, buff.length); + randomAccessFile.close(); + + System.out.println("下载结束"); + } catch (IOException e) { + e.printStackTrace(); + } + + } +} diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/FileDownloader.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/FileDownloader.java new file mode 100644 index 0000000000..f9d79fcae4 --- /dev/null +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/FileDownloader.java @@ -0,0 +1,87 @@ +package com.github.FelixCJF.coding2017.coderising.download; + +import com.github.FelixCJF.coding2017.coderising.download.api.Connection; +import com.github.FelixCJF.coding2017.coderising.download.api.ConnectionException; +import com.github.FelixCJF.coding2017.coderising.download.api.ConnectionManager; +import com.github.FelixCJF.coding2017.coderising.download.api.DownloadListener; + +public class FileDownloader { + + String url; + + DownloadListener listener; + + ConnectionManager cm; + + + public FileDownloader(String _url) { + this.url = _url; + + } + + public void execute(){ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + Connection conn = null; + try { + + conn = cm.open(this.url); + int length = conn.getContentLength(); + //自定义线程数量 + int threadCount = 3; + //计算每条线程下载数据的大小 + int blockSize = length/threadCount; + + for (int threadId = 0; threadId <= threadCount; threadCount++) { + + //定义每个线程开始以及结束的下载位置 + // 开始下载的位置 + int startPos = (threadId - 1) * blockSize; + // 结束下载的位置(不包含最后一块) + int endPos = (threadId * blockSize) - 1; + if (threadCount == threadId) { + endPos = length; + } + new DownloadThread(conn,0,length-1).start(); + } + + + } catch (ConnectionException e) { + e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + } + + + + + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + + + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } + + public DownloadListener getListener(){ + return this.listener; + } + +} diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/FileDownloaderTest.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/FileDownloaderTest.java new file mode 100644 index 0000000000..4e96a56459 --- /dev/null +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/FileDownloaderTest.java @@ -0,0 +1,60 @@ +package com.github.FelixCJF.coding2017.coderising.download; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.github.FelixCJF.coding2017.coderising.download.api.ConnectionManager; +import com.github.FelixCJF.coding2017.coderising.download.api.DownloadListener; +import com.github.FelixCJF.coding2017.coderising.download.impl.ConnectionManagerImpl; + + +public class FileDownloaderTest { + boolean downloadFinished = false; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + + String url = "https://www.baidu.com/img/bd_logo.png"; + + FileDownloader downloader = new FileDownloader(url); + + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = true; + } + + }); + + + downloader.execute(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + + + + } + +} diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/api/Connection.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/api/Connection.java new file mode 100644 index 0000000000..e4469d666f --- /dev/null +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/api/Connection.java @@ -0,0 +1,23 @@ +package com.github.FelixCJF.coding2017.coderising.download.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos,int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/api/ConnectionException.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/api/ConnectionException.java new file mode 100644 index 0000000000..657ba9543e --- /dev/null +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/api/ConnectionException.java @@ -0,0 +1,5 @@ +package com.github.FelixCJF.coding2017.coderising.download.api; + +public class ConnectionException extends Exception { + +} diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/api/ConnectionManager.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/api/ConnectionManager.java new file mode 100644 index 0000000000..f131cb622b --- /dev/null +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.github.FelixCJF.coding2017.coderising.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/api/DownloadListener.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/api/DownloadListener.java new file mode 100644 index 0000000000..a14e84acb4 --- /dev/null +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.github.FelixCJF.coding2017.coderising.download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/impl/ConnectionImpl.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..b56384022e --- /dev/null +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/impl/ConnectionImpl.java @@ -0,0 +1,54 @@ +package com.github.FelixCJF.coding2017.coderising.download.impl; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.URLConnection; + +import com.github.FelixCJF.coding2017.coderising.download.api.Connection; + + +public class ConnectionImpl implements Connection{ + + + public URLConnection urlConnection; + + public ConnectionImpl(URLConnection urlConnection) { + this.urlConnection = urlConnection; + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + //设置连接超时属性 + urlConnection.setReadTimeout(5000); + + urlConnection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + + BufferedInputStream inputStream= new BufferedInputStream(urlConnection.getInputStream()); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + byte[] buff = new byte[1024]; + int len = 0; + + while ((len = inputStream.read(buff)) != -1) { + outputStream.write(buff,0,len); + } + byte[] temp = outputStream.toByteArray(); + + inputStream.close(); + outputStream.close(); + + return temp; + } + + @Override + public int getContentLength() { + return urlConnection.getContentLength(); + } + + @Override + public void close() { + urlConnection = null; + } + +} diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/impl/ConnectionManagerImpl.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..771dd30b36 --- /dev/null +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,25 @@ +package com.github.FelixCJF.coding2017.coderising.download.impl; + + +import java.net.URL; + +import com.github.FelixCJF.coding2017.coderising.download.api.Connection; +import com.github.FelixCJF.coding2017.coderising.download.api.ConnectionException; +import com.github.FelixCJF.coding2017.coderising.download.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + Connection connection = null; + try { + + connection = new ConnectionImpl(new URL(url).openConnection()); + + } catch (Exception e) { + e.printStackTrace(); + } + return connection; + } + +} diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/LoginAction.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/LoginAction.java index dcdbe226ed..b803afb24d 100644 --- a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/LoginAction.java +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/LoginAction.java @@ -1,39 +1,43 @@ -package com.coderising.litestruts; - -/** - * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 - * @author liuxin - * - */ -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; - } -} +package com.github.FelixCJF.coding2017.coderising.litestruts; + +/** + * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 + * @author liuxin + * + */ +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; + } + + public void setMessage(String message) { + this.message = message; + } +} \ No newline at end of file diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/Struts.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/Struts.java index 85e2e22de3..32852a36dd 100644 --- a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/Struts.java +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/Struts.java @@ -1,34 +1,84 @@ -package com.coderising.litestruts; - -import java.util.Map; - - - -public class Struts { - - public static View runAction(String actionName, Map 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中的 配置,以及execute的返回值, 确定哪一个jsp, - 放到View对象的jsp字段中。 - - */ - - return null; - } - -} +package com.github.FelixCJF.coding2017.coderising.litestruts; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.dom4j.Document; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; + + + + +public class Struts { + + public static View runAction(String actionName, Map parameters) { + + View view = new View(); + + try { + // 0. 读取配置文件struts.xml + //0.1将xml加载进内存中 + SAXReader reader = new SAXReader(); + Document document = null; + try{ + document = reader.read("src/com/github/FelixCJF/coding2017/coderising/litestruts/struts.xml"); + }catch (Exception e) { + e.printStackTrace(); + } + //0.2读取根元素 + Element rootElement = document.getRootElement(); + //0.3根据根元素获取其子元素 + List actionElements = rootElement.elements("action"); + for (int i = 0; i < actionElements.size(); i++) { + Element actionElement = actionElements.get(i); + if (actionName.equals(actionElement.attributeValue("name"))) { + // 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + String className = actionElement.attributeValue("class"); + Class clazz = Class.forName(className); + Object object = clazz.newInstance(); + // 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 + // ("name"="test" , "password"="1234") , + // 那就应该调用 setName和setPassword方法 + for (Map.Entry entry : parameters.entrySet()) { + PropertyDescriptor descriptor = new PropertyDescriptor(entry.getKey(), clazz); + Method method = descriptor.getWriteMethod(); + method.invoke(object, entry.getValue()); + } + // 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + Method execute = clazz.getMethod("execute"); + String result = (String) execute.invoke(object); + // 3. 通过反射找到对象的所有getter方法(例如 getMessage), + // 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , + Field[] fields = clazz.getDeclaredFields(); + HashMap map = new HashMap<>(); + for (Field field : fields) { + PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz); + Method method = descriptor.getReadMethod(); + Object value = method.invoke(object); + map.put(field.getName(), value); + } + // 放到View对象的parameters + view.setParameters(map); + // 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + // 放到View对象的jsp字段中。 + List resultElements = actionElement.elements("result"); + for (int j = 0; j < resultElements.size(); j++) { + Element resultElement = resultElements.get(j); + if (result.equals(resultElement.attributeValue("name"))) { + view.setJsp(resultElement.getText()); + return view; + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} \ No newline at end of file diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/StrutsTest.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/StrutsTest.java index b8c81faf3c..1157313180 100644 --- a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/StrutsTest.java +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/StrutsTest.java @@ -1,43 +1,43 @@ -package com.coderising.litestruts; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; - - - - - -public class StrutsTest { - - @Test - public void testLoginActionSuccess() { - - String actionName = "login"; - - Map params = new HashMap(); - 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")); - } - - @Test - public void testLoginActionFailed() { - String actionName = "login"; - Map params = new HashMap(); - 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")); - } -} +package com.github.FelixCJF.coding2017.coderising.litestruts; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + + + + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + + String actionName = "login"; + + Map params = new HashMap(); + 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")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + 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")); + } +} \ No newline at end of file diff --git a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/View.java b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/View.java index 07df2a5dab..6d74cb6843 100644 --- a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/View.java +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/View.java @@ -1,23 +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; - } -} +package com.github.FelixCJF.coding2017.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/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/struts.xml b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/struts.xml index a6cfe43e6c..8a5fe95942 100644 --- a/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/struts.xml +++ b/group02/1554421063/src/com/github/FelixCJF/coding2017/coderising/litestruts/struts.xml @@ -1,11 +1,11 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - + + + + /jsp/homepage.jsp + /jsp/showLogin.jsp + + + /jsp/welcome.jsp + /jsp/error.jsp + \ No newline at end of file