Tomcat

1. WEB服务器-Tomcat

1.1 简介

1.1.1 服务器概述

服务器硬件

  • 指的也是计算机,只不过服务器要比我们日常使用的计算机大很多。
image-20231222173448980

服务器,也称伺服器。是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

服务器的构成包括处理器、硬盘、内存、系统总线等,和通用的计算机架构类似,但是由于需要提供高可靠的服务,因此在处理能力、稳定性、可靠性、安全性、可扩展性、可管理性等方面要求较高。

在网络环境下,根据服务器提供的服务类型不同,可分为:文件服务器,数据库服务器,应用程序服务器,WEB服务器等。

服务器只是一台设备,必须安装服务器软件才能提供相应的服务。

服务器软件

服务器软件:基于ServerSocket编写的程序

  • 服务器软件本质是一个运行在服务器设备上的应用程序
  • 能够接收客户端请求,并根据请求给客户端响应数据

image-20231222173608608

1.1.2 Web服务器

Web服务器是一个应用程序(软件),对HTTP协议的操作进行封装,使得程序员不必直接对协议进行操作(不用程序员自己写代码去解析http协议规则),让Web开发更加便捷。主要功能是”提供网上信息浏览服务”。

image-20231222173646117

Web服务器是安装在服务器端的一款软件,将来我们把自己写的Web项目部署到Tomcat服务器软件中,当Web服务器软件启动后,部署在Web服务器软件中的页面就可以直接通过浏览器来访问了。

Web服务器软件使用步骤

  • 准备静态资源
  • 下载安装Web服务器软件
  • 将静态资源部署到Web服务器上
  • 启动Web服务器使用浏览器访问对应的资源

第1步:准备静态资源

  • 在提供的资料中找到静态资源文件

image-20231222173726408

第2步:下载安装Web服务器软件

image-20231222173712179

第3步:将静态资源部署到Web服务器上

image-20231222173719630

第4步:启动Web服务器使用浏览器访问对应的资源

image-20231222173734901

浏览器输入:http://localhost:8080/demo/index.html

image-20231222173752168

上述内容在演示的时候,使用的是Apache下的Tomcat软件,至于Tomcat软件如何使用,后面会详细的讲到。而对于Web服务器来说,实现的方案有很多,Tomcat只是其中的一种,而除了Tomcat以外,还有很多优秀的Web服务器,比如:

image-20231222173802921

Tomcat就是一款软件,我们主要是以学习如何去使用为主。具体我们会从以下这些方向去学习:

  1. 简介:初步认识下Tomcat

  2. 基本使用: 安装、卸载、启动、关闭、配置和项目部署,这些都是对Tomcat的基本操作

  3. IDEA中如何创建Maven Web项目

  4. IDEA中如何使用Tomcat,后面这两个都是我们以后开发经常会用到的方式

首选我们来认识下Tomcat。

1.1.3 Tomcat

Tomcat服务器软件是一个免费的开源的web应用服务器。是Apache软件基金会的一个核心项目。由Apache,Sun和其他一些公司及个人共同开发而成。

由于Tomcat只支持Servlet/JSP少量JavaEE规范,所以是一个开源免费的轻量级Web服务器。

JavaEE规范: JavaEE => Java Enterprise Edition(Java企业版)

avaEE规范就是指Java企业级开发的技术规范总和。包含13项技术规范:JDBC、JNDI、EJB、RMI、JSP、Servlet、XML、JMS、Java IDL、JTS、JTA、JavaMail、JAF

因为Tomcat支持Servlet/JSP规范,所以Tomcat也被称为Web容器、Servlet容器。JavaWeb程序需要依赖Tomcat才能运行。

Tomcat的官网: https://tomcat.apache.org/

image-20231222173824051

1.2 基本使用

1.2.1 下载

直接从官方网站下载:https://tomcat.apache.org/download-90.cgi

image-20231222173909174

Tomcat软件类型说明:

  • tar.gz文件,是linux和mac操作系统下的压缩版本
  • zip文件,是window操作系统下压缩版本(我们选择zip文件)

大家可以自行下载,也可以直接使用资料中已经下载好的资源,

Tomcat的软件程序 :/资料/SpringbootWeb/apache-tomcat-9.0.27-windows-x64.zip

image-20231222173921491

1.2.2 安装与卸载

  • 安装: Tomcat是绿色版,直接解压即安装

在E盘的develop目录下,将apache-tomcat-9.0.27-windows-x64.zip进行解压缩,会得到一个apache-tomcat-9.0.27的目录,Tomcat就已经安装成功。

image-20231222173945563

==注意,Tomcat在解压缩的时候,解压所在的目录可以任意,但最好解压到一个不包含中文和空格的目录,因为后期在部署项目的时候,如果路径有中文或者空格可能会导致程序部署失败。==

打开apache-tomcat-9.0.27目录就能看到如下目录结构,每个目录中包含的内容需要认识下

image-20231222173958288

