反射 注解 jdbc xml解析

反射

Class对象: Class类我们可以创建该类的实例(对象)
可以获取该对象的所有属性信息(修饰符、属性名等)、所有方法信息(修饰符、返回值类型、
参数列表等) 一个.class 文件 只有一个 Class对象

获取Class 对象有3种方式
    1. Class.fromName(“xxxx”) 通过包名获取
    2 .类名.class 获取
    3. 通过对象.getClass()来获取

// 加载.class 文件后
		// 字符串 是全路径 (包名 + 类名)
		Class<Emp> clazz = (Class<Emp>) Class.forName("cn.szsxt.demo01.Emp");

		// 方式2
		Class<Emp> clazz1 = Emp.class;

		// 通过对象来获取 Clazz 对象
		Emp emp = new Emp();

		// 泛型的 (范围)上限
		Class<Emp> clazz2 = (Class<Emp>) emp.getClass();

构造器

可以通过 class对象来获取属性 方法构造器

通过class获取构造器

		// 获取class对象 
		Class<Emp> clazz = (Class<Emp>) Class.forName("cn.szsxt.demo01.Emp");
		
	   // 通过构造器 可以和创建对象 
		// 参数类型要给class类型 
		// int类型 不要给成 Integer.class 给 int.class
		Constructor<Emp> c = clazz.getConstructor(int.class,String.class);
		// 通过构造器创建对象 
		Emp emp = c.newInstance(1,"虚竹");
		System.out.println(emp);
		
		//获无参构造器 
		Constructor<Emp> c1 = clazz.getConstructor(null);
		Emp emp2 = c1.newInstance(null);
	   
		//直接用 Class 对象 创建emp对象 
		Emp emp3 = clazz.newInstance(); // 内部是调用了 构造器创建对象
		System.out.println(emp3.hashCode());
		// 可以通过Class 对象 获取 构造器 对象 
		// Constructor  这个对象 封装构造器的信息
		//获取所有的构造器 
		Constructor<Emp>[] cs = (Constructor<Emp>[]) clazz.getConstructors();
		
		//遍历构造器 
		for (Constructor<Emp> c : cs) {
			System.out.println(c);
			
			// getName() 构造器的名字 
		   //  getParameterCount 构造器的参数个数
			//  getModifiers 构造器的修饰符   1 是 public  2 private 4 protected     ...
			System.out.println(c.getName() +""
					+ "\t" +c.getParameterCount() + "\t"+c.getModifiers());
			
		}
		
		System.out.println("获取指定的构造器 ......");
		// 获取值指定的构造器 
		Constructor<Emp> c2 = clazz.getConstructor(null);
		System.out.println(c2);
		System.out.println(c2.getParameterCount());
属性

通过 class 对象操作属性

// 获取class对象
		Class<Emp> clazz = (Class<Emp>) Class.forName("cn.szsxt.demo01.Emp");

		// 先拿到属性
		
		// Field 封装属性的类 
		
//		test01(clazz);
		
		//拿到属性操作属性 
		Field f = clazz.getDeclaredField("name");
		
		writeGetMethode(f);
		
		Emp emp = clazz.newInstance();
		/**
		 *   obj 属性是哪个对象的属性 
		 *   value 是属性的值 
		 */
		// 设置 private 的安全检查 跳过 
		f.setAccessible(true);
		f.set(emp, "程灵素");
/**
	 *  通过属性 拿到set方法
	 * @param f
	 */
	private static void writeGetMethode(Field f) {
		
		StringBuffer sb = new StringBuffer();
		//拿到属性的名字 
		String name = f.getName();
		//拿到类型 
		String fType = f.getType().getName();
		
		// 修饰符的拼接   
		sb.append("public ").append(fType).append(" ");
		//get方法的拼接 
		sb.append("get").append( name.substring(0, 1).toUpperCase().concat(name.substring(1)));
		
		// () 和 换行的拼接 
		sb.append("(").append("){\r\n");
		// return 的拼接 
		sb.append("\treturn ").append(name).append(";\r\n");
		
		sb.append("}");
		System.out.println(sb.toString());
	}
