1. 程式人生 > 其它 >JavaSE03_Day01(下)-反射機制、執行緒池、WebServer專案(十四、十五)、企業開發流程

JavaSE03_Day01(下)-反射機制、執行緒池、WebServer專案(十四、十五)、企業開發流程

一、反射(續)

1.1 通過反射物件進行解析:獲取屬性、方法、構造器

package cn.tedu.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
* 使用反射進行獲取Person物件中的
* 屬性、方法、構造器
* @author cjn
*
*/
public class ReflectDemo03 {

public static void main(String[] args) {
//1.獲取Person的反射物件
Class<Person> cla = Person.class;

/*
* 2.通過反射物件獲取屬性
* getFields() 獲取當前反射物件的可訪問屬性
* getDeclaredFields() 獲取當前放射物件的所有屬性(可訪問+不可訪問)
* getName() 獲取名字
* getType() 獲取型別
*/
Field[] fields = cla.getDeclaredFields();
for (Field field : fields) {
System.out.print(field.getName() + " ");
System.out.println(field.getType().getName());
}

/*
* 3.通過反射物件獲取方法
* getMethods() 獲取反射物件可以進行訪問的方法
* getParameterTypes() 獲取方法物件的引數型別
*/
Method[] methods = cla.getMethods();
for (Method method : methods) {
System.out.println(method.getName() + " ");
Class[] cla1 = method.getParameterTypes();
for (Class c : cla1) {
System.out.println(c.getName());
}
}

/*
* 4. 通過反射物件獲取構造器
* getConstructors() 獲取反射物件的構造器
*/
Constructor[] con = cla.getConstructors();
for (Constructor constructor : con) {
System.out.println(constructor.getName());
}
}

}

1.2 通過反射呼叫無參方法

(1)測試類Animal.java

package cn.tedu.reflect;
/**
* 用於反射呼叫方法的測試類
* @author cjn
*
*/
public class Animal {

public void eat() {
System.out.println("動物餓了要吃飯~");
}

public void run(String name) {
System.out.println(name + "在奔跑!!!");
}

}

(2)反射呼叫無參方法案例

package cn.tedu.reflect;

import java.lang.reflect.Method;
import java.util.Scanner;

/**
* 使用反射呼叫無參方法案例
* @author cjn
*
*/
public class ReflectDemo04 {

public static void main(String[] args) throws Exception {
// Animal animal1 = new Animal();
// animal1.eat();


//1.獲取反射物件
//Class<Animal> cla = Animal.class;
//2.通過反射物件進行例項化物件
//Animal animal = cla.newInstance();
//3.獲取指定方法名字的反射
//Method method = cla.getMethod("eat");
//4.通過例項化的物件呼叫方法 invoke 啟動/呼叫
//method.invoke(animal);

Scanner scan = new Scanner(System.in);
System.out.println("請您輸入需要獲取反射物件的類名:");
String className = scan.nextLine();
System.out.println("請您輸入需要獲取反射的方法名:");
String methodName = scan.nextLine();
//採用獲取反射物件的方式二
Class cla = Class.forName(className);
Object obj = cla.newInstance();
Method method = cla.getMethod(methodName);
method.invoke(obj);
//關閉資源
scan.close();
}

}

測試結果:

請您輸入需要獲取反射物件的類名:
cn.tedu.reflect.Animal
請您輸入需要獲取反射的方法名:
eat
動物餓了要吃飯~

1.3 通過反射呼叫有參方法

package cn.tedu.reflect;

import java.lang.reflect.Method;

/**
* 使用反射呼叫有參方法案例
* @author cjn
*
*/
public class RefelectDemo05 {

public static void main(String[] args) throws Exception{

Class<Animal> cla = Animal.class;
Animal animal = cla.newInstance();
Method method = cla.getMethod("run", String.class);
method.invoke(animal, "斑馬");

/*
* public Object invoke(Object obj, Object... args)
* 觀察該方法的引數,在第二個引數部分,引數型別的後方...表示的是可變引數
* 可變引數是JDK1.5以後提出的,表示該引數可以是0個也可以是1個或者多個。
* 注意事項:...後面的空格可以刪除,但是建議新增
* 一個方法只能有一個可變引數,並且只能放到方法引數的最後方
*/
}

}

二、webserver專案

2.1 版本十四:利用反射機制重構程式碼

  利用反射機制載入Servlet來解決新增不同的業務時,每次都修改ServletContext這個類的問題。

步驟1:在專案下的conf目錄新建servlet.xml檔案

<?xml version="1.0" encoding="UTF-8"?>
<servlets>
<servlet>
<url-pattern>/myweb/reg</url-pattern>
<class-name>cn.tedu.servlets.RegServlet</class-name>
</servlet>
<servlet>
<url-pattern>/myweb/login</url-pattern>
<class-name>cn.tedu.servlets.LoginServlet</class-name>
</servlet>
</servlets>

步驟2:在ServletContext類中先進行解析xml檔案,利用反射機制進行動態的載入這個類並且例項化。

package cn.tedu.core;
import java.io.File;
/**
* 用於儲存伺服器請求路徑對應的Servlet類物件
* @author cjn
*
*/
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;

import cn.tedu.servlets.HttpServlet;
import cn.tedu.servlets.LoginServlet;
import cn.tedu.servlets.RegServlet;