bin:目录下有两类文件,一种是以.bat结尾的,是Windows系统的可执行文件,一种是以.sh结尾的,是Linux系统的可执行文件。

webapps:就是以后项目部署的目录

  • 卸载:卸载比较简单,可以直接删除目录即可

1.2.3 启动与关闭

启动Tomcat

  • 双击tomcat解压目录/bin/startup.bat文件即可启动tomcat
image-20231222174200134

==注意: tomcat服务器启动后,黑窗口不会关闭,只要黑窗口不关闭,就证明tomcat服务器正在运行==

image-20231222174211676

Tomcat的默认端口为8080,所以在浏览器的地址栏输入:http://127.0.0.1:8080 即可访问tomcat服务器

127.0.0.1 也可以使用localhost代替。如:http://localhost:8080

  • 能看到以上图片中Apache Tomcat的内容就说明Tomcat已经启动成功

==注意事项== :Tomcat启动的过程中,遇到控制台有中文乱码时,可以通常修改conf/logging.prooperties文件解决

image-20231222174239235

关闭: 关闭有三种方式

1、强制关闭:直接x掉Tomcat窗口(不建议)

2、正常关闭:bin\shutdown.bat

3、正常关闭:在Tomcat启动窗口中按下 Ctrl+C

  • 说明:如果按下Ctrl+C没有反映,可以多按几次

1.2.4 常见问题

问题1:Tomcat启动时,窗口一闪而过

  • 检查JAVA_HOME环境变量是否正确配置
image-20231222174300794

问题2:端口号冲突

image-20231222174308683

  • 发生问题的原因:Tomcat使用的端口被占用了。

  • 解决方案:换Tomcat端口号

    • 要想修改Tomcat启动的端口号,需要修改 conf/server.xml文件

注: HTTP协议默认端口号为80,如果将Tomcat端口号改为80,则将来访问Tomcat时,将不用输入端口号。

dom4j入门

一、XML解析方式(面试考点)

其实就是获取元素里面的字符数据或者属性数据

其中常用的两种解析方式:

  • DOM
  • SAX

DOM(document object model)

将整个xml全部读到内存当中,形成树形结构(所有的对象都叫做Node节点。)

整个文档---document对象
属性(标签内描述属性)---attribute对象
所有元素节点(stu/name/age等标签)---element对象
文本(文字等描述)---text对象

SAX(simple API for Xml)

基于事件驱动(读一行解析一行)


二、针对两种解析方式的API(Dom4j 入门)

  • jaxp sun公司(比较繁琐)
  • jdom
  • dom4j 使用广泛

Dom4j 基本用法(导入jar)

1.创建SAXReader对象

1
SAXReader reader=new SAXReader();

2.指定解析的xml原地址(SAXReader调用read方法)

1
Document document=reader.read(new File("src/xml/demo.xml"));  //整个文档叫做document对象

3.获取根元素(文档document对象调用getRootElement方法)

1
Element rootElement=document.getRootElement();

4.根据根元素—下面的元素

element.element  //一个stu元素
element.elements();  //所有stu元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//得到根元素的子元素 age (找两层element)
rootElement.element("stu").element("age");

//得到根元素下面的所有子元素(所有的stu)
List<Element> elements=rootElement.elements(); //泛型(stu/name/age)返回子元素stu

//遍历所有的stu元素
for(Element element :elements)
{
//获取stu元素下面的name元素
String name = element.element("name").getText();
String age = element.element("age").getText();
String desc = element.element("desc").getText();
System.out.println("name="+name+" age+"+age+" desc="+desc);
}

具体实现::

demo.xml内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<stus>
<stu>
<name>李四</name>
<age>15</age>
<desc>我是老大</desc>
</stu>

<stu>
<name>网名</name>
<age>15</age>
<desc>我是老大</desc>
</stu>

</stus>

MainTest.java实现类内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package xml;
import java.io.File;
import java.util.List;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.sun.xml.internal.txw2.Document;
public class MainTest {
public static void main(String[] args){
//1.创建sax读取对象
SAXReader reader=new SAXReader();

try {
//2.指定解析的xml源
org.dom4j.Document document=reader.read(new File("src/xml/demo.xml")); //整个文档叫做document对象

//3.得到元素(element)

//得到根元素 getRootElement
Element rootElement=document.getRootElement();

//得到根元素的子元素 age (找两层element)
rootElement.element("stu").element("age");

//得到根元素下面的所有子元素(所有的stu)
List<Element> elements=rootElement.elements(); //泛型(stu/name/age)返回子元素stu

//遍历所有的stu元素
for(Element element :elements)
{
//获取stu元素下面的name元素
String name = element.element("name").getText();
String age = element.element("age").getText();
String desc = element.element("desc").getText();
System.out.println("name="+name+" age+"+age+" desc="+desc);
}

} catch (DocumentException e) {

e.printStackTrace();
}

}
}

通过泛型遍历所有的文本text内容(getText())


三 、Dom4j中的Xpath入门(导入jar)

