JDBC
JDBC本质
官方定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。
mysql连接包:https://wws.lanzous.com/i2o9Khdf38b
JDBC快速入门
import java.sql.Statement;
import java.sql.Connection;
import java.sql.DriverManager;
public class JdbcTest {
public static void main(String[] args) throws Exception {
//加载注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取数据库连接对象
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/javaee?useSSL=false","root","root");
//定义sql语句
String sql = "insert into admin(username, password) values('root','root')";
//获取执行sql对象的statement
Statement statement = connection.createStatement();
//执行sql
int count = statement.executeUpdate(sql);
System.out.println(count);
statement.close();
connection.close();
}
}
Result集合使用
import java.sql.*;
public class JdbcTest {
public static void main(String[] args){
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/javaee?useSSL=false","root","root");
String sql = "select * from admin";
statement = connection.createStatement();
resultSet = statement.executeQuery(sql);
while (resultSet.next()){
String username = resultSet.getString("username");
String password = resultSet.getString("password");
System.out.println("username: "+username+" & "+"password: "+password);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(statement!=null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
将查询到的数据封装成集合对象
//JdbcTest.java
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class JdbcTest {
public static void main(String[] args){
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
List<Person> list = new ArrayList<Person>();
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/javaee?useSSL=false","root","root");
String sql = "select * from person";
statement = connection.createStatement();
resultSet = statement.executeQuery(sql);
while(resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String sex = resultSet.getString("sex");
Person person = new Person();
person.setId(id);
person.setName(name);
person.setAge(age);
person.setSex(sex);
list.add(person);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(statement!=null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
for (Person person : list) {
System.out.println(person.getId() + " : " + person.getName() + " : " + person.getAge() + " : " + person.getSex());
}
}
}
//Person.java
public class Person {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getSex() {
return sex;
}
private String sex;
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSex(String sex) {
this.sex = sex;
}
}
JDBC 工具类
//jdbc.properties
url = jdbc:mysql://localhost:3306/javaee?useSSL=false
user = root
password = root
driver = com.mysql.jdbc.Driver
//JdbcUtil.java
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
public class JdbcUtil {
private static String url;
private static String user;
private static String password;
static {
Properties properties = new Properties();
try {
//获取配置文件路径
ClassLoader classLoader = JdbcUtil.class.getClassLoader();
URL resource = classLoader.getResource("jdbc.properties");
String src = resource.getPath();
properties.load(new FileReader(src)); //加载配置文件
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
Class.forName(properties.getProperty("driver"));
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
public static void close(Connection connection, Statement statement){
if(statement!=null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (connection!=null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static void close(Connection connection, Statement statement, ResultSet resultSet){
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(statement!=null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
//JdbcTest.java
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class JdbcTest {
public static void main(String[] args){
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
List<Person> list = new ArrayList<Person>();
try {
connection = JdbcUtil.getConnection();
String sql = "select * from person";
statement = connection.createStatement();
resultSet = statement.executeQuery(sql);
while(resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String sex = resultSet.getString("sex");
Person person = new Person();
person.setId(id);
person.setName(name);
person.setAge(age);
person.setSex(sex);
list.add(person);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtil.close(connection, statement, resultSet);
}
for (Person person : list) {
System.out.println(person.getId() + " : " + person.getName() + " : " + person.getAge() + " : " + person.getSex());
}
}
}
//Person.java 等同于上文
PreparedStatement
解决SQL注入问题
import java.sql.*;
import java.util.Scanner;
public class JdbcTest {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
System.out.print("请输入用户名:");
String username = scanner.nextLine();
System.out.print("请输入密码:");
String password = scanner.nextLine();
if (JdbcTest.login(username,password)){
System.out.println("登录成功!");
}else{
System.out.println("账号或密码错误!");
}
}
public static Boolean login(String username, String password){
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = JdbcUtil.getConnection();
String sql = "select * from admin where username = ? and password = ?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,username);
preparedStatement.setString(2,password);
resultSet = preparedStatement.executeQuery();
return resultSet.next();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JdbcUtil.close(connection,preparedStatement,resultSet);
}
return false;
}
}
JDBC事务管理
事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
操作:
- 开启事务
- 提交事务
- 回滚事务
import java.sql.*;
public class JdbcTest {
public static void main(String[] args){
JdbcTest.transfer(1001,1002,6666);
}
public static void transfer(int myId, int id, int money){
Connection connection = null;
PreparedStatement preparedStatement1 = null;
PreparedStatement preparedStatement2 = null;
try {
connection = JdbcUtil.getConnection();
connection.setAutoCommit(false); //开启事务
String sql1 = "update person set money = money - ? where id = ?";
String sql2 = "update person set money = money + ? where id = ?";
preparedStatement1 = connection.prepareStatement(sql1);
preparedStatement2 = connection.prepareStatement(sql2);
preparedStatement1.setInt(1,money);
preparedStatement1.setInt(2,myId);
preparedStatement2.setInt(1,money);
preparedStatement2.setInt(2,id);
preparedStatement1.executeUpdate();
preparedStatement2.executeUpdate();
connection.commit();//提交事务
System.out.println("转账成功!");
} catch (Exception throwables) {
try {
connection.rollback(); //回滚事务
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println("转账失败!");
throwables.printStackTrace();
}finally {
JdbcUtil.close(connection,preparedStatement1);
JdbcUtil.close(null,preparedStatement2);
}
}
}
数据库连接池
一个存放数据库连接的容器(集合)
C3P0连接池:https://wws.lanzous.com/i1oHghdf2fc
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class C3P0 {
public static void main(String[] args) {
DataSource dataSource = new ComboPooledDataSource(); //创建数据库连接池对象
Connection connection = null;
try {
connection = dataSource.getConnection(); //获取连接
System.out.println(connection);
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
if(connection!=null){
try {
connection.close(); //归还连接
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
Druid连接池:https://wws.lanzous.com/igRwlhdf2pc
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
public class Druid {
public static void main(String[] args) {
Connection connection = null;
Properties properties = new Properties();
String src = Druid.class.getClassLoader().getResource("druid.properties").getPath();
try {
properties.load(new FileReader(src)); //装载配置文件
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); //创建数据库连接池对象
connection = dataSource.getConnection();
System.out.println(connection);
} catch (Exception e) {
e.printStackTrace();
}finally {
if(connection!=null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
Druid连接池工具类
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DruidUtil {
private static DataSource dataSource;
static {
Properties properties = new Properties();
String str = DruidUtil.class.getClassLoader().getResource("druid.properties").getPath();
try {
properties.load(new FileReader(str));
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static DataSource getDataSource(){
return dataSource;
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
public static void close(Connection connection, Statement statement){
if(connection!=null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(statement!=null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
public static void close(Connection connection, Statement statement, ResultSet resultSet){
if(connection!=null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(statement!=null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
Spring JDBC
Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发
template快速入门
import org.springframework.jdbc.core.JdbcTemplate;
public class JdbcTemplateTest {
public static void main(String[] args) {
JdbcTemplate template = new JdbcTemplate(DruidUtil.getDataSource());
String sql = "insert into admin values(?,?)";
int count = template.update(sql,"queue", "queue");
System.out.println(count);
}
}
template 详解
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
import java.util.Map;
public class JdbcTest {
JdbcTemplate template = new JdbcTemplate(DruidUtil.getDataSource());
//将查询结果封装成Map 集合,只能用于查询结果只有一条数据的情况
@Test
public void queryMap(){
String sql = "select * from person where id = ?";
Map<String,Object> map = template.queryForMap(sql, 1001);
System.out.println(map);
}
//将查询结果封装成list集合
@Test
public void queryList(){
String sql = "select * from person";
List<Map<String, Object>> maps = template.queryForList(sql);
for(Map map:maps){
System.out.println(map);
}
}
//将查询结果封装成Person对象,定义Person实体类时不能用基本数据类型,因为基本数据类型不能接收null,会报错
public void queryPerson(){
String sql = "select * from person";
List<Person> persons = template.query(sql, new BeanPropertyRowMapper<Person>());
for(Person person: persons){
System.out.println(person);
}
}
//用于执行聚合函数
@Test
public void queryCount(){
String sql = "select count(*) from person";
Long aLong = template.queryForObject(sql, Long.class);
System.out.println(aLong);
}
}
Servlet
什么是Servlet?
Servlet是用来处理客户端请求并产生动态网页内容的Java类。Servlet主要是用来处理或者是存储HTML表单提交的数据,产生动态内容,在无状态的HTTP协议下管理状态信息。
Servlet的生命周期?
Servlet有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。 Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。
<!--第一次访问时创建,负数-->
<!--<load-on-startup>-1</load-on-startup>-->
<!--启动服务器时创建,非负数-->
<!--<load-on-startup>0</load-on-startup>-->
Servlet的体系结构?
Servlet接口 -> GenericServlet抽象类->HttpServlet抽象类
GenericServlet:将Servlet接口中的其他方法进行默认空实现,只将service方法进行抽象
HttpServlet:继承GenericServlet,在service中实现对请求方式的判断,怕生出doGet和doPost方法
Servlet相关配置
- 设置多个访问路径 WebSocket({"/demo1","/demo2","/demo3"})
- 设置多重访问路径 WebSocket("")
- .do 后缀为 .do 才能访问,代表通配符
HTTP协议
- 超文本传输协议
- 基于TCP/IP 协议
- 无状态协议
请求方式
OPTIONS
返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性HEAD
向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。GET
向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在Web Application中,其中一个原因是GET可能会被网络蜘蛛等随意访问。Loadrunner中对应get请求函数:web_link和web_urlPOST
向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。Loadrunner中对应POST请求函数:web_submit_data,web_submit_formPUT
向指定资源位置上传其最新内容DELETE
请求服务器删除Request-URL所标识的资源TRACE
回显服务器收到的请求,主要用于测试或诊断CONNECT
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
注意:
1. 当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Mothod Not Allowed);当服务器不认识或者不支持对应的请求方法时,应返回状态码501(Not Implemented)。
2. HTTP服务器至少应该实现GET和HEAD/POST方法,其他方法都是可选的,此外除上述方法,特定的HTTP服务器支持扩展自定义的方法。
请求头中的referer 告诉服务器,我从哪里来,可以实现 防盗链和统计流量的工作
request 和response 对象的原理
浏览器通过连链接请求消息,Tomcat服务器根据请求消息创建对应的servlet对象,Tomcat服务器会创建request和response对象,request对象用来封装请求的信息,Tomcat将request和response对象传递给service方法,程序员设置响应消息,服务器返回给客户端响应消息。
request 继承体系结构
ServletRequest 接口 -> HttpRequest 接口 ->Tomacat 实现类 RequestFacade
获取请求行数据
- 获取请求方式 String getMethod()
- 获取虚拟目录 String getContextPath()
- 获取servlet路径 String getServletPath()
- 获取get参数请求方式 String getQueryString()
- 获取请求URI String getRequestURI()
- 获取请求URL StringBuffer getRequestURL()
- 获取客户机IP地址 String getRemoteAddr()
- 获取协议及版本 String getProtocol()
URI :统一资源标识符
URL:统一资源定位符
获取请求头数据
String getHeader()
获取请求体数据(只有POST方法才有)
BufferedReader reader = getReader()
ServletInputStream input = getInputSteam()
获取请求参数
String getParameter(String name) 根据参数名称获取参数值
String[] getParameterValue(String name) 根据参数名称获取参数数组,用于复选框
Enumeration<String> getParameterNames() 获取所有请求参数名称
Map<String, String[]> getParameterMap() 获取所有参数的map集合
请求转发
req.getRequestDispatcher("/demo3").forward(req,resp);
特点:
- 浏览器地址路径不发生变化
- 只能转发到当前服务器内部资源中
- 转发是一次请求
共享数据
代表一次请求的范围,一般用于请求转发的时候
req.setAttribute(String, Object) //设置共享数据
req.getAttribute(String) //通过键获取共享数据
req.removeAttribute("name"); //移除共享数据
登录案例
通过Beanutils封装对象,适合多个参数,例如注册。
Map<String, String[]> parameterMap = req.getParameterMap();
User user = new User();
BeanUtils.populate(user,parameterMap);
Beanutils作用 用于封装JavaBean,简化操作
什么是JavaBean : 标准的java类
- 类必须被public 修饰
- 必须提供空参构造器
- 成员变量必须使用private修饰
- 提供公共setter和getter方法
响应状态码
- 1xx 服务器接收客户端消息但是没有接收完成,等待一段时间就会发送1xx状态码询问客户端
- 2xx 成功 代表:200
- 3xx 重定向 代表:302 访问缓存 :304
- 4xx 客户端错误 404: 没有找到对应资源 405:方法不被允许
- 5xx 服务器端错误 500:服务器内部出现异常
response
重定向 resp.sendRedirect 需要加虚拟目录 原理:设置状态码302,设置响应头
String contextPath = req.getContextPath(); //动态获取虚拟路径
重定向特点:
- 地址栏发生变化
- 可以访问其他站点的资源
- 两次请求
- 不可以共享数据
告诉浏览器以什么编码方式解码
resp.setHeader("content-type","text/html;charset=utf-8");
resp.setContentType("text/html;charset=utf-8"); //简化方式