public class ServletContext {
//宣告Map屬性,key用於儲存業務的請求路徑,value用於儲存對應的servlet類的物件
private static Map<String, HttpServlet> servletMapping =
new HashMap<String, HttpServlet>();

/**
* 靜態塊
* 用於在類載入時期進行呼叫initServletMapping方法,
* 並且往屬性Map中新增元素內容
*/
static {
initServletMapping();
}

/**
* 該方法用於向Map屬性中新增具體的資訊資料
*/
private static void initServletMapping() {
//註冊請求路徑和註冊業務處理的業務類的例項儲存到map中
//登入請求路徑和登入業務處理的業務類的例項儲存到map中

try {
SAXReader reader = new SAXReader();
Document document = reader.read(new File("conf/servlet.xml"));
Element root = document.getRootElement();
//獲取根節點中,節點名稱為servlet的所有子元素
List<Element> list = root.elements("servlet");
//遍歷servlet元素,進行獲取裡面的子元素內容
for (Element e : list) {
String key = e.elementText("url-pattern");
String value = e.elementText("class-name");
//對value進行使用反射建立物件
Class cla = Class.forName(value);
HttpServlet servlet = (HttpServlet)cla.newInstance();
servletMapping.put(key, servlet);
}
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 對外提供可以通過業務請求路徑進行獲取業務例項物件的方法
*/
public static HttpServlet getServlet(String path) {
return servletMapping.get(path);
}

}

三、執行緒池

3.1 定義

  執行緒池就是Java中可以進行統一排程和對執行緒進行儲存的容器物件。

3.2 優點

  使用執行緒池可以避免程式中頻繁的對於執行緒物件的建立和銷燬導致程式記憶體開銷過大的現象發生,也就會在使用執行緒池以後減少記憶體資源的浪費,提高整個軟體執行的效能。

3.3 程式碼

package cn.tedu.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* 執行緒池使用案例
* @author cjn
*
*/
public class ThreadPoolDemo {

public static void main(String[] args) {
//建立指定大小的執行緒池物件
ExecutorService threadPool = Executors.newFixedThreadPool(2);

//設定需要進行通過執行緒池分發的任務
for (int i = 1; i < 6; i++) {
//建立任務序列
Runnable runnable = new Runnable() {
public void run() {
Thread t = Thread.currentThread();
System.out.println(t.getName() + ":正在執行任務");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(t.getName() + ":執行任務完畢");
}
};
//將任務指派給執行緒池物件(執行緒池對自動進行排程被管理的執行緒)
threadPool.execute(runnable);
System.out.println("將任務" + i + "指派給執行緒池物件");
}

//關閉執行緒池,如果不關閉執行緒池,一直是等待分配任務的狀態,程式不會終止
threadPool.shutdown();
//如果立即關閉執行緒池,會引發異常。
//threadPool.shutdownNow();
System.out.println("執行緒池關閉");
}

}

四、webserver專案

4.1 版本十五:利用執行緒池重構程式碼

  重構WebServer專案:在WebServer主類中,使用執行緒池來管理處理客戶端請求的ClientHandler。

五、企業開發流程

5.1 階段

  需求分析、需求評審、UI設計、功能開發、專案測試、專案驗收、專案上線、版本迭代、系統運維、產品運營。

5.2 需求分析

  由產品經理進行整理,也需要根據運營部門的提煉和市場部門的相關訴求,共同形成一個可以進行實際操作的需求文件書名的書面文稿,書寫需求文件的目的是用於進行對UI設計、APP移動端、WEB前端、後端開發人員、測試人員一個明確的工作目標和方向。

5.3 需求評審

  主要目的是對於專案的需求達成一個一致的共識。

  需求評審的流程:

  • 發出評審通知

  • 提前下發《需求說明文稿》

  • 產品經理會上陳述專案需求

  • 需求在技術上的可實施性評估

  • 業務架構的合理性評估

  • 使用者的互動邏輯評估

  • 產品經理總結

5.4 UI 設計

  該階段是通過甲方或者外包企業再或者自己公司的UI設計人員完成。(效果圖,資源,layout)

5.5 功能開發

  • 入職時進行組內成員劃分

  • 前端:根據UI設計的頁面進行編寫前端程式碼

       後期根據後端提供的介面,進行資料的繫結

  • 後端:資料庫和資料表設計

    介面文件的書寫

    開發

    單元測試

  • 測試:

    內測

    正式上線之前測試

  • 運維:

    部署上線

5.6 專案測試:

  • 分析測試需求

    • 根據提供的互動原型,效果圖等等進行分析測試需求

  • 指定測試計劃

    • 根據具體的測試需求,需要置頂特定的測試計劃

  • 編寫測試用例

    • 根據上面制定的測試計劃,撰寫測試用例

  • 整合測試

    • 開發人員在內測以後,根據測試用例進行整合測試

5.7 專案驗收

  根據測試工程師整合測試以後,在禪道上沒有進行修改的問題以後,進行申請公司領導和甲方進行驗收。如果和原型中的產品相差較大的時候會驗收不通過。

5.8 專案上線

  由運維人員在雲產品(阿里雲、華為雲、騰訊雲等等)上進行部署專案,專案部署是需要明確當前專案的實際生產環境進行部署。

5.9 版本迭代

  根據產品當前的特徵,不斷的進行版本的迭代任務規劃,往復上面的流程。

5.10 系統運維

  根據特定的產品,進行保證系統的正常執行工作。

5.11 產品運營

  根據產品的特性,由產品經理和運營人員進行推廣,宣傳產品的相關工作。