dom4j里面支持Xpath的写法。 xpath其实是xml的路径语言,支持我们在解析xml的时候,能够快速定位到具体的某一个元素。

  • 不同之处:

如果需要获得单个的name:

1
2
3
4
5
Dom4j里面是根节点.element()方法:
rootElement.element("stu").element("age");

Xpath里面是根节点.selectSingleNode("具体的//或者/行为")方法;
Element nameElement=(Element) rootElement.selectSingleNode("//name");

如果需要获得所有的name:

1
2
3
4
5
Dom4j里面是根节点.elements()方法:
List<Element> elements=rootElement.elements(); //泛型(stu/name/age)返回子元素stu

Xpath里面是根节点.selectNodes("具体的//或者/行为")方法;
List<Element> elements= rootElement.selectNodes("//name"); //泛型(stu/name/age)返回子元素stu

完整代码如下(xml一样只是展示Xpath的不同):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package xml;
import java.io.File;
import java.util.List;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class XpathTest {
public static void main(String[] args){
//1.创建sax读取对象
SAXReader reader=new SAXReader();

try {
//2.指定解析的xml源
org.dom4j.Document document=reader.read(new File("src/xml/demo.xml")); //整个文档叫做document对象

//3.得到元素(element)

//得到根元素 getRootElement
Element rootElement=document.getRootElement();

//要想使用Xpath,还需要支持的jar(获取的是第一个,只返回一个)
Element nameElement=(Element) rootElement.selectSingleNode("//name");
System.out.println(nameElement.getText());

System.out.println("-----------");

List<Element> elements= rootElement.selectNodes("//name"); //泛型(stu/name/age)返回子元素stu
//遍历所有的stu元素
for(Element element :elements)
{
System.out.println(element.getText());
}


} catch (DocumentException e) {
e.printStackTrace();
}

}
}

两者对比如下:


四、XML约束

  • DTD
  • Schema

XML

eXtendsible markup language 可扩展的标记语言

一、Xml简述和作用

作用:

  1. 可以用来保存数据
  2. 做配置文件(Tomcat)
  3. 可以传输载体(客户端和服务器端之间)

结构分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<stus>
<stu>
<name>lisi</name>
<age>15</age>
<desc>我是老大</desc>
</stu>
</stus>

<stus>
<stu>
<name>liming</name>
<age>17</age>
<desc>我是老二</desc>
</stu>
</stus>


二、定义xml

其实就是一个文件,文件的后缀为 .xml

version : 解析这个xml的时候,使用什么版本的解析器解析
               <?xml version="1.0" ?>

encoding : 解析xml中的文字的时候,使用什么编码来翻译
               <?xml version="1.0" encoding="gbk/UTF-8/big5" ?>

   standalone  : no - 该文档会依赖关联其他文档 ,  yes-- 这是一个独立的文档
               <?xml version="1.0" encoding="gbk" standalone="no" ?>

三、encoding详解(UTF-8 万岁!)

默认文件保存的时候,使用的是GBK的编码保存。

所以要想让我们的xml能够正常的显示中文,有两种解决办法

  1. 让encoding也是GBK 或者 gb2312 .

  2. 如果encoding是 utf-8 , 那么保存文件的时候也必须使用utf-8

  3. 保存的时候见到的ANSI 对应的其实是我们的本地编码 GBK。

为了通用,建议使用UTF-8编码保存,以及encoding 都是 utf-8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<stus>
<stu>
<name>lisi</name>
<age>15</age>
<desc>我是老大</desc>
</stu>
</stus>

<stus>
<stu>
<name>liming</name>
<age>17</age>
<desc>我是老二</desc>
</stu>
</stus>

四、XML元素定义(标签)

类似于h5的标签(<>里面的),但是可以**自己写标签!**(可扩展)。

XML 命名规则:

名称可以含字母、数字以及其他的字符 
名称不能以数字或者标点符号开始 
名称不能以字符 “xml”(或者 XML、Xml)开始 
名称不能包含空格 

五、XML属性定义

定义在元素里面, <元素名称 属性名称=”属性的值”></元素名称>

1
2
3
4
5
6
7
8
9
10
11
12
	
<stus>
<stu id="10086">
<name>张三</name>
<age>18</age>
</stu>

<stu id="10087">
<name>李四</name>
<age>28</age>
</stu>
</stus>

六、注释

与html的注释一样。

<!-- --> 
如: 

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 
        //这里有两个学生
        //一个学生,名字叫张三, 年龄18岁, 学号:10086
        //另外一个学生叫李四  。。。
     -->

xml的注释,不允许放置在文档的第一行。 必须在文档声明的下面


七、CDATA区(服务器给客户端返回)

  • 非法字符

    严格地讲,在 XML 中仅有字符 “<”和”&” 是非法的。
    所以用以下两种方式来代替(<&)
    < <
    & &

如果某段字符串里面有过多的字符, 并且里面包含了类似标签或者关键字的这种文字,不想让xml的解析器去解析。 那么可以使用CDATA.

使用 ![CDATA[]]让<a href="http://www.baidu.com">我爱黑马训练营</a>变为普通字符串

