WEB——07JDBC
JDBC
-
Java DataBase Connectivity:java数据库连接
-
学习JDBC主要学习的就是如何通过java语言和数据库软件进行连接并执行SQL语句。
-
JDBC是SUN公司提供的一套用于Java语言和数据库软件进行连接的API(Application Programma Interface)
-
为什么定义JDBC系列接口?
- Sun公司为了避免Java程序员,每一种数据库软件都学习一套全新的方法,通过JDBC接口将方法定义好,让各个数据库厂商根据此接口中方法各自写各自的实现类(驱动),这样java程序员只需要掌握JDBC接口中的方法的调用即可访问任何数据库软件。
-
如何通过JDBC连接数据库
-
创建mave工程
-
复制一下驱动
<!-- 连接MySQL数据库的依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.15</version> </dependency>
-
添加Demo01.java 并在main方法中添加一下代码
package com.kuang.lesson01;
import java.sql.*;
//我的第一个JDBC程序
public class JdbcFirstDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
DriverManager.registerDriver(new Driver());
Class.forName(“com.mysql.jdbc.Driver”);//固定写法//2.用户信息和url String url = "jdbc:mysql://localhost:3306/empdb?useUnicode=true&characterEncoding=UTF8&useSSL=true"; String username = "root"; String password = "root"; //3.连接成功 数据库对象 Connection 代表数据库 Connection connection = DriverManager.getConnection(url, username, password); //4.执行SQL的对象 Statement 执行sql对象 Statement statement = connection.createStatement(); //5.执行SQL的对象 去 执行SQL 可能存在结果,查看返回结果 String sql = "SELECT * FROM emp"; ResultSet resultSet = statement.executeQuery(sql);//返回的结果集 while(resultSet.next()){ System.out.println("id="+resultSet.getObject("id")); System.out.println("name="+resultSet.getObject("name")); System.out.println("job="+resultSet.getObject("job")); System.out.println("manager="+resultSet.getObject("manager")); System.out.println("hiredate="+resultSet.getObject("hiredate")); System.out.println("sal="+resultSet.getObject("sal")); System.out.println("comm="+resultSet.getObject("comm")); System.out.println("dept_id="+resultSet.getObject("dept_id")); System.out.println("======================================"); } //6.释放连接 resultSet.close(); statement.close(); connection.close(); }
}
//1.获取连接的数据库 导包java.sql* 异常抛出 参数:数据库连接地址,用户名,密码
Connection conn = DriverManager.getConnection(
"jdbc:mysql//localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","root"
);
//2.创建执行SQL语句的对象
Statement s = conn.createStatement();
//3.执行SQL语句
s.execute("create table jdbcct1(name varchar(20))");
//4.关闭连接
conn.close();
System.out.println("创建完成");
步骤总结
- 加载驱动
- 连接数据库DriverManager
- 获取执行sql对象 statement
- 获得返回的结果集
- 释放连接
Statement执行SL语句的对象
- .execute(sql):此方法可以执行任意SQL语句,推荐执行DDL(数据库相关和表相关的SQL语句)
- int row = .executeUpdate(sql):此方法执行增删改相关的SQL语句。方法返回值是一个整数 表示生效的行数
- ResultSet rs = .executeQuery(sql);此方法执行查询相关的SQL语句,方法的返回值为结果集对象。里面装着查询回来的所有数据。
package cn.tedu;
import java.sql.*;
public class Demo03 {
public static void main(String[] args) throws SQLException {
Connection conn =
DriverManager.getConnection("jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","root");
System.out.println("连接对象"+conn);
Statement s = conn.createStatement();
//执行插入数据SQL
// s.executeUpdate("insert into emp(name) values('Tom')");
//执行修改数据
// s.executeUpdate("update emp set name='jerry' where name='Tom'");
//执行删除数据
// s.executeUpdate("delete from emp where name='jerry'");
//执行查询
ResultSet rs = s.executeQuery("select * from emp");
//遍历结果集对象 rs.next()让游标往下移动一个 并且返回true或false,true代表有下一条数据。
while(rs.next()){
//通过查询字段的名称获取数据
String name = rs.getString("name");
double sal = rs.getDouble("sal");
//通过查询字段的位置获取数据
String name1 = rs.getString(1);
String sal1 = rs.getString(2);
System.out.println(name + ":" + sal);
System.out.println(name1 + ":" + sal1);
}
conn.close();
System.out.println("执行成功");
}
}
package cn.tedu;
/**
* 将连接的方法抽离出去
*/
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBUtils {
public static Connection getConn() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/empdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","root");
System.out.println("连接对象"+conn);
return conn;
}
}
package cn.tedu;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class Demo04 {
public static void main(String[] args) {
//获取连接 如果下面代码报错 alt+回车 选择 set language level to 7
try (Connection conn = DBUtils.getConn()){
//创建执行SQL语句对象
Statement s = conn.createStatement();
//执行查询
ResultSet rs = s.executeQuery("select * from emp");
while(rs.next()){
String name = rs.getString("name");
System.out.println(name);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
用户输入进行添加数据,类似于简单的注册功能
package cn.tedu;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
System.out.println("请输入英雄名:");
String name = new Scanner(System.in).nextLine();
System.out.println("请输入价格:");
double money = new Scanner(System.in).nextDouble();
try (Connection conn = DBUtils.getConn()){
Statement s = conn.createStatement();
s.executeUpdate("insert into hero values(null,'"+name+"',"+money+")");
System.out.println("添加完成!");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
DBCP
-
DataBaseConnectionPool:数据库连接池
-
作用:可以将数据库连接重用,避免开关频繁导致资源浪费
-
如何使用:找依赖复制到pom文件即可
注册功能:
- 创建user表
use empdb;
create table user(id int primary key auto_increment,username varchar(20),password varchar(20),nick varchar(20));
- 登录的SQL语句:
select count(*) from user where username=‘tom’ and password=‘123456’;
SQL注入
select count(*) from user
where username=‘abcd’ and password=‘’ or ‘1’=‘1’
- 什么是SQL注入?
用户往传值的地方传递进来了SQL语句导致原有SQL语句的逻辑发生改变,从而达到一些非法目的.这个过程叫做SQL注入.
PreparedStatement
-
带有预编译效果的执行SQL语句的对象
-
通过此对象可以解决SQL注入的问题
将此编译SQL语句的时间点从执行提前到创建时,在创建PreparedStatement对象时将SQL语句进行编译,此时用户输入的内容还没有放到SQL语句里面,这是编译的好处是将SQL语句业务逻辑锁死,之后再将用户输入的内容添加进去,这样原有SQL语句的逻辑就不会被用户输入的内容改动,从而避免SQL注入的问题。
PreparedStatement和Statement的区别
- PreparedStatement是预编译的,对于批量处理可以大大提高效率,也叫JDBC存储过程。
- Statement对象,用于对数据库只执行一次性存取的时候。
- Statement每次执行SQL语句,相关数据库都要执行sql语句的编译。
- Statement会出现SQL注入问题,而 PreparedStatement可以避免SQL注入问题。
404状态码
-
意思是客户端找不到服务器的资源,服务器资源包括静态资源和动态资源
-
静态资源404:
- 检查请求的路径拼写是否正确
- 检查静态资源文件是否在static下的正确位置
- 如果路径和文件位置都没有问题,重新编译工程: Build->ReBuild 然后重启工程再测试
-
动态404
- 检查请求的路径拼写是否正确
- 检查Controller类是否创建在了cn.tedu.工程名这个包下面
- 检查@RequestMapping注解里面的路径是否正确,这里的路径必须以/开头
- 如果路径和文件位置都没有问题,重新编译工程: Build->ReBuild 然后重启工程再测试
浏览器发出请求的几种方式
- 在浏览器地址栏中输入请求地址 回车发出请求
- 在html页面中通过超链接发出请求
<h2>通过超链接发出路径</h2>
<!--相对路径会相对于当前页面所出的位置-->
<!--http://localhost:8088/aaa/nnn/index.html
http://localhost:8088/aaa/nnn/hello-->
<a href="hello">相对路径</a>
<!--绝对路径和当前页面所处的位置无关,都是从工程根路径开始-->
<!--http://localhost:8088/aaa/nnn/index.html
http://localhost:8088/hello-->
<a href="/hello">相对路径1</a>
<!--绝对路径-->
<a href="http://localhost:8080/hello">绝对路径</a>
- 在html页面中通过form表单发出请求
<h2>通过form表单发出请求</h2>
<form action="/hello">
<input type="text" name="info">
<input type="submit">
</form>
- 通过前端框架发出异步请求
package cn.tedu.boot11.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@Controller
public class HelloController {
// @RequestMapping("/hello")
// public void hello(HttpServletResponse response) throws IOException {
// System.out.println("服务器接收到请求");
// //设置响应类型告诉客户端浏览器响应的内容是文本或标签 字符集utf-8
// response.setContentType("text/html;charset=utf-8");
// //获取输出对象 异常抛出
// PrintWriter pw = response.getWriter();
// //给客户端响应数据
// pw.print("恭喜你测试成功!");
// pw.close();
@RequestMapping("/hello")
@ResponseBody//注解作用:可以通过返回值给客户端响应数据
public String hello(){
return "恭喜你有测试成功了";
}
}
通过@ResponseBody注解简化响应代码
@RequestMapping("/hello")
@ResponseBody//注解作用:可以通过返回值给客户端响应数据
public String hello(){
return "恭喜你有测试成功了";
端口被占用
- 检查是不是有其它正在运行的工程, 将其关闭后再运行新工程
- 如果没有正在运行的工程,可通过以下几种方式:
- 重启电脑
- 修改工程的端口号
server.port=8081
-
- 通过命令
获取客户端传递过来的参数
- 三种方式接受参数的方式:
1.通过HTTPServletRequest对象挨个获取参数
<h3>第一种</h3>
<form action="/param1">
<input type="text" name="info">
<input type="submit">
</form>
@RequestMapping("/param1")
@ResponseBody
public String param1(HttpServletRequest request){
//获取传递过来的参数
String info = request.getParameter("info");
return "测试成功!info="+info;
}
2.直接在方法的参数列表中声明的方式
<h3>第二种</h3>
<form action="/param2">
<input type="text" name="name" placeholder="名字">
<input type="text" name="age" placeholder="年龄">
<input type="submit">
</form>
@RequestMapping("/param2")
@ResponseBody
public String param2(String name,int age){
return "测试成功!name="+name+"age="+age;
}
3.通过自定义对象直接将多个参数封装
public class User {
private String username;
private String password;
private String nick;
//重写get set toString
}
<h3>第三种</h3>
<form action="/param3">
<input type="text" name="username" placeholder="用户名">
<input type="text" name="password" placeholder="密码">
<input type="text" name="nick" placeholder="昵称">
<input type="submit">
</form>
@RequestMapping("/param3")
@ResponseBody
public String param3(User user){
return "测试成功"+user
}
Web服务软件做了哪些事儿?
-
负责建立底层的网络连接
-
负责根据客户端请求的静态资源文件路径找到对应的对应的静态资源文件并且返回给客户端
-
负责根据客户端请求的动态资源路径找到对的Controller里面的方法并且执行
-
静态资源: 指文件或静态页面(任何人任何时间请求的都是一样的称为静态页面) bmi.html param.html index.html
-
动态资源: 由Controller里面的方法处理的请求称为动态资源请求, /hello /bmi /param1…
SSM三大框架
- Spring:此框架在第四阶段开始接触
- SpringMVC:此框架的作用主要涉及接受请求以及做出响应相关的内容
- Mybatis:此框架负责将JDBC代码进行封装。此阶段只涉及注解相关内容。
SpringBoot
- 也是一个框架,此框架的作用是让程序员更加便捷的在空工程中引入其他框架如果不使用SpringBoot框架创建一个空工程,再引入其它框架,需要在pom.xml文件中添加各种依赖,个别框架还需要添加大量的配置文件,里面书写大量的配置信息,使用SpringBoot框架大大提高了开发效率
注册功能步骤
- 创建SpringBoot工程 , 勾选Web->Spring Web
- 创建完工程后 检查Build 里面是否显示绿色对勾 ,如果有红色报错的话 安装以下步骤解决:
- 右侧边栏maven 里面 点击刷新
- 检查maven是否配置成功
- 如果确定maven配置过, 还是不行, 则找到.m2文件夹下的repository文件夹 删除, 删除完之后再次刷新maven
- 在工程的static里面添加一个index.html首页 里面添加注册和登录的超链接
- 创建reg.html页面 ,里面添加form表单 提交地址为/reg
- 创建controller.UserController 添加reg方法处理 /reg请求
- 因为需要用数据库相关内容, 把jdbc03工程中pom.xml里面引入的两个数据库相关依赖添加到新工程, 还需要把DBUtils.java工具类复制到新工程
- 在reg方法中通过jdbc代码 把传递过来的用户信息保存到数据库中
登录功能步骤
- 在static里面创建login.html页面 添加form表单提交地址为/login
- 在UserController里面创建login方法处理/login请求, 在方法里面通过jdbc代码实现登录流程(和昨天jdbc03里面的登录流程一样)