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() 获取反射对象可以进行访问的方法
* getDeclaredMethods() 获取反射对象的所有方法(可访问+不可访问)
* 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个或者多个。
* 注意事项:
* (1)...后面的空格可以删除,但是建议添加
* (2)一个方法只能有一个可变参数,并且只能放到方法参数的最后方
*/
}
}
二、webserver项目
2.1 版本十四:利用反射机制重构代码
利用反射机制加载Servlet来解决添加不同的业务时,每次都修改ServletContext这个类的问题。
步骤1:在项目下的conf目录新建servlet.xml文件
步骤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 产品运营
根据产品的特性,由产品经理和运营人员进行推广,宣传产品的相关工作。