1
<des><![CDATA[<a href="http://www.baidu.com">我爱黑马训练营</a>]]></des>

JDBC中的JAVAEE结构

一、JavaEE结构

客户端-服务器端


二、Dao模式(Data Access Object 数据访问对象)

  • 1.现将数据库和java连接的外接jar导入。将第一讲的类JDBC放入util包内,并且导入properties文件(student改为新的数据库user)。
  • 2.新建数据库为user,建立一个属性有id/name/password的表t_user

  • 3.建立四个包:dao(里面声明数据库访问规则) impl(具体实现早前定义的规则) test(直接使用实现) util
  • 4.dao包内建立一个UserDao的接口
1
2
3
4
5
6
7
8
9
package dao;

import java.sql.SQLException;

public interface UserDao {

void findAll() throws SQLException; //里面写具体要干的方法

}
  • 5.impl包内建立一个UserDaoImp类—>UserDao接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

package impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;
import dao.UserDao;
import util.JDBC;
public class UserDaoImp implements UserDao{ ///实现UserDao的接口 去完成具体实现代码

@Override
public void findAll() throws SQLException {
//1.获得连接对象
java.sql.Connection conn=JDBC.getConn();

//2.根据连接对象,得到statement
java.sql.Statement st=null;
try {
st = conn.createStatement();
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}

//3.执行sql语句,返回ResultSet
String sql="select * from t_user"; //写sql语句
ResultSet rs = st.executeQuery(sql);//返回给ResultSet对象 st连接对象去调用Query方法

//4.遍历
while(rs.next())
{
int id=rs.getInt("id");
String name=rs.getString("name");
String age=rs.getString("password");
System.out.println("id="+id+" name="+name+" age="+age);
}

}
}
  • 6.test包内建立testUserDaoImpl类去使用Junit单元测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package test;
import java.sql.SQLException;
import org.junit.Test;
import dao.UserDao;
import impl.UserDaoImp;
public class testUserDaoImpl {

@Test //点击项目右键选择Junit单元测试的(4)---然后@Test即可
public void testFindAll() throws SQLException
{
UserDao dao=new UserDaoImp(); //面向接口编程
dao.findAll(); //对象调用方法
}

}

  • 7.util包内存放的就是原来写好的JDBC类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package util;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Driver;
import com.mysql.jdbc.Statement;
public class JDBC{
//写在外面好更改
static String driverClass=null;
static String url=null;
static String name=null;;
static String password=null;

static{

//1.创建一个属性配置对象
Properties properties=new Properties();

InputStream is=JDBC.class.getClassLoader().getResourceAsStream("properties"); //类.class.getClassLoader().getResourceAsStream("文件名");
//2.导入输入流
try {
properties.load(is); //load方法加载
} catch (IOException e) {
e.printStackTrace();
}

//3.调用方法读取文档里面的url/name/password等
driverClass=properties.getProperty("driverClass");
url=properties.getProperty("url");
name=properties.getProperty("name");
password=properties.getProperty("password");
}

public static java.sql.Connection getConn(){
java.sql.Connection conn=null;
//1.注册驱动
//DriverManager.registerDriver(new Driver()); //需要一个参数 这个参数是java.sql.jdbc.Driver
try {
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
//2.建立连接(url协议+数据库,user账号,password密码)
try {
conn=DriverManager.getConnection(url,name,password);
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return conn;
}

public static void main(String[] args) throws SQLException{
java.sql.Connection conn = getConn();
//3.创建statement,跟数据库打交道,一定需要这个对象
java.sql.Statement st=conn.createStatement();

//4.执行查询
String sql="select * from s_stu";
ResultSet rs=st.executeQuery(sql);

//5.遍历每一条查询
while(rs.next()) //是否可以移动到下一行
{
int id=rs.getInt("id"); //获得id
String name=rs.getString("name"); //获得name
int age=rs.getInt("age"); //获得age
System.out.println("id="+id+" name="+name+" age="+age);
}

//6.释放
rs.close();
}

public static void release(java.sql.Connection conn, java.sql.Statement st, ResultSet rs) {
// TODO 自动生成的方法存根

}
}
  • 8.properties文件内内容:
1
2
3
4
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost/user
name=root
password=njdxrjgc7777777.

代码实现框架:


三、增加登录界面

1. Dao包的UserDao类增加一个 login方法

1
void login(String username,String password) throws SQLException;

2. impl包的UserDaoImp增加一个实现方法(只是更改了sql语句)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

public void login(String username,String password) throws SQLException {
//1.获得连接对象
java.sql.Connection conn=JDBC.getConn();

//2.根据连接对象,得到statement
java.sql.Statement st=null;
try {
st = conn.createStatement();
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}

//3.执行sql语句,返回ResultSet
String sql="select * from t_user where name='"+ username +"' and password='"+ password +"'"; //写sql语句
ResultSet rs = st.executeQuery(sql);//返回给ResultSet对象 st连接对象去调用Query方法

//4.遍历
if(rs.next())
{
System.out.println("成功");
}
else
{
System.out.println("失败");
}

}

3. test包内的testUserDaoImpl类增加一个调用方法(dao.login(“xxx”,”yyy”))

1
dao.login("admin","10086");


四、statement安全问题

执行原理:是进行拼接sql语句的过程(先拼接,后执行)


五、PreparedStatement

更改目录代码(主要是2.3步更改)

  • 原来的statement是先创建statement对象,然后书写sql语句最后进行调用executeQuery()方法
  • 现在的preparedstatement是先写sql语句(判定条件都写?),然后调用方法去检验,之后使用setString()方法进行,最后调用executeQuery()方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public void login(String username,String password) throws SQLException {
//1.获得连接对象
java.sql.Connection conn=JDBC.getConn();

//2.预先对sql语句校验(?把它认为是字符串)
String sql="select * from t_user where name=? and password=?"; //写sql语句 "
java.sql.PreparedStatement ps=conn.prepareStatement(sql);
//?对应的索引从1开始
ps.setString(1, username);
ps.setString(2, password);

ResultSet rs = ps.executeQuery();//返回给ResultSet对象 st连接对象去调用Query方法

//4.遍历
if(rs.next())
{
System.out.println("成功");
}
else
{
System.out.println("失败");
}

}

  • 总结:

1. 先写sql语句(增删查改)

1
String sql="select * from t_user where name=? and password=?";  //写sql语句    "

2. 预先对sql语句校验(?把它认为是字符串)

1
2
3
java.sql.PreparedStatement  ps=conn.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, password);

3. 调用方法进行执行

1
ResultSet rs = ps.executeQuery();

六、利用preparedstatment—-增删查改

1. dao包里面的UserDao类里面写增删查改的方法

1
2
3
4
5
6
7
8
9
10
11
12
public interface UserDao {

void update(int id , String name); //更新(利用id去更新)

void delete(int id); //删除(利用id去删除)

void insert(String userName , String password); //插入(id可以通过sql语句自己写)

void findAll(); //查询展示所有的

void login(String username , String password); //登录
}

2. impl包里面的UserDaoImpl类里面写增删查改的具体实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
public class UserDaoImpl implements UserDao{

@Override
public void findAll() {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
//1. 获取连接对象
conn = JDBCUtil.getConn();
//2. 创建statement对象
st = conn.createStatement();
String sql = "select * from t_user";
rs = st.executeQuery(sql);

while(rs.next()){
String userName = rs.getString("username");
String password = rs.getString("password");
System.out.println(userName+"="+password);
}

} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.release(conn, st, rs);
}
}