/**
	 *  通过 class对象拿到属性
	 * @param clazz
	 * @throws NoSuchFieldException
	 */
	private static void test01(Class<Emp> clazz) throws NoSuchFieldException {
		// 获取所有的 公开属性
		Field[] fs1 = clazz.getFields();
		// 获取所有的属性 (private + public)
		Field[] fs2 = clazz.getDeclaredFields(); 
		for (Field f : fs2) {

			// getName() 获取属性名称
			// getModifiers() 属性修饰符 
			// getType 属性 的类型 
			System.out.println(f.getName() + "\t" + f.getModifiers() + "\t" + f.getType());
		}
		
		//拿到指定的属性 
		Field f = clazz.getDeclaredField("name");
		System.out.println(f.getName());
	}
方法

通过class 拿到 方法进行操作

public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		// 获取class对象
		Class<Emp> clazz = (Class<Emp>) Class.forName("cn.szsxt.demo01.Emp");
		
//		test012(clazz);
		// obj 是哪个对象 
		Emp emp = clazz.newInstance();
		
		//操作方法 
		Method m = clazz.getDeclaredMethod("setName", String.class);
		/**
		 * invoke 执行方法 
		 * obj  方法的对象 
		 * value 方法的参数
		 */
		m.invoke(emp, "张无忌");
		System.out.println(emp);
		
	}
	
	/**
	 *   通过反射拿到 所有的 方法 
	 * @param clazz
	 * @throws NoSuchMethodException
	 */
	private static void test012(Class<Emp> clazz) throws NoSuchMethodException {
		//拿到所有的方法 
		
		// Method 封装方法的类 (方法描述的类)
		
		Method[] ms = clazz.getDeclaredMethods();
		
		//遍历所有的方法 
		for (Method m : ms) {
			// getName 获取方法的名字 
			// getModifiers 获取方法的修饰符 
			// getParameterCount 获取方法的参数的个数 
			System.out.println(m.getName() + "\t" + m.getModifiers() + "\t" + m.getParameterCount()); 
		  
			// 获取方法返回类型 
			System.out.println(m.getReturnType());
			System.out.println("$$$$$$$$$$");
		}
		
		// 获取指定的方法 
		
		Method m = clazz.getDeclaredMethod("setName", String.class);
		System.out.println(m.getName());
	}
通过反射 把一个map转成对象
public class Demo06 {

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

		Map<String,String> map = new HashMap<>();
		
		map.put("id", "1");
		map.put("name", "赵敏");
		
		Emp emp = new Emp();
		
		Class<Emp> clazz = (Class<Emp>) emp.getClass();
		Emp e = mapToBean(map,clazz);
		System.out.println(e);
		
	}

	/**
	 * 通过反射 把map的值赋值给对象
	 * @param map
	 * @param class1
	 * @return
	 */
	private static Emp mapToBean(Map<String, String> map, Class<Emp> clazz) throws Exception{
		
		//创建对象
		Emp emp = clazz.newInstance();
		
		// 拿到属性
		Field[] fs = clazz.getDeclaredFields();
		
		for (Field f : fs) {
			
			//拿到所有属性名称 
			String key = f.getName();
			
		    //通过属性名称 获取map中的value值 
			String value = map.get(key);
			// 把value 赋值到 对象中 
			// 跳过 private安全检查 
			f.setAccessible(true);
			
			//判断数据类型 
			if (f.getType() == int.class) {
				// 把字符串转成int 
				int id = Integer.valueOf(value);
				f.set(emp, id);
			}
			if (f.getType() == String.class) {
				//直接操作
				f.set(emp, value);
			}
			
		}
		
		return emp;
	}
	
}

注解

注解的作用:
1 标记
2. 编译检查
3. 反射中使用

@Override:
    表示一个方法声明打算重写超类中的另一个方法声明。
     如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。 
      标记这个方法是 父类的方法 

