- 一,模拟用户登录过程
- --1,需求
- --2,测试
- --3,程序优化
- 二,SQL攻击/注入
- --1,概述
- --2,解决方案
- --3,修改代码
- --4,两种传输器的区别
- 三,练习新的传输器
- --1,测试
- --2,标准的关闭资源
- --3,优化关闭资源
- 封装工具类,提供close()
- 改造代码
- 四,Maven
- --1,概述
- --2,Maven的四个特性
- 仓库repository:
- 坐标
- 依赖
- 命令
- --3,操作步骤
- 1, 下载 / 安装: 解压压缩包就可以了
- 2, 修改settings.xml文件,配置信息(镜像仓库,本地仓库)
- 3, IDEA整合Maven
- --4,使用maven
- 创建Maven工程
- 在IDEA里配置maven
- 五,使用Maven工程开发jdbc程序
- --1,修改pom.xml文件
- --2,编写jdbc的程序
select * from user where name=‘jack’ and pwd=‘123’
如果查到了数据,就可以登录
如果没查到,就登录失败
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
//模拟用户登录的过程--查库
public class Login {
public static void main(String[] args) throws Exception {
//利用工具类 1,注册驱动 2,获取连接
Connection c = JDBCUtils.get();
//3,获取传输器
Statement s = c.createStatement();
//4,执行SQL
String sql ="select * from user where name='jack' and pwd='xyz'";
ResultSet r = s.executeQuery(sql);
//5,解析结果
if( r.next() ){ //判断,查到了就登录
System.out.println("欢迎您回来~");
}else{
System.out.println("登录失败~");
}
//6,关闭资源
r.close();
s.close();
c.close();
}
}
–3,程序优化
动态拼接SQL语句
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
//模拟用户登录的过程--查库
public class Login {
public static void main(String[] args) throws Exception {
//利用工具类 1,注册驱动 2,获取连接
Connection c = JDBCUtils.get();
//3,获取传输器
Statement s = c.createStatement();
//4,执行SQL
System.out.println("请您输入账号:");
String a = new Scanner(System.in).nextLine();
System.out.println("请您输入密码:");
String b = new Scanner(System.in).nextLine();
//中间动态拼接字符串: "+???+"
//String sql ="select * from user where name='jack' and pwd='xyz'";
String sql ="select * from user where name='"+a+"' and pwd='"+b+"'";
ResultSet r = s.executeQuery(sql);
//5,解析结果
if( r.next() ){ //判断,查到了就登录
System.out.println("欢迎您回来~");
}else{
System.out.println("登录失败~");
}
//6,关闭资源
r.close();
s.close();
c.close();
}
}
二,SQL攻击/注入
–1,概述
在SQL语句拼接参数的过程中,出现了特殊的符号# ,改变了SQL的语义
上面的案例中,当用户输入固定的用户名:jack’# 时,不必输入密码竟然可以登录!!!
SELECt * FROM USER WHERe NAME='jack' #' and pwd='xyz' 此时,#之后的条件会被注释掉.–2,解决方案
使用新的传输器PreparedStatement 代替现在的传输器Statement
解决了SQL攻击的问题,把特殊符号#当做一个普通的字符在用,不会当做注释来解析.
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
//模拟用户登录的过程--查库
public class Login {
public static void main(String[] args) throws Exception {
//利用工具类 1,注册驱动 2,获取连接
Connection c = JDBCUtils.get();
//4,执行SQL
System.out.println("请您输入账号:");
String a = new Scanner(System.in).nextLine();
System.out.println("请您输入密码:");
String b = new Scanner(System.in).nextLine();
//SQL的骨架,?叫占位符
String sql = "select * from user where name=? and pwd=?";
//3,获取传输器
PreparedStatement s = c.prepareStatement(sql);
//给?设置值
s.setObject(1,a);//给第一个问号,设置a的值
s.setObject(2,b);//给第二个问号,设置b的值
ResultSet r = s.executeQuery();//直接执行拼好的就行了
//5,解析结果
if( r.next() ){ //判断,查到了就登录
System.out.println("欢迎您回来~");
}else{
System.out.println("登录失败~");
}
//6,关闭资源
r.close();
s.close();
c.close();
}
}
–4,两种传输器的区别
Statement:父接口+SQL攻击+SQL语句需要手动拼接参数(复杂)+低效
PreparedStatement:子接口,用了父接口的所有功能,还进行了优化+解决了SQL攻击+SQL骨架(简化了)+高效
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
//使用新的传输器 向dept表里新增一条数据
public class Test3 {
public static void main(String[] args) throws Exception {
//利用工具类
Connection c = JDBCUtils.get();
//准备SQL骨架
String sql = "insert into dept values(null,?,?)";
//获取新的传输器--高效,安全,SQL简洁
PreparedStatement s = c.prepareStatement(sql);
//设置参数
s.setObject(1,"web前端");
s.setObject(2,"大钟寺");
//executeUpdate()执行增删改的SQL
s.executeUpdate();
//关闭资源
s.close();
c.close();
}
}
–2,标准的关闭资源
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
//使用新的传输器 向dept表里新增一条数据
public class Test3 {
public static void main(String[] args){
Connection c = null; //为了让finally里能够使用变量,所以扩大作用范围
PreparedStatement s = null;
try{
//利用工具类
c = JDBCUtils.get();
//准备SQL骨架
String sql = "insert into dept values(null,?,?)";
//获取新的传输器--高效,安全,SQL简洁
s = c.prepareStatement(sql);
//设置参数
s.setObject(1,"web前端2");
s.setObject(2,"大钟寺2");
//executeUpdate()执行增删改的SQL
s.executeUpdate();
}catch(Exception e){
System.out.println("插入失败~~");
}finally{//第一会被执行--关闭资源
//为了防止空指针异常--加一个非空的判断
if(s != null){
try {
s.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally{
//防止发生异常导致s没被关闭,手动置空,等着GC垃圾回收了.
s = null;
}
}
if(c != null) {
try {
c.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally{
//防止发生异常导致c没被关闭,手动置空,等着GC垃圾回收了.
c = null;
}
}
}
}
}
–3,优化关闭资源
封装工具类,提供close()
package cn.tedu.jdbc;
import java.sql.*;
//封装了一些常用方法,提高代码的复用性--高内聚
public class JDBCUtils {
static public Connection get() throws Exception{
//1,注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2,获取连接
String url = "jdbc:mysql://localhost:3306/cgb211001?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url, "root", "root");
return c; //交给调用者
}
static public void close(ResultSet r, PreparedStatement s,Connection c){
if(r != null){//防止发生空指针异常
try {
r.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally{
//防止发生异常导致r没被关闭,手动置空,等着GC垃圾回收了.
r = null;
}
}
if(s!=null) {
try {
s.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally{
//防止发生异常导致s没被关闭,手动置空,等着GC垃圾回收了.
s = null;
}
}
if(c!=null) {
try {
c.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally{
c = null;
}
}
}
}
改造代码
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
//使用新的传输器 向dept表里新增一条数据
public class Test3 {
public static void main(String[] args){
Connection c = null; //为了让finally里能够使用变量,所以扩大作用范围
PreparedStatement s = null;
try{
//利用工具类
c = JDBCUtils.get();
//准备SQL骨架
String sql = "insert into dept values(null,?,?)";
//获取新的传输器--高效,安全,SQL简洁
s = c.prepareStatement(sql);
//设置参数
s.setObject(1,"web前端2");
s.setObject(2,"大钟寺2");
//executeUpdate()执行增删改的SQL
s.executeUpdate();
}catch(Exception e){
System.out.println("插入失败~~");
}finally {//第一会被执行--关闭资源
JDBCUtils.close(null,s,c);//使用工具类的close()
}
}
}
四,Maven
–1,概述
现在: 下载jar包,管理jar包,编译jar包.
以后: 这套关于jar包的操作全都交给Maven
作用: 是一个项目构建工具,创建Maven项目,maven会自动管理jar包(下载,保存,编译)
远程仓库/中央仓库: 本质就是一个国外网址
镜像仓库: 本质就是一个国内的网址
本地仓库: 自己创建一个文件夹,用来存放 maven从镜像仓库 下载好的jar包(D:Javamavenresp)
用来存放jar包和查找jar包的定位方式.本质上就是一层一层的文件夹
groupId: 组id,通常值是公司的域名
artifactId: 项目id,通常值是项目名称
version: 版本,jar包也有很多版本
可以指定项目需要用到的jar包的坐标,maven会自动关联jar包
命令mysql mysql-connector-java 5.1.32
是Maven的一大特色,结合着IDEA来使用一些命令
clean: 清空缓存
install: 安装
D:Javamavenapache-maven-3.6.32, 修改settings.xml文件,配置信息(镜像仓库,本地仓库)
打开,解压好的 apache-maven-3.6.3confsettings.xml文件
3, IDEA整合Maven –4,使用maven 创建Maven工程D:Javamavenresp ali ali Maven * https://maven.aliyun.com/repository/public/
File - New - Project - 选择Maven - next - 输入工程名 - Finish
–2,编写jdbc的程序4.0.0 cn.tedu cgb2110maven02 1.0-SNAPSHOT mysql mysql-connector-java 5.1.48
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
//利用新的传输器.删除dept里的一条记录
public class Test1 {
public static void main(String[] args) {
Connection c = null;
PreparedStatement p = null;
try {
//1,注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2,获取连接
String url="jdbc:mysql://localhost:3306/cgb211001?characterEncoding=utf8";
c = DriverManager.getConnection(url,"root","root");
//3,获取传输器
String sql ="delete from dept where deptno=?";
p = c.prepareStatement(sql);
//4,执行SQL
p.setObject(1,1);//给1个问号的位置,设置的值是1
p.executeUpdate();//用来执行增删改的SQL,会返回对数据库的影响行数
//5,解析结果集--查询时才会有结果集,这里不需要
}catch (Exception e){
System.out.println("删除失败~~~");
}finally {//6,释放资源
//防止空指针异常
if(p!=null){
try {
p.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(c!=null) {
try {
c.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}



