java的反射
java反射的原理
java文件--->class文件--->jvm放入内存进行运行。这个是jvm的运行的原理,但是事实上的操作是。把java文件变成了class的文件,在文件里边有Constructor用于放java里边的构造方法。Field放的是java的字段。Method放的是java的方法。
所以记住:
class
Constructor
Field
Method
获取类文件的类对象
-->类名.class
-->对象.getClass()
-->Class.forName("包名.类名");
获取类的所有的构造方法
public static void main(String[] args) throws Exception {
//获取类
Class classPerson=Class.forName("com.hu.Person");
//通过类获取构造函数,获取有两个参数的构造函数.如果不加参数获取所有的构造函数,接收的是一个数组。
Constructor c=classPerson.getConstructor(String.class,String.class);
//通过构造函数获取一个对象
Person p=(Person) c.newInstance("张三","男");
System.out.println(p);
}
关于属性的操作Field
/**
* 关于属性的操作
* */
//不管是私有的属性还是公有的属性都可以操作的方法是
Field f=classPerson.getDeclaredField("name");
//如果对这个属性进行修改,则需要对属性进行修改的确认。
f.setAccessible(true);
//进行修改
f.set(p,"王五");
System.out.println("------------------"+p);
//获取值f属性的值。表示的p对象中f属性的值。
Object obj=f.get(p);
System.out.println("obj:"+obj);
关于反射的Method
/**
* 方法Method的使用
* */
//获取公有方法和私有方法,不管是公有还是私有多是ok的。除了方法名以外,后边是参数的类型。
Method method=classPerson.getDeclaredMethod("eat",String.class);
//方法的执行。哪个对象的这个方法,后天是参数。
method.invoke(p,"苹果");
//私有方法可以被修改值的确认
method.setAccessible(true);
//方法的返回值
String value=(String)method.invoke(p,"樱桃");
System.out.println(value);
java中的jdbc相关内容
jdbc链接数据库首先需要的是一个数据库的驱动。
这里的java链接的是mysql的数据库。所以用的是mysql的jar包为:mysql-connector-java-5.1.7-bin.jar
具体链接数据库的代码如下:
import java.sql.*;
public class Demo {
public static void demo1() throws ClassNotFoundException, SQLException {
Connection con=null;
Statement stmt=null;
ResultSet rs=null;
//1,加载驱动
Class.forName("com.mysql.jdbc.Driver");
//获取链接
con = DriverManager.getConnection
("jdbc:mysql://localhost:3306/jdbctest","root","a1234567");
//获取执行的Statement
stmt=con.createStatement();
String sql="select * from user";
//执行后获取的结果
rs=stmt.executeQuery(sql);
//循环这个结果集
while (rs.next()){
//获取结果集中的内容,按照结果集中的类型进行获取
System.out.print(rs.getInt("id"));
System.out.print(rs.getString("name"));
System.out.println();
}
//关闭这些资源
if(rs!=null){
rs.close();
}
if(stmt!=null){
stmt.close();
}
if(con!=null){
con.close();
}
}
public static void main(String[] args) {
try {
demo1();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
属性文件的使用
属性文件的文件名和后缀是: fileName.properties
需要用到Properties这个类。生成这个类的实例,然后加载properties文件的流。就可以对文件里边的内容进行相关的操作了。如下的代码:
static{
//加载属性文件并且解析
Properties props=new Properties();
//读取properties文件流,这个差不多是个固定的写法。properties文件放在src的目录下才可以
InputStream is=JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
props.load(is);
} catch (IOException e) {
e.printStackTrace();
}
//props加载流后就可以读取文件里边的内容了
driverClass=props.getProperty("driverClass");
url=props.getProperty("url");
username=props.getProperty("username");
password=props.getProperty("password");
}
jdbc的工具类的实现
如下代码:
package com.hu.jdbc;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
private static final String driverClass;
private static final String url;
private static final String username;
private static final String password;
static{
//加载属性文件并且解析
Properties props=new Properties();
//读取properties文件流,这个差不多是个固定的写法。properties文件放在src的目录下才可以
InputStream is=JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
props.load(is);
} catch (IOException e) {
e.printStackTrace();
}
//props加载流后就可以读取文件里边的内容了
driverClass=props.getProperty("driverClass");
url=props.getProperty("url");
username=props.getProperty("username");
password=props.getProperty("password");
}
//加载驱动
public static void loadDriver(){
try {
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接数据的链接
public static Connection getConnection(){
//先驱动起来
loadDriver();
Connection con= null;
try {
//获取链接数据库的链接
con = DriverManager.getConnection(url,username,password);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return con;
}
/*关闭流,需要写两个方法,这两个方法说加载的方法。一个是查询的方法,一个是增删改的方法*/
//增删改的关闭流的方法
public static void closeStream(Connection con, Statement stmt){
_closeStream(con,stmt);
}
//改的关闭流的方法
public static void closeStream( ResultSet rs,Connection con, Statement stmt){
_closeStream(con,stmt);
if(rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
rs=null;
}
}
private static void _closeStream(Connection con,Statement stmt){
if(stmt!=null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
stmt=null;
}
if(con!=null){
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
con=null;
}
}
}
sql的注入问题
实际的代码如下:
因为sql注入用的是sql的关键字进行传入注册的。
我们使用PreparedStatment这个类。对sql语句先进行预编译,然后再传入进来变量。这时传入进来的变量就起不到作用,因为sql语句已经结构化了,传入进来的只是作为数据而已。
public static boolean login(String name){
boolean flag=false;
PreparedStatement pstmt=null;
Connection con=JDBCUtils.getConnection();
/*防止sql的注入,我们需要用preparedStatement 这个会先对sql语句进行预编译,
然后再传入变量。这样的话即使变量里边有关键字也不会起到效果。因为sql语句的结构固定,传入进来的不管是什么关键字
都只会当做用户名,如果是密码就是只会当做密码
*/
String sql="select * from user where name=?";
try {
//会对上边的sql语句进行预编译
pstmt=con.prepareStatement(sql);
//预编译之后对第几个问号填写什么变量
pstmt.setString(1,name);
//然后执行查询语句,因为之前sql已经预编译了,所以无需再传入sql语句
ResultSet rs=pstmt.executeQuery();
if(rs.next()){
flag=true;
}
//关闭资源
JDBCUtils.closeStream(rs,con,pstmt);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return flag;
}
数据池链接数据库
有点:能够提升性能。客户端到数据池获取链接就可以。因为链接数据库是非常耗费性能的。
我们这里是以c3p0数据池jar包为例。
代码如下:
package com.hu.jdbc;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class C3P0Test {
public static void main(String[] args) {
demo1();
}
public static void demo1(){
PreparedStatement pstmt=null;
Connection conn=null;
ResultSet rs=null;
//创建一个数据池
ComboPooledDataSource dataSource=new ComboPooledDataSource();
//设置这个数据池的配置
try {
//设置驱动
dataSource.setDriverClass("com.mysql.jdbc.Driver");
//设置链接的地址
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbctest");
//设置登录的用户名
dataSource.setUser("root");
//设置登录的密码
dataSource.setPassword("a1234567");
//设置最大的链接数
dataSource.setMaxPoolSize(20);
//设置初始时的链接数
dataSource.setInitialPoolSize(3);
//获取数据库的链接
conn=dataSource.getConnection();
String sql="select * from user";
//生成预编译对象
pstmt=conn.prepareStatement(sql);
//执行sql语句
rs=pstmt.executeQuery();
while (rs.next()){
System.out.print(rs.getInt("id")+" ");
System.out.print(rs.getString("name"));
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(pstmt!=null){
try {
pstmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}