Java数据库小项目00---基础知识
目录
JDBC的简单使用
向JDBC注入攻击
防止注入攻击
自建JDBC工具类
自建工具类优化--使用配置文件
使用数据库连接池优化工具类
JDBC的简单使用
package Test; import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; /*JDBCsun公司提供的一套标准数据库操作规范
* JDBC使用步骤
* 1 注册驱动--告诉JVM使用的是哪一个数据库
* 2 获得连接--使用JDBC中的类完成对MySQL数据库的连接
* 3 获得语句执行平台--通过连接对象获取SQL语句1的执行者对象
* 4 执行sql语句--使用执行者对象向数据库执行SQL语句,并获取执行后的结果
* 5 处理结果
* 6 释放资源
* ----------在使用之前一定要先导入jar包
*/ public class Main{
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1 注册驱动,但查看源码发现这样会注册两次
//DriverManager.registerDriver(new Driver());
//使用反射技术注册,在这里类名可能找不到因此抛出类名查不到的异常
Class.forName("com.mysql.jdbc.Driver"); //2连接数据库 url:数据库 jdbc:jdbc:mysql://连接主机IP:端口号//数据库名
String url ="jdbc:mysql://localhost:3306/mybase";
String username="root";//用户名
String password="123";//密码
//连接,可能连接不到抛出SQL异常
Connection con =DriverManager.getConnection(url, username,password); //3 获得语句执行平台,通过数据库连接对象获得SQL语句的执行者对象,注意导包为sql的包
Statement stat=con.createStatement();
//查询语句
String sql ="Select * from titles"; //4 调用执行者对象方法,执行SQL语句获取结果集
ResultSet rs=stat.executeQuery(sql);
//5 处理结果集
while(rs.next()){
System.out.println(rs.getString("emp_no")+" "+rs.getString("title"));
} //6 释放资源
rs.close();
stat.close();
con.close();
}
}
向JDBC注入攻击
创建数据表
CREATE TABLE users(
username VARCHAR(20),
PASSWORD VARCHAR(10)
); INSERT INTO users VALUES('a',''),('b','');

待注入攻击的代码:
package Test; import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner; /*MySQL注入攻击
* 用户登录案例
*/ public class Main{
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver"); //2连接数据库 url:数据库 jdbc:jdbc:mysql://连接主机IP:端口号//数据库名
String url ="jdbc:mysql://localhost:3306/mybase";
String username="root";//用户名
String password="123";//密码
Connection con =DriverManager.getConnection(url, username,password);
Statement stat=con.createStatement();
//查询语句
Scanner sc=new Scanner(System.in);
String user=sc.next();
String pass=sc.next();
String sql ="Select * from users where username= '"+user+"' and password= '"+pass+"'"; //4 调用执行者对象方法,执行SQL语句获取结果集
ResultSet rs=stat.executeQuery(sql);
System.out.println(sql);
//5 处理结果集
while(rs.next()){
System.out.println(rs.getString("username")+" "+rs.getString("password"));
} //6 释放资源
rs.close();
stat.close();
con.close();
}
}
代码运行结果:

攻击的原理:
利用SQL语句:Select * from users where username= 'a' and password= '1'or'1=1',这样由于最后一个是或运算那么就会显示出来所有的数据,因此在输入时只要想办法凑成这样的形式就可以了。
输入:aa 12'or'1=1 这样便可以完成攻击,即使输入的用户名不对也可以正常登陆。
防止注入攻击
package Test; import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner; /*MySQL防止注入攻击--采用statement的子类preparedstatement
* 还可以用占位符实现增删改查等操作
*/ public class Main{
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver"); //2连接数据库 url:数据库 jdbc:jdbc:mysql://连接主机IP:端口号//数据库名
String url ="jdbc:mysql://localhost:3306/mybase";
String username="root";//用户名
String password="123";//密码
Connection con =DriverManager.getConnection(url, username,password); //查询语句
Scanner sc=new Scanner(System.in);
String user=sc.next();
String pass=sc.next();
//用?占位符代替参数
String sql ="Select * from users where username=? and password= ?";
PreparedStatement pds=con.prepareStatement(sql);
pds.setObject(1, user);
pds.setObject(2, pass);
//4 调用执行者对象方法,执行SQL语句获取结果集
ResultSet rs=pds.executeQuery();
System.out.println(sql);
//5 处理结果集
while(rs.next()){
System.out.println(rs.getString("username")+" "+rs.getString("password"));
} //6 释放资源
rs.close();
pds.close();
con.close();
}
}
自建JDBC工具类
JDBCUtils.class文件
package Test; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; public class JDBCUtils {
private JDBCUtils(){}
private static Connection con; static{
try {
Class.forName("com.mysql.jdbc.Driver");
//2连接数据库 url:数据库 jdbc:jdbc:mysql://连接主机IP:端口号//数据库名
String url ="jdbc:mysql://localhost:3306/mybase";
String username="root";//用户名
String password="123";//密码
con =DriverManager.getConnection(url, username,password);
} catch (Exception e) {
throw new RuntimeException(e+"数据库连接失败!");
}
}
//定义静态方法,返回数据库的连接对象
public static Connection getConnection(){
return con;
} //释放资源
public static void close(Connection con,Statement stat){
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//重载,关闭结果集
public static void close(Connection con,Statement stat,ResultSet rs){
//注意释放的顺序
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
测试代码:
package Test; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import Test.JDBCUtils; public class JDBCTset {
public static void main(String[] args) throws SQLException {
Connection con =JDBCUtils.getConnection();
PreparedStatement pst=con.prepareStatement("SELECT * FROM titles");
ResultSet rs =pst.executeQuery();
while(rs.next()){
System.out.println(rs.getString("title"));
}
//释放资源
JDBCUtils.close(con, pst);
}
}
自建工具类优化--使用配置文件
优化代码
package Test; import java.io.IOException;
import java.io.InputStream; /*在前面的代码中由于数据库用户名,密码直接在静态代码块中,相当于写死了代码,不容易修改
* 因此采用properties配置文件,方便后期维护。配置文件建议放在src下,方便自动拷贝bin目录下
*
*/ import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties; public class JDBCUtils {
private JDBCUtils(){}
private static Connection con;
private static String driverClass;
private static String url;
private static String username;
private static String password;
//放到静态代码块中保证读取配置文件,获取连接只执行一次
static{
try{
readConfig();
//反射
Class.forName(driverClass);
con=DriverManager.getConnection(url,username,password);
}catch(Exception e){
throw new RuntimeException("数据库连接失败!");
} } private static void readConfig() throws IOException{
//通过字节流,使用类加载器读取配置文件的内容
InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("database.properties");
Properties pro = new Properties();
pro.load(in);
driverClass=pro.getProperty("driverClass");
url = pro.getProperty("url");
username=pro.getProperty("username");
password=pro.getProperty("password");
} //定义静态方法,返回数据库的连接对象
public static Connection getConnection(){
return con;
} //释放资源
public static void close(Connection con,Statement stat){
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//重载,关闭结果集
public static void close(Connection con,Statement stat,ResultSet rs){
//注意释放的顺序
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
测试代码
package Test; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import Test.JDBCUtils; public class JDBCTset {
public static void main(String[] args) throws SQLException {
Connection con =JDBCUtils.getConnection();
//当能输出数据库连接时边说用工具类正常了
System.out.println(con);
//由于是简单的测试,因此不用释放资源
//JDBCUtils.close(con, pst);
}
}
使用数据库连接池优化工具类
优化代码:
package Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties; import javax.sql.DataSource; /*
* JDBC连接池工具类,使用连接池专门负责数据库的连接
* JDBC连接池简化了sql语句中的增删改查操作,方便代码编写
*/
import org.apache.commons.dbcp.BasicDataSource; public class JDBCUtils {
private JDBCUtils(){}
private static String driverClass;
private static String url;
private static String username;
private static String password;
private static BasicDataSource datasource =new BasicDataSource();
//放到静态代码块中保证读取配置文件,获取连接只执行一次
static{
try {
readConfig();
//数据库连接配置
datasource.setDriverClassName(driverClass);
datasource.setUrl(url);
datasource.setUsername(username);
datasource.setPassword(password);
//对象连接池中的数量配置,这些配置可以不用配置的
datasource.setInitialSize(10);//初始化的连接数
datasource.setMaxActive(8);//最大连接数
datasource.setMaxIdle(5);//最大空闲数
datasource.setMinIdle(1);//最小空闲数
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} private static void readConfig() throws IOException{
//通过字节流,使用类加载器读取配置文件的内容
InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("database.properties");
Properties pro = new Properties();
pro.load(in);
driverClass=pro.getProperty("driverClass");
url = pro.getProperty("url");
username=pro.getProperty("username");
password=pro.getProperty("password");
} //定义静态方法,返回数据库的连接对象
public static DataSource getDataSource(){
return datasource;
}
}
测试代码:
package Test; import java.sql.SQLException;
import java.util.List; import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler; public class JDBCTset {
private static QueryRunner qr=new QueryRunner(JDBCUtils.getDataSource()); public static void main(String[] args) throws SQLException {
String sql="select * from titles";
//ArrayListHandler:把结果集中的每一行数据都转成一个对象数组,再存放到List中。这是dbutils所特有的
List<Object[]> list =qr.query(sql, new ArrayListHandler());
for(Object[] objs:list){
for(Object obj:objs)
System.out.print(obj+"\t\t");
System.out.println();
}
} }
0
Java数据库小项目00---基础知识的更多相关文章
- Java数据库小项目02--管家婆项目
目录 项目要求 开发环境搭建 工具类JDBCUtils 创建管家婆数据表 项目分层 MainApp层 MainView层 ZhangWuController层 ZhangWuService层 Zhan ...
- Java数据库小项目01--实现用户登录注册
先实现数据库和数据表,检测正常后再做其他的 CREATE TABLE users( username ) NOT NULL, PASSWORD ) NOT NULL); INSERT INTO use ...
- 总结了零基础学习Java编程语言的几个基础知识要点
很多Java编程初学者在刚接触Java语言程序的时候,不知道该学习掌握哪些必要的基础知识.本文总结了零基础学习Java编程语言的几个基础知识要点. 1先了解什么是Java的四个方面 初学者先弄清这 ...
- java Reflection(反射)基础知识讲解
原文链接:小ben马的java Reflection(反射)基础知识讲解 1.获取Class对象的方式 1.1)使用 "Class#forName" public static C ...
- Java中实现异常处理的基础知识
Java中实现异常处理的基础知识 异常 (Exception):发生于程序执行期间,表明出现了一个非法的运行状况.许多JDK中的方法在检测到非法情况时,都会抛出一个异常对象. 例如:数组越界和被0除. ...
- JAVA面试题集之基础知识
JAVA面试题集之基础知识 基础知识: 1.C 或Java中的异常处理机制的简单原理和应用. 当JAVA程序违反了JAVA的语义规则时,JAVA虚拟机就 ...
- 【Java面试】1、基础知识篇
[Java面试]基础知识篇 Java基础知识总结,主要包括数据类型,string类,集合,线程,时间,正则,流,jdk5--8各个版本的新特性,等等.不足的地方,欢迎大家补充. 源码分享:https: ...
- Java IO(1)基础知识——字节与字符
正所谓怕什么来什么,这是知名的“墨菲定律”.Java基础涵盖各个方面,敢说Java基础扎实的人不是刚毕业的学生,就是工作N年的程序员.工作N年的程序员甚至也不敢人人都说Java基础扎实,甚至精通,往往 ...
- Java 面试知识点解析(一)——基础知识篇
前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...
随机推荐
- 对JSON.parse()中存在转义字符的解决以及js中替换函数replace()的认识
在工作中,遇到对页面数据进行转存json格式数据后存储在数据库中.然而在显示数据时遇到无法显示json中的数据,产生的bug 问题抛出: 1.首先认识下,在JSON.parse()将后台传过来的字符串 ...
- Dom4j 生成xml并格式化
Document document = DocumentHelper.createDocument(); //创建root Element root = document.addEle ...
- Disruptor 并发框架
什么是Disruptor Martin Fowler在自己网站上写了一篇LMAX架构的文章,在文章中他介绍了LMAX是一种新型零售金融交易平台,它能够以很低的延迟产生大量交易.这个系统是建立在JVM平 ...
- Python文件操作——读写图片,音频,视频
注意:其实就是将mode="rb"或者mode="wb",因为图片,视频,音频就是二进制进行读取,b 代表binary ,其他的和一般文件操作步骤一样,另外, ...
- 开始学Python 啦 ,持续不断总结中。。(转)快捷键的使用
最重要的快捷键1. ctrl+shift+A:万能命令行2. shift两次:查看资源文件新建工程第一步操作1. module设置把空包分层去掉,compact empty middle packag ...
- js摄像头
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...
- [NOIP2018模拟10.15]比赛报告
闲扯 昨晚又颓到好晚,Yali的降智光环感觉持续至今... 题面好评 T1T3都玩过 逃) T1没看多久就开始写二分+并查集 然后T3看着眼熟想了一个多小时...结果啥都没想出来 赶紧看T2发现还是没 ...
- js中的函数提升和变量提升
变量提升和函数提升: 就是将变量声明或者函数全部代码提升到当前作用域(全局作用域或函数作用域)最开始的部分. JavaScript中函数域为最小域范围:for循环.while循环.if语句.switc ...
- webpack4快速上手
1.在项目根目录cnpm init -y初始化.生成package.json文件 2.在项目里面使用cnpm安装webpack 3.需要在根目录下新建webpack.config.js文件(在其里面配 ...
- 为什么有了uwsgi还要nginx这个“前端”服务器
相信每一个使用nginx+uwsgi+django部署过的人,都感到非常复杂.到底为什么一个项目的发布要经过这么多层级,他们每一层有什么理由存在?这就带大家宏观地看待一下 首先nginx 是对外的服务 ...