@Override
public void login(String username, String password) { //登录

Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
//1. 获取连接对象
conn = JDBCUtil.getConn();
//2. 创建statement对象
String sql = "select * from t_user where username=? and password=?";

//预先对sql语句执行语法的校验, ? 对应的内容,后面不管传递什么进来,都把它看成是字符串。 or select
PreparedStatement ps = conn.prepareStatement(sql);
//? 对应的索引从 1 开始。
ps.setString(1, username);
ps.setString(2, password);

rs = ps.executeQuery();
if(rs.next()){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}

} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.release(conn, st, rs);
}
}




@Override
public void insert(String userName, String password) { //插入
Connection conn = null;
PreparedStatement ps = null;

try {
conn = JDBCUtil.getConn();
String sql = "insert into t_user values(null , ? , ?)";
ps = conn.prepareStatement(sql);

//给占位符赋值 从左到右数过来,1 代表第一个问号, 永远你是1开始。
ps.setString(1, userName);
ps.setString(2, password);


int result = ps.executeUpdate();
if(result>0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtil.release(conn, ps);
}
}

@Override
public void delete(int id) { //删除
Connection conn = null;
PreparedStatement ps = null;

try {
conn = JDBCUtil.getConn();
String sql = "delete from t_user where id = ?";
ps = conn.prepareStatement(sql);

//给占位符赋值 从左到右数过来,1 代表第一个问号, 永远你是1开始。
ps.setInt(1, id);


int result = ps.executeUpdate();
if(result>0){
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtil.release(conn, ps);
}
}

@Override
public void update(int id, String name) { //更新
Connection conn = null;
PreparedStatement ps = null;

try {
conn = JDBCUtil.getConn();
String sql = "update t_user set username=? where id =?";
ps = conn.prepareStatement(sql);

//给占位符赋值 从左到右数过来,1 代表第一个问号, 永远你是1开始。
ps.setString(1, name);
ps.setInt(2, id);


int result = ps.executeUpdate();
if(result>0){
System.out.println("更新成功");
}else{
System.out.println("更新失败");
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtil.release(conn, ps);
}
}


}

3. test包里面的TestUserDaoImpl类里面写增删查改的直接调用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class TestUserDaoImpl {
@Test
public void testInsert(){ //测试插入

UserDao dao = new UserDaoImpl();

dao.insert("aobama", "911");
}

@Test
public void testUpdate(){ //测试更新

UserDao dao = new UserDaoImpl();

dao.update(2, "itheima");
}

@Test
public void testDelete(){ //测试删除

UserDao dao = new UserDaoImpl();

dao.delete(30);
}

@Test
public void testFindAll(){ //测试查询所有

//面向父类编程 接口编程
UserDao dao = new UserDaoImpl(); //体现多态的特征
dao.findAll();
}

@Test
public void testLogin(){
UserDao dao = new UserDaoImpl();
dao.login("admin", "100234khsdf88' or '1=1");
}

}

数据库的CRUD

数据库(sql)—-增删查改(CRUD)

  • 开始的数据库:

其中四个增删查改的操作

  • insert(插入)

       //插入全部
    insert into t_stu (id,name,age) 
    values ('4','wangqiang',28)    
       //插入一部分
    insert into t_stu (name,age) 
    values ('wangqiang',28)
  • delete(删除)

    delete 
    from s_stu
    where id=6    
  • query(查询)

    select  */列/行
    from t_stu(表)
    where  name='wangwu'
  • update(更新)

    update t_stu(表)
    set id=6
    where age=5;

一、查询

查询的sql语句:

1
String sql="select * from s_stu where name='lisi'";  //写sql语句

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package CRUDlianxi;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;
public class MainTest {
public static void main(String[] args) throws SQLException {

//1.获得连接对象
java.sql.Connection conn=JDBC.getConn();

//2.根据连接对象,得到statement
java.sql.Statement st=conn.createStatement();

//3.执行sql语句,返回ResultSet
String sql="select * from s_stu where name='lisi'"; //写sql语句
ResultSet rs=st.executeQuery(sql); //返回给ResultSet对象 st连接对象去调用Query方法

//4.遍历
while(rs.next()) //判断是不是有下一个
{
int id=rs.getInt("id");
String name=rs.getString("name");
int age=rs.getInt("age");
System.out.println("id="+id+" name="+name+" age="+age);
}

}
}

查询结果如下:


二、修改

  主要是更改为st调用executeUpdate(sql)方法,结果返回给一个整数rs,判断rs得知结果修改正确与否

1
2
3
4
5
6
7
8
9
10
11
12
//3.执行sql语句,返回ResultSet
String sql="update s_stu set id=22 where age=18"; //写sql语句
int rs=st.executeUpdate(sql); //返回给ResultSet对象 st连接对象去调用Query方法

//4判断是不是修改正确
if(rs >0 ){
System.out.println("更新成功");
}
else
{
System.out.println("更新失败");
}

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package CRUDlianxi;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;
public class MainTest {
public static void main(String[] args) throws SQLException {

//1.获得连接对象
java.sql.Connection conn=JDBC.getConn();

//2.根据连接对象,得到statement
java.sql.Statement st=conn.createStatement();

//3.执行sql语句,返回ResultSet
String sql="update s_stu set id=22 where age=18"; //写sql语句
int rs=st.executeUpdate(sql); //返回给ResultSet对象 st连接对象去调用Query方法

//4判断是不是修改正确
if(rs >0 ){
System.out.println("更新成功");
}
else
{
System.out.println("更新失败");
}

}
}

修改结果如下:

修改之后数据库的样子:


三、删除

  和修改操作相比只是sql语句不同,调用的方法都相同。

1
2
3
4
5
6
7
8
9
10
11
//3.执行sql语句,返回ResultSet
String sql="delete from s_stu where id=22"; //写sql语句
int result = st.executeUpdate(sql);//返回给ResultSet对象 st连接对象去调用Query方法

//4判断是不是删除正确
if(result >0 ){
System.out.println("删除成功");
}
else{
System.out.println("删除失败");
}

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package CRUDlianxi;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;
public class MainTest {
public static void main(String[] args) throws SQLException {

//1.获得连接对象
java.sql.Connection conn=JDBC.getConn();

//2.根据连接对象,得到statement
java.sql.Statement st=conn.createStatement();

//3.执行sql语句,返回ResultSet
String sql="delete from s_stu where id=22"; //写sql语句
int result = st.executeUpdate(sql);//返回给ResultSet对象 st连接对象去调用Query方法

//4判断是不是删除正确
if(result >0 ){
System.out.println("删除成功");
}
else{
System.out.println("删除失败");
}

}
}

删除结果如下:

删除之后数据库的样子:


四、插入

  和修改操作相比只是sql语句不同,调用的方法都相同。

1
2
3
4
5
6
7
8
9
10
//3.执行sql语句,返回ResultSet
String sql="insert into s_stu (id,name,age) values (66,'wangqiang',28)"; //写sql语句
int result = st.executeUpdate(sql);//返回给ResultSet对象 st连接对象去调用Query方法

//4判断是不是删除正确
if(result >0 ){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package CRUDlianxi;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;
public class MainTest {
public static void main(String[] args) throws SQLException {

//1.获得连接对象
java.sql.Connection conn=JDBC.getConn();

//2.根据连接对象,得到statement
java.sql.Statement st=conn.createStatement();

//3.执行sql语句,返回ResultSet
String sql="insert into s_stu (id,name,age) values (66,'wangqiang',28)"; //写sql语句
int result = st.executeUpdate(sql);//返回给ResultSet对象 st连接对象去调用Query方法

//4判断是不是删除正确
if(result >0 ){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}

}
}

插入结果如下:

插入之后数据库的样子:


代码步骤总结:

  1. 需要去拷贝JDBC文件内的JDBC类还有properties文件(有url/name/password等),之后导入mysql和java的jar连接包。

  1. 根据类.getConn()方法—>连接对象conn
    java.sql.Connection conn=JDBC.getConn();
  2. 根据对象调取createStatement()方法—>关键对象st
    java.sql.Statement st=conn.createStatement();
  3. 然后编写sql语句—>关键对象st调用相关方法(SQL)
    1
    2
    String sql="xxxx";  //写sql语句		
    int result = st.executeUpdate(sql);//返回给ResultSet对象 st连接对象去调用Query方法
  4. 按查询的话可以遍历输出答案,如果是其他三种就可以让返回int整数判断是不是成功修改。
if(result >0 )
{
    System.out.println("添加成功");
}
else
{    
    System.out.println("添加失败");
}

数据库

一、数据库分类

  1. mysql:开源免费(.7之前)的适用于中小型企业的免费数据库。最后sun公司被oracle收购。
  2. mariadb:有mysql创作人提出的相当于mysql开源版本的一个分支(命令基本一样)
  3. oracle:甲骨文公司的商业收费软件,适用于大型电商网站
  4. db2:IBM公司解决软件和硬件方案的服务器架构,适用于银行系统
  5. sql server:windows里面的政府网站asp.net,大学教学使用(图形化界面)
  6. sybase:被淘汰

二、关系型数据库和非关系型数据库区别

  • 非关系型数据库(NOSQL)
    key:value
  • 关系型数据库(E-R图)
  1. 实体:方框
  2. 属性:椭圆
  3. 关系:菱形


三、mysql的SQL语句(结构化查询语言)

DDL(数据定义语言):定义数据库、数据表它们的结构

1
create(创建) drop(删除) alter(修改)

DML(数据操纵语言):主要对数据

1
insert(插入) update(修改) delete(删除)

DCL(数据控制语言):定义访问权限

1
grant(授权)

DQL(数据查询语言)

1
select(查询) from子句 where子句

四、数据库的概述图

JDBC的工具类

一、释放资源

  主要是在所有的操作结束之后,需要释放资源(close()方法)

1
2
3
4
5
6
7
8
9
10
11
12
13

if (rs != null) //添加一个判断rs对象是不是空(防止一行都没有)
{
try
{
rs.close();
}
catch (SQLException sqlEx)
{
} // ignore

rs = null;
}

二、 驱动注册#

  原来的DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Driver 这个类里面有静态代码块,一上来就执行了,所以等同于我们注册了两次驱动。 其实没这个必要的。
//静态代码块 —> 类加载了,就执行。

最后形成以下代码即可。
Class.forName("com.mysql.jdbc.Driver");    
1
2
3
4
5
6
7
8
//1.注册驱动
//DriverManager.registerDriver(new Driver()); //需要一个参数 这个参数是java.sql.jdbc.Driver
try {
Class.forName("com.mysql.jdbc.Driver"); //直接使用forName方法
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}

三、连接对象整合

  其实就是把1注册驱动和2建立连接拿出来专门做一个getconn()方法,方便将前两步整合在一起。第三步开始只需要调用方法得到结果就可以。

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package lianxi;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Driver;
import com.mysql.jdbc.Statement;
public class JDBC{

//写在外面好更改
static String url="jdbc:mysql://localhost/student";
static String name="root";
static String password="njdxrjgc7777777.";

public static java.sql.Connection getConn(){ //新建一个方法整合
java.sql.Connection conn=null;

//1.注册驱动
//DriverManager.registerDriver(new Driver()); //需要一个参数 这个参数是java.sql.jdbc.Driver
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}

//2.建立连接(url协议+数据库,user账号,password密码)
try {
conn=DriverManager.getConnection(url,name,password);
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return conn;
}

public static void main(String[] args) throws SQLException{
java.sql.Connection conn = getConn(); //创建conn去得到刚才那个方法的结果
//3.创建statement,跟数据库打交道,一定需要这个对象
java.sql.Statement st=conn.createStatement();

//4.执行查询
String sql="select * from s_stu";
ResultSet rs=st.executeQuery(sql);

//5.遍历每一条查询
while(rs.next()) //是否可以移动到下一行
{
int id=rs.getInt("id"); //获得id
String name=rs.getString("name"); //获得name
int age=rs.getInt("age"); //获得age
System.out.println("id="+id+" name="+name+" age="+age);
}

//6.释放
rs.close();
}
}

最终代码如下:


四、创建properties

  将url,name,password等放在配件内(代码如上的完整代码为例)

src下新建一个文件(properties)里面存放这几条内容

1
2
3
4
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost/student"
name=root
password=njdxrjgc7777777.

创建文件目录:


五、读取properties

  主要是要将driverClass/url/name/password改到文档里之后,将四个写成static的null然后写一个static{}去加载文档内容。

主要步骤:

  1. 创建一个Properties属性配置对象。
  2. 先创建一个InputStream对象,然后调动Properties对象的load()方法去加载输入流。
  3. 使用Properties对象的getProperties()方法获取 url/name等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//写在外面好更改
static String driverClass=null;
static String url=null;
static String name=null;;
static String password=null;

static{

//1.创建一个属性配置对象
Properties properties=new Properties();

InputStream is=JDBC.class.getClassLoader().getResourceAsStream("properties"); //类.class.getClassLoader().getResourceAsStream("文件名");
//2.导入输入流
try {
properties.load(is); //load方法加载
} catch (IOException e) {
e.printStackTrace();
}

//3.调用方法读取文档里面的url/name/password等
driverClass=properties.getProperty("driverClass");
url=properties.getProperty("url");
name=properties.getProperty("name");
password=properties.getProperty("password");
}

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package lianxi;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Driver;
import com.mysql.jdbc.Statement;
public class JDBC{
//写在外面好更改
static String driverClass=null;
static String url=null;
static String name=null;;
static String password=null;

static{

//1.创建一个属性配置对象
Properties properties=new Properties();

InputStream is=JDBC.class.getClassLoader().getResourceAsStream("properties"); //类.class.getClassLoader().getResourceAsStream("文件名");
//2.导入输入流
try {
properties.load(is); //load方法加载
} catch (IOException e) {
e.printStackTrace();
}

//3.调用方法读取文档里面的url/name/password等
driverClass=properties.getProperty("driverClass");
url=properties.getProperty("url");
name=properties.getProperty("name");
password=properties.getProperty("password");
}

public static java.sql.Connection getConn(){
java.sql.Connection conn=null;
//1.注册驱动
//DriverManager.registerDriver(new Driver()); //需要一个参数 这个参数是java.sql.jdbc.Driver
try {
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
//2.建立连接(url协议+数据库,user账号,password密码)
try {
conn=DriverManager.getConnection(url,name,password);
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return conn;
}

public static void main(String[] args) throws SQLException{
java.sql.Connection conn = getConn();
//3.创建statement,跟数据库打交道,一定需要这个对象
java.sql.Statement st=conn.createStatement();

//4.执行查询
String sql="select * from s_stu";
ResultSet rs=st.executeQuery(sql);

//5.遍历每一条查询
while(rs.next()) //是否可以移动到下一行
{
int id=rs.getInt("id"); //获得id
String name=rs.getString("name"); //获得name
int age=rs.getInt("age"); //获得age
System.out.println("id="+id+" name="+name+" age="+age);
}

//6.释放
rs.close();
}
}

读取结果:


JDBC

一、JDBC概述

  SUN公司提供的一种数据库访问规则、规范。用于JAVA和各种数据库连接!我们的JAVA程序只需要使用sun公司提供的jdbc驱动就行!


二、JDBC入门案例#

  • 1.准备好jdbc的外部引入的库(网上也有!)。

  • 2.下载好MYSQL5.5 然后下载一个navicat(可视化软件)方便建立数据库等。

  • 3.创建一个student的数据库,然后建立表s_stu,并且往里填充三条数据。

  • 4.然后按照步骤进行编写代码

    • 4.1注册驱动 DriverManager.registerDriver(new Driver());
    • 4.2建立连接 Connection conn=DriverManager.getConnection("jdbc:mysql://localhost/student", "root","njdxrjgc7777777.");
    • 4.3创建和数据库打交道的对象 Statement st=conn.createStatement();
    • 4.4执行查询 st.executeQuery(sql);
    • 4.5遍历查询 rs.get()方法
    • 4.6释放 rs.close()

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Driver;
import com.mysql.jdbc.Statement;
public class JDBC{
public static void main(String[] args) throws SQLException{
//1.注册驱动
DriverManager.registerDriver(new Driver()); //需要一个参数 这个参数是java.sql.jdbc.Driver

//2.建立连接(url协议+数据库,user我的主机账号,password我的主机密码)
java.sql.Connection conn=DriverManager.getConnection("jdbc:mysql://localhost/student", "root","njdxrjgc7777777.");

//3.创建statement,跟数据库打交道,一定需要这个对象
java.sql.Statement st=conn.createStatement();

//4.执行查询
String sql="select * from s_stu";
ResultSet rs=st.executeQuery(sql);

//5.遍历每一条查询
while(rs.next()) //是否可以移动到下一行
{
int id=rs.getInt("id"); //获得id
String name=rs.getString("name"); //获得name
int age=rs.getInt("age"); //获得age
System.out.println("id="+id+"===name"+name+"==age="+age);
}

//6.释放
rs.close();

}
}

查询结果如下:


,