// 标记这个方法  过时了 不推荐使用 
// Date 
@Deprecated

// 告诉编译器 不要警告我这个方法
@SuppressWarnings(“all”)
public void demo03() {
List list = new ArrayList();
}

通过反射 操作注解
public class Demo03 {

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

		// 拿到class对象
		Person p = new Person();
		Class<Person> clazz = (Class<Person>) p.getClass();

		// 通过class 拿到所有的属性
		Field[] fs = clazz.getDeclaredFields();
		for (Field f : fs) {

			// 拿到所有的属性对象
			// 判断属性是否有MyAnnotion 注解
			
			// 判断是否有注解方法的 api 
//			Method m;
//			m.isAnnotationPresent(annotationClass)
//			m.getAnnotation(annotationClass)
			// 类判断是否有注解
//			clazz.isAnnotationPresent(annotationClass)
//			clazz.getAnnotation(annotationClass)
			
			if (f.isAnnotationPresent(MyAnnotion.class)) {

				// 拿到 属性上的注解对象
				MyAnnotion anno = f.getAnnotation(MyAnnotion.class);
				// 通过注解的属性拿到值
				String value = anno.value();
				f.setAccessible(true);
				// 通过反射给属性赋值
				f.set(p, value);

			}
		}
		
		System.out.println(p);

	}
}

Junit

测试类型
1.添加测试环境

  •   add Junit jar 一般的开发工具都继承了 junit 直接添加就可以
    
  •       方式1 手动添加 
    
  •       方式2  添加 junit  注解 报错提示让我 添加依赖的jar 包 
    
public class Demo01Test {
	
	//添加注解后   选中方法  Run as  JunitTest
	// 测试方法 要是 public 不能是 private static
	@Test
	public void demo01() {
		
		// Error   测试 异常 error 
		// Failures 
		// 进度条   如果是绿色 通过(测试成功)
		System.out.println("hello JUnit ");
//		int a= 10/0;
	}
	
	@Test
	public void demo02() {
		
		Demo01 demo01 = new Demo01();
		int add = demo01.add(2, 3);
		System.out.println(add);
		// 断言测试
		// Failures  失败 (预期结果 和实际结果不一致 )
		assertEquals(4, add);	
	}
	
	// @before  测试 方法之前执行的方法  可以在初始方法中初始一些数据 
	// @After   在测试方法执行之后的方法  (释放资源) 
	@Before
	public void init() {
		System.out.println("测试 方法之前执行的方法 ");
	}

	@After
	public void after() {
		System.out.println("释放资源");
	}
}


jdbc

连接 数据库

  1. 加载驱动
  2. 获取连接 (DriverManagaer )
public static void main(String[] args){
		
		// 通过 Class.for(); 加载驱动 (jvm帮我们实现的)
		
		try {
			// 加载数据库的驱动类
			Class.forName("oracle.jdbc.OracleDriver");
			
			//获取连接
			// DriverManager 管理一组 JDBC 驱动程序的基本服务
			// jdbc:oracle:thin:@localhost:1521:orcl
			//  jdbc:oracle:thin 数据库协议 
			//  @localhost:1521 + ip端口
			//  orcl 数据库的名字
			
			// 与特定数据库的连接(会话)
			Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");
			System.out.println(conn);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
  1. 通过conn 拿到 statment (给数据库发送sql指令)
    createStatement()

Statement st=conn.createStatement();

返回数据库中 响应的行数
int update =st.executeUpdate(sql) 执行sql的更新 (删除 修改 插入 )

ResultSet 数据库结果集的数据表
rs = st.executeQuery(sql); // 执行sql 查询语句

rs 可以使用列的索引编号或列的名称获取值
getInt 通过 列名的索引获取int值

if (rs.next()) { //获取下一行数据
//
// }

		多行数据 可以 使用while循环 
		将光标从当前位置向前移一行   判断 下一行是否有数据

批处理

			String insert1 = "insert into t_stu(id,name,info) values (4,'黄蓉','帮主')";
			String insert2 = "insert into t_stu(id,name,info) values (5,'任盈盈','小姐')";
			
			st.addBatch(insert1); //  添加批处理 
			st.addBatch(insert2);
			int[] executeBatch = st.executeBatch(); // 执行批处理


statement 这个接口 容易出现sql的注入 (开发中不要使用这个 接口)

  •     statement  有一个子接口 ps (PreparedStatement)
    

因为sql语句是用String拼接的,那么就可以在条件中 追加一个类似 OR 1=1 这种条件,
让整个判断 和一个结果为true的逻辑 进行 OR运算。
使得结果为true。这就是所谓的SQL注入。

ps的测试 : PreparedStatement优点 PreperedStatement可以避免SQL注入的问题;
PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率;
PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化

使用ps容易出错的地方:

  •   1. ps设置 参数下标容易出错
    
  •   2. ps设置参数 类型和 sql中的参数类型不一致
    
  •   3. int executeUpdate(String sql) 和 executeUpdate() 带参数的是 st的方法 (sql字符拼接 执行时候 需要sql) 不带参数的是ps方法
    
  •   (会提前预编译sql 不要在个sql)
    

rsmd 可以 获取 rs中的 列的信息
ResultSetMetaData rsmd = rs.getMetaData();

数据库连接池
public class Demo01 {

	@Test
	public void demo01() {
		
		// 创建 c3p0 连接池对象 
		ComboPooledDataSource dataSource = new ComboPooledDataSource("oracle");		
		
		// 从 连接池中获取连接 
		Connection conn = null;
		try {
			conn = dataSource.getConnection();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println(conn);
	}
}

事物

开启事务
conn.setAutoCommit(false);

提交事务
conn.commit();

事务回滚
conn.rollback();

// 创建 c3p0 连接池对象
	static ComboPooledDataSource dataSource = new ComboPooledDataSource("oracle");
	
	//创建一个 ThreadLocal 
	static ThreadLocal<Connection> th = new ThreadLocal<Connection>();

	public static Connection getConn() {

		// 从 连接池中获取连接
		// 先 从  th 中获取   如果为空 在重连接池中拿  
		Connection conn = th.get();
		
		if (conn == null) {
			try {
				
				//把 获取的conn 存到  ThreadLocal 中   存在这里 保存 统一线程中 使用统一conn 
				
				// ThreadLocal 内部有个map
				// 通过当前的 线程 作为 key  value 是存的内容 
				
				// 统一线程  key一致  value值 肯定一致  
				conn = dataSource.getConnection();
				//把 conn存到th中 
				th.set(conn);
				
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return conn;
	}

xml的dom4j解析

public class Demo01 {

	@Test
	public void demo01() throws DocumentException {

		// 拿到解析器
		SAXReader saxReader = new SAXReader();

		// 加载 xml 文件 拿到 doc 文档对象
		Document doc = saxReader.read(new File("src/stus.xml"));

		// doc 对象拿到 root节点
		Element rootEle = doc.getRootElement();

		// 获取 root 节点下面的 子节点 elements() 获取所有的root节点下面的子节点
		List<Element> eles = rootEle.elements();

		for (int i = 0; i < eles.size(); i++) {
			Element ele = eles.get(i);
			// 拿到节点的名字
//			System.out.println(ele.getName());

			// 拿到 stu节点的下面的 id 节点
			Element idEle = ele.element("id");
			// 拿到id 节点的 文本
			String id = idEle.getText();
			System.out.println(id);

			// 拿到 stu 下面的name节点
			Element nameEle = ele.element("name");
			// 拿到id 节点的 文本
			String name = nameEle.getText();
			System.out.println(name);

		}
	}
}

<?xml version="1.0" encoding="UTF-8"?>
<stus>
   <stu>
       <id>1</id>
       <name>雷军</name>
       <age>45</age>
   </stu>
   
   <stu>
       <id>2</id>
       <name>马云</name>
       <age>52</age>
   </stu>
</stus>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值