111
import com.gsw.TestCat;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.*;
import java.util.Properties;
/**
* @author 耿世伟
* @version 1.0
*/
/*
网络通讯:就是两台设备通过网络实现数据传输 java.net提供了一系列类和接口实现网络通讯
根据网路覆盖范围不同分为:局域网(覆盖范围小,一个机房或一个教室) 城域网(覆盖一个城市) 广域网(覆盖范围最大,可以覆盖全球 万维网就是广域网的代表)
ip是用于唯一识别网络中的每台计算机和主机 查看ip:ipconfig ip地址表现形式:点分十进制 xx.xx.xx.xx 每个十进制范围0-255
ip地址=网络地址+主机地址 ipv6是替代ipv4(网络地址资源有限)的下一代Ip协议,其地指数量号称可以为全世界每一粒沙子编上一个地址
ipv6使用128位表示地址 16个字节 是ipv4的4倍
域名(www.baidu.com) 方便记忆,将ip地址映射为域名
端口(整数形式 0-65535):哟哦美好与表示计算机某个特定程序 0-1024已经被占用
tomcat(8080)免费的web服务器 mysql(3360) oracle(1521)商业数据库 sqlserver(1433)微软数据库
语言本身就是一种协议 数据的组织形式就是协议 TCP/IP(协议)传输控制协议/因特尔互联网协议,又叫网络通讯协议,这个是Internet最基本的协议
TCP/IP模型 应用层--传输层(TCP)---网络层(IP)---物理+数据链螺层
TCP传输前需要三次握手 在链接中可进行大量的数据传输 传输完毕需要释放已建立的链接,效率低
UDP协议 将数据,源,目的封装成数据包,不需要建立联系 每个数据报的大小限制在64K内 因无需链接所以不可靠 发送链接无需释放资源(因为不是面向链接)速度快
*/
/*public class Web01 {
public static void main(String[] args) throws UnknownHostException {
//1.获取本机的InetAddress对象
InetAddress inetAddress=InetAddress.getLocalHost();
System.out.println(inetAddress);
//2.根据指定主机名,获取InetAddress对象
InetAddress inetAddress1=InetAddress.getByName("DESKTOP-7IOE4NO");
System.out.println(inetAddress1);
//3.根据域名返回InetAddress对象
InetAddress inetAddress2=InetAddress.getByName("www.baidu.com");
System.out.println(inetAddress2);
//4.通过InetAddress对象,获取对应的地址
String string=inetAddress2.getHostAddress();
System.out.println(string);
//5.通过InetAddress对象,获取对应的主机名/域名
String string1=inetAddress2.getHostName();
System.out.println(string1);
}
}*/
/*
通讯的两端都要有Socket,是两台机器间通信的端点 网络通讯就是Socket通讯
Socket允许程序把网络连接当成一个流 数据在两个Socket间通过IO传输 一般主动发动通讯的应用程序是客户端,等待通讯请求的为服务端
*/
/*public class Web01 {
public static void main(String[] args) throws IOException {
//在本机9999端口监听 等待连接 要求本机没有其他服务在监听
//ServerSocket可以通过accept()返回多个Socket,多个客户端链接服务器的并发
ServerSocket serverSocket=new ServerSocket(9999);
System.out.println("服务端在9999监听,等待连接");
//当没有客户端链接9999端口时 程序会阻塞 等待连接 如果有客户端连接,则会返回Socket对象,程序继续
Socket socket =serverSocket.accept();
System.out.println("socket="+socket.getClass());
//通过socket.getInputStream() 读取客户端写入到数据通道的数据
InputStream inputStream= socket.getInputStream();
*//*byte[] array=new byte[1024];
int readLen=0;
while((readLen=inputStream.read(array))!=-1){
System.out.println(new String(array,0,readLen));
}*//*
//使用字符流 InputStreamReader 将 inputStream转换成字符流
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));
String string=bufferedReader.readLine();
System.out.println(string);
//获取socket相关联的输出流
OutputStream outputStream=socket.getOutputStream();
*//* outputStream.write("hello,客户端".getBytes());
//设置结束标志
socket.shutdownOutput();*//*
BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello 客户端 字符流");
bufferedWriter.newLine();//插入一个换行符 表示回复结束
bufferedWriter.flush();
//outputStream.close();
//inputStream.close();
bufferedReader.close();
bufferedWriter.close();
socket.close();
serverSocket.close();
}
}*/
/* TCP网络通讯编程
netstat -an可以查看当前主机网络情况 包括端口监听和网络连接情况
netstat -an | more可以分页显示
要求在dos控制台下运行
LISTENING--监听状态 ESTABLISHED--连接状态
当客户端连接到服务器后 实际上客户端也是通过一个一个端口和服务端进行通讯的 这个端口是TCP/IP来分配的 随机的
UDP网络通讯编程
UDP数据包(数据报)DatagramSocket发送和接受 DatagramPacket封装UDP数据报,在数据报中包含了发送端的IP地址和端口以及接收端IP地址和端号
没有明确的服务端和客户端,演变成数据的发送端和接收端
接收数据和发送数据是通过DatagramSocket对象完成
DatagramPacket封装UDP数据报(装包)/接受它需要拆包取出数据
DatagramSocket可以指定在哪个接口接收数据
*/
/*public class Web01 {
public static void main(String[] args) throws IOException {
//创建对象 准备在9999接收数据
DatagramSocket datagramSocket=new DatagramSocket(9999);
//构建对象准备接受数据 UDP协议时 一个数据包最大64KB
byte[] array=new byte[1024];
DatagramPacket packet=new DatagramPacket(array, array.length);
//调用接收方法 将网络传输的DatagramPacket对象填充到packet对象
//当数据包发送到9999,就会接受数据 否则会阻塞等待
System.out.println("接收端准备接受数据...");
datagramSocket.receive(packet);
//把packet拆包 取出数据并显示
int length= packet.getLength();//实际接受到数据字节长度
byte[] array1= packet.getData();//接收到的数据
System.out.println(new String(array1,0,length));
//回复消息
array1="hello,man".getBytes();
packet=new DatagramPacket(array1, array1.length,InetAddress.getByName("192.168.1.111"),9998);
datagramSocket.send(packet);
datagramSocket.close();
System.out.println("回复成功.");
}
}*/
//项目开发流程简介 需求分析(需求分析师)-->设计阶段(架构师/项目经理)-->实现阶段(程序员+自己测试)-->测试阶段(测试工程师黑白盒测试)-->实施阶段(实施工程师)->维护阶段
111-111
import java.io.*;
import java.net.*;
/**
* @author 耿世伟
* @version 1.0
*/
/*public class Test01 {
public static void main(String[] args) throws IOException {
//链接服务器(ip,端口) 如果连接成功返回Socket对象
Socket socket=new Socket(InetAddress.getLocalHost(),9999);
System.out.println("客户端socket="+socket.getClass());
//连接上后,通过socket.getOutputStream
OutputStream outputStream=socket.getOutputStream();
*//* //通过输出流 写入数据到数据通道
outputStream.write("hello,服务器".getBytes());
//设置结束标志
socket.shutdownOutput();*//*
BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello,服务器 字符流");
bufferedWriter.newLine();//插入一个换行符 表示写入的内容结束
bufferedWriter.flush();//如果使用字符流 则需要手动刷新 否则不会写入数据
//获取socket关联的输入流(字节)
InputStream inputStream=socket.getInputStream();
*//*byte[] array=new byte[1024];
int readLen=0;
while((readLen=inputStream.read(array))!=-1){
System.out.println(new String(array,0,readLen));
}*//*
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));
String string=bufferedReader.readLine();
System.out.println(string);
//关闭流对象金额socket
//bufferedWriter.close();
//inputStream.close();
bufferedWriter.close();
bufferedReader.close();;
outputStream.close();
socket.close();
}
}*/
/*public class Test01 {
public static void main(String[] args) throws IOException {
//创建对象 在9998接收数据
DatagramSocket socket=new DatagramSocket(9998);
//需要发送的数据 封装到DatagramPacket array字节数组 数组长度 主机IP 端口
byte[] array="hello,java".getBytes();
DatagramPacket packet=new DatagramPacket(array, array.length,InetAddress.getByName("192.168.1.111"),9999);
socket.send(packet);
byte[] array1=new byte[1024];
packet=new DatagramPacket(array1, array1.length);
socket.receive(packet);
int length=packet.getLength();
array= packet.getData();
System.out.println(new String(array,0,length));
socket.close();
System.out.println("发送完成");
}
}*/
222
/*通过外部文件配置,在不修改源码情况下 来配置程序 也符合设计模式的ocp(不修改源码来扩容功能)原则
反射机制取得任何类的内部信息,并能操纵对象的属性和方法 反射在设计模式和框架底层都会用到
加载完类后在堆中就产生了一个class对象,一个类只能有一个class对象,这个对象包含了类的完整结构信息
得到class对象后创建对象(任意一个对象) 调用方法 操作属性等 生成动态代理
Class也是类(放在堆中) 因此继承了Object(class对象不是new出来的,而是随系统创建的)
类的字节码二进制文件放在方法区 有的地方称类的元数据
*/
/* @SuppressWarnings({"all"})
public class Web01 {
public static void main(String[] args) throws Exception {*/
/*Properties properties=new Properties();
properties.load(new FileInputStream("D:\\ShiWeiGeng\\新建文件夹 (11)\\Start\\Study\\code\\web\\web\\src\\test.properties"));
String classfullpath=properties.get("classfullpath").toString();
String methodOne=properties.get("methodOne").toString();
System.out.println("classfullpath="+classfullpath);
System.out.println("method="+methodOne);
//使用反射机制解决
Class cls =Class.forName("com.gsw.TestCat");//加载类 返回Class类型的对象
//通过cls得到你的加载类 com.gsw.TestCat的对象实例
Object o=cls.newInstance();
System.out.println(o.getClass());
//通过cls得到你加载类的com.gsw.TestCat的methodOne的方法对象 即在反射中把方法式为对象
Method method1=cls.getMethod(methodOne);
//通过method1方法调用对象 即通过方法对象来实现调用方法
method1.invoke(o);//传统方法 对象.方法() 反射机制 方法.invoke(对象)
//getField不能得到私有属性 Field表示某个类的成员变量
Field nameField=cls.getField("age");
System.out.println(nameField.get(o));
//
Constructor constructor= cls.getConstructor();//()中指定构造器的参数类型 返回无参构造器
System.out.println(constructor);
Constructor constructor1= cls.getConstructor(String.class);//String.class String类的class对象
System.out.println(constructor1);*/
//反射机制优点:可以动态创建和使用对象(也是框架底层核心),使用灵活 缺点:对执行速度有影响
//test01();
//test02();
//反射机制优化 关闭访问检查 setAccessible(true) 参数值为true取消关闭检查 false执行访问检查
//test03();
/* //对于某个类的Class对象 在内存中只有一份 因此类只加载一次
Class cls1=Class.forName("com.gsw.TestCat");
Class cls2=Class.forName("com.gsw.TestCat");
System.out.println(cls1.hashCode());
System.out.println(cls2.hashCode());//hashCode值一样*/
/* String classRoute="com.gsw.TestCat";
//获取Car对应的class对象 >表示不确定的Java类型
Class> cls=Class.forName(classRoute);
System.out.println(cls);//显示cls对象是哪个类的Class对象 com.gsw.TestCat
System.out.println(cls.getClass());//输出class的运行类型 java.lang.Class
//得到包名
System.out.println(cls.getPackage().getName());//包名 com.gsw
//得到类名
System.out.println(cls.getName());//com.gsw.TestCat
//通过cls创建对象实例
TestCat cat=(TestCat) cls.newInstance();
System.out.println(cat);
//通过反射获取属性
Field color= cls.getField("color");
System.out.println(color.get(cat));
//通过反射给属性赋值
color.set(cat,"抹茶色");
System.out.println(color.get(cat));
//我们希望获取所有的属性
Field[] fields= cls.getFields();
for(Field num:fields){
System.out.println(num.getName());
}
}
public static void test01(){
TestCat cat=new TestCat();
long start=System.currentTimeMillis();
for (int i = 0; i < 9000000; i++) {
cat.cry();
}
long end=System.currentTimeMillis();
System.out.println("test01耗时->"+(end-start));
}
public static void test02()throws Exception{
Class cls=Class.forName("com.gsw.TestCat");
Object o=cls.newInstance();
Method cry= cls.getMethod("cry");
long start=System.currentTimeMillis();
for (int i = 0; i < 9000000; i++) {
cry.invoke(o);
}
long end=System.currentTimeMillis();
System.out.println("test02耗时->"+(end-start));
}
public static void test03()throws Exception{
Class cls=Class.forName("com.gsw.TestCat");
Object o=cls.newInstance();
Method cry= cls.getMethod("cry");
cry.setAccessible(true);
long start=System.currentTimeMillis();
for (int i = 0; i < 9000000; i++) {
cry.invoke(o);
}
long end=System.currentTimeMillis();
System.out.println("test03耗时->"+(end-start));
}
}*/
public class Web01 {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
/* 获取Class对象
//1.//通过配置文件读取获得 编译阶段
String route="com.gsw.TestCat";
Class cls1=Class.forName(route);
System.out.println(cls1);
//2. 类名.class 用于参数传递 加载阶段
Class cls2=TestCat.class;
System.out.println(cls2);
//3. 对象名.getClass 运行阶段
TestCat testCat=new TestCat();
Class cls3=testCat.getClass();
System.out.println(cls3);
//4.通过类加载器来获取类的Class对象
ClassLoader classLoader=testCat.getClass().getClassLoader();//先得到类的加载器
Class cls4=classLoader.loadClass(route);//通过类的加载器的de到Class对象
System.out.println(cls4);
//5.基本数据类型按下方式得到Class类对象
Class integerClass = int.class;
Class characterClass = char.class;
System.out.println(integerClass);//int
System.out.println(characterClass);//char
//6.基本数据类型对应的包装类 .TYPE得到class对象
Class type = Integer.TYPE;
Class type1 = Character.TYPE;
System.out.println(type);
System.out.println(type1);
*/
//那些类型有Class对象
/*Class cls = String.class;//外部类
Class cls1 = Serializable.class;//接口
Class cls2 = Integer[].class;//数组
Class cls3 = float[][].class;//二维数组
Class cls4 = Thread.State.class;//枚举
Class cls5 = long.class;//基本数据类型
Class cls6 = void.class;//void类型
Class cls7 = Class.class;//Class本身也是类
System.out.println(cls);
System.out.println(cls1);
System.out.println(cls2);
System.out.println(cls3);
System.out.println(cls4);
System.out.println(cls5);
System.out.println(cls6);
System.out.println(cls7);*/
/*反射机制是java实现动态语言的关键
静态加载 编译时加载相关类 类要提前创建好 依赖性太强
动态加载 运行时加载需要的类 如果是运行时不用该类 则不报错 降低了依赖性
类的加载时机 1.new创建对象 2.当子类被加载 3.调用类的静态成员 4.通过反射
类加载
Java源码(javac编译)->字节码文件->java运行--->类加载的三个阶段: 加载-->连接(验证->准备->解析)-->初始化
类加载后内存布局 方法区类的字节码二进制数据 堆区类的class对象
三个阶段 加载:将类的class文件读入内存 并为之创建一个java.lang.Class对象
连接:将类的二进制文件合并到JRE中
验证:为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求
准备:JVM会在该阶段对静态变量分配内存并初始化(对应数据类型默认初始值,0,null,false等等)
public int number1=10; number1是实例对象 不是静态变量 因此在准备阶段 是不会分配内存
public static int number2=10; number2是静态变量 默认初始化是0 而不是20
public static final int number3=10; number3是final修饰的常量 他和静态不一样 因此默认初始化是10,一旦赋值就不会改变
解析:虚拟机将常量池内符号引用替换成直接引用的过程
初始化:JVM负责对类进行初始化,这里主要是静态成员 初始化阶段才真正开始执行类中定义的java程序 收集静态变量和静态代码块的信息并进行合并
正因为这个机制 才保证类在内存中 只有一个class对象
*/
/* //得到class对象
Class> aClass = Class.forName("com.gsw.TestCat");
//getName获取全类名
System.out.println(aClass.getName());//com.gsw.TestCat
System.out.println(aClass.getSimpleName());//获取简单类名 TestCat
//获取所有public修饰的属性
Field[] fields=aClass.getFields();
for (Field field : fields) {
System.out.println("本类的属性以及父类的属性"+field.getName());
}
//获取本类所有属性
Field[] fields1=aClass.getDeclaredFields();
for (Field field : fields1) {
System.out.println("本类所有属性"+field.getName()+"该属性修饰符值="+field.getModifiers()+"属性的返回类型"+field.getType()+"属性的返回名"+field.getName());
//getModifiers()以int形式返回修饰符 默认修饰符0 public是1 private是2 protected是4 static是8 final是16 static final是8+16
//getType() 以class形式返回类型
//getName 返回属性名
}
Method[] fields2=aClass.getMethods();
//获取public修饰的方法 包含本类以及父类
for (Method method : fields2) {
System.out.println("本类方法以及父类的方法"+method.getName());
}
//获取本类所有方法
Method[] fields3=aClass.getDeclaredMethods();
for (Method method : fields3) {
System.out.println("本类中所有方法"+method.getName()+"该方法访问修饰符值"+method.getModifiers()+"该方法返回类型"+method.getReturnType());
//method.getModifiers() 以int类型返回修饰符
// method.getReturnType() 以class形式获取返回类型
Class>[] parameterTypes = method.getParameterTypes();// 以Class[] 返回参数类型数组
for (Class> parameterType : parameterTypes) {
System.out.println("该方法的形参类型"+parameterType);
}
}
//获取本类public修饰的构造器
Constructor>[] constructor = aClass.getConstructors();
for (Constructor> constructor1 : constructor) {
System.out.println("本类以及父类的构造器"+constructor1.getName());
}
//获取本类所有构造器
Constructor>[] declaredConstructors = aClass.getDeclaredConstructors();
for (Constructor> declaredConstructor : declaredConstructors) {
System.out.println("本类所有构造器"+declaredConstructor.getName()+"以int类型返回修饰符"+declaredConstructor.getModifiers()+"该构造器的形参类型"+declaredConstructor.getParameterTypes());
}
System.out.println(aClass.getPackage());//返回包信息
//以class形式返回父类信息
Class> superclass = aClass.getSuperclass();
System.out.println("父类class对象"+superclass);
//以class[]返回接口信息
Class>[] interfaces = aClass.getInterfaces();
for (Class> anInterface : interfaces) {
System.out.println("接口信息"+anInterface);
}*/
/*//先得到TestCat对象 通过反射创建对象
Class> aClass = Class.forName("com.gsw.TestCat");
//通过public的无参构造器实例
Object o = aClass.newInstance();
System.out.println(o);
//通过public有参构造器创建实例
Constructor> constructor = aClass.getConstructor(String.class);//先得到对应构造器
Object o1 = constructor.newInstance("守护水灵");//创建实例
System.out.println(o1);
//通过非public的有参构造器创建实例
Constructor> constructor1 = aClass.getDeclaredConstructor(int.class, String.class);//得到private的构造器对象
constructor1.setAccessible(true);//暴力破解 使用反射可以访问private构造器或属性和方法 反射面前 都是纸老虎
Object o3 = constructor1.newInstance(101, "烈火战神");
System.out.println(o3);*/
/*//通过反射访问类中成员
Class> student = Class.forName("Student");
Object o2 = student.newInstance();
System.out.println(o2.getClass());//Student
Field age=student.getField("age");
age.set(o2,88);//通过反射来操作
System.out.println(o2);
System.out.println(age.get(o2));//88
Field name=student.getDeclaredField("name");
name.setAccessible(true);
name.set(o2,"罗隐");
System.out.println(o2);
name.set(null,"武斗酷猫");//如果是静态属性 则set和get中的参数o2可以写成null
System.out.println(o2);
System.out.println(name.get(null));*/
Class> dog = Class.forName("Dog");
Object o = dog.newInstance();
//调用public方法
Method say = dog.getDeclaredMethod("say", String.class);
say.invoke(o,"gun");
//调用private static方法
Method eat = dog.getDeclaredMethod("eat", int.class, String.class);
eat.setAccessible(true);//爆破
System.out.println(eat.invoke(o,100,"格斗小六"));
System.out.println(eat.invoke(null,100,"格斗小六"));
//在反射中 如果方法有返回值 同一返回Object
Object buHui = eat.invoke(null, 300, "不会");
System.out.println(buHui);
}
}
/*
class Student{
public int age;
private static String name;
public Student() {
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
*/
class Dog{
public int age;
private String name;
public Dog() {
}
public void say(String str){
System.out.println("hello"+str);
}
public static String eat(int number,String str){
return number+""+str;
}
}
222-222
package com.gsw;
/**
* @author 耿世伟
* @version 1.0
*/
/*public class TestCat {
public String name="武斗酷猫";
public int age=100;
public String color="绿色";
public TestCat() {
}
public TestCat(String name) {
this.name = name;
}
public void say(){
System.out.println("我是"+name);
}
public void cry(){
}
@Override
public String toString() {
return "TestCat{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}';
}
}*/
/* interface IA{}
interface IB{}
class A{
public String hobby;
public A() {
}
public A(String hobby) {
this.hobby = hobby;
}
}
public class TestCat extends A implements IA,IB{
public String name;
protected int age;
String gender;
private String phone;
private TestCat(int age,String name){
}
public TestCat() {
}
public TestCat(int age) {
this.age = age;
}
public void one(){}
protected void two(){}
void three(){}
private void four(){}
}*/
public class TestCat{
private int age=100;
private String name="武斗酷猫";
public TestCat() {
}
public TestCat(String name) {
this.name = name;
}
private TestCat(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
配置文件 properties classfullpath=com.gsw.TestCat methodOne=say
333
/*
使用命令行窗口连接MYSQL数据库 mysql -h 主机名ip -P 端口 -u 用户名 -p密码
启动mysql数据库的常用方式 net stop mysql服务名 net start mysql服务名
-p后面没有写密码,回车要求输入密码 如果没写-h主机,默认就是本机 如果没写-P端口,默认就是3306
所谓安装Mysql数据库,就是在主机安装一个数据库管理系统(DBMS),这个程序可以管理多个数据库
一个数据库可以创建多个表(表的本质仍是文件),以保存数据 表的一行称之为一条记录-->java程序中,一行记录往往使用对象表示
character set指定数据库采用的字符集 如果不指定 默认utf8
collate 指定数据库字符集校对规则 不写默认是 utf8_general_ci
show databases显示数据库语句
show create database 数据库名字 -->显示数据库创建名字
drop database 数据库名字 -->数据库删除语句
备份数据库 mysqldump -u 用户名 -p -B 数据库1 数据库2 > 文件名.sql 再DOS执行
恢复数据库 source 文件名.sql
备份数据库中的表 mysqldump -u 用户名 -p -B 数据库 表1 表2 > 文件名.sql 再DOS执行
*/
-- #创建一个名称为gsw_db01的数据库
-- CREATE DATABASE gsw_db01;
-- #删除数据库指令
-- DROP DATABASE gsw_db01;
-- #创建一个UTF8字符集的gsw_01的数据库
-- CREATE DATABASE gsw_01 CHARACTER SET utf8
-- #创建一个UTF8字符集并带校对规则的gsw_02数据库
-- CREATE DATABASE gsw_02 CHARACTER SET utf8 COLLATE utf8_bin
-- #校对规则 utf8_bin是区分大小写的 默认utf8_general_ci是不区分大小写的
--
-- #下面是一条查询的sql select表示查询 *所有字段 form那个表 where那个字段 name=查询名字
-- SELECT * from users where name='古力娜扎'
-- #查看程序中有哪些数据库
-- show databases
-- #查询test01定义的信息
-- SHOW CREATE DATABASE test01
-- #删除前面创建的数据库
-- drop database gsw_db01
-- #备份 要在dos下执行mysqldump指令 其实在mysql安装目录\bin文件下
-- mysqldump -u root -p -B gsw_01 > d:\\haha.sql
-- mysqldump -u root -p -B gsw_db01 > d:\\hehe.sql
-- #备份库的表
-- mysqldump -u root -p test01 users > d:\\biao.sql
-- #恢复数据库 进入mysql命令框再执行
-- source d:\\haha.sql
-- #第二个恢复方法 直接将hehe.sql的内容放到查询编译器运行
-- #创建表时 要根据需要保存的数据创建相应的列 并根据数据的类型定义相应的列类型
-- CREATE TABLE `user`(
-- id INT,
-- `name` VARCHAR(255),
-- `birthday` DATE)
-- character set utf8 collate utf8_bin engine innodb;
-- #character set不指定则为数据库字符集 collate不指定则为数据库校队规则 engine引擎
-- #mysql数据类型
-- #数值类型 整形 tinyint[一个字节] smallint[两个字节] mediumint[三个字节]
-- # int[四个字节] bigint[8个字节]
-- #小数类型 float[单精度四个字节] double[双精度八个字节] decimal[M,D]大小不确定
-- #文本类型(字符串类型) char 0-255 varchar 0-65535(0-2^16-1) text 0-2^16-1
-- #longtext 0-2^32-1 二进制数据类型 blob 0-2^16-1 longblob 0-2^32-1
-- #日期类型 date 3个字节年月日 time3个字节时分秒 datetime8个字节年月日时分秒 YYYY-MM-DD HH:mm:ss year1个字节
-- #timestamp4个字节时间戳 它用于自动记录insert和update操作的时间
-- create table a1(id tinyint);#如果没有指定unsigned 则tinyint就是有符号的
-- insert into a1 values(125);
-- select *from a1
-- create table a2(id tinyint unsigned);
-- insert into a2 values(244);
-- select *from a2
-- #bit类型使用 bit(m) m指定位数,默认是1 范围在1-64
-- create table a3(num bit(8));
-- insert into a3 values(3);
-- select *from a3;
-- select *from a3 where num=3;#查询时可以按照数字来查询
-- #decimal[m,d] m是小数位数的总数,m最大65,m被省略自动为10 可以放很大的数
-- #d是小数点后面的位数,最大是30 d被省略 最大10 如果希望小数精度高 推荐使用decimal
-- create table a4(num1 float, num2 double,num3 decimal(40,20));#创建表
-- insert into a4 values(11.12345678912345,11.12345678912345,11.12345678912345);#添加数据
-- select *from a4;
-- # char(size)固定字符串 就是即使你插入'aa' 也会占用分配好的size个字符的空间 最大0-255字符 不管是中文还是英文都是放四个 varchar(size) 如果你插入'aa',实际占用的并不是size个字符,而是按照实际占用的空间分配 最大字节0-65535 不管是字母还是中文都以定义好的表的编码来存放数据 utf8编码最大21844字符 1-3字节用于记录大小 如果编码表是gbk 则varchar(size) size=(65535-3)/2=32766 如果是定长 推荐使用char 比如手机号 身份证号 如果一个长度不确定 我们使用varchar 比如留言或文章 查询速度char>varchar
-- create table a5(`name` varchar(21844));
-- select *from a5;
-- create table a6(`name` varchar(32766)) character set gbk;
-- create table a7(`name` varchar(32766)) charset gbk;
-- # 在存放文本 也可以使用text数据类型 可以将text视为vachar列 注意text不能有默认值 大小0-2^16字节 mediumtext 0-2^24 longtext 0-2^32
-- create table a8(content text,content2 mediumtext,content3 longtext);
-- insert into a8 values('你好,java','hello,世界','又是新的一天');
-- select *from a8;
-- #演示时间相关的类
-- create table a9(
-- birthday date,
-- now datetime,
-- job_time timestamp #timestamp 时间戳
-- not null default current_timestamp on update current_timestamp#如果默认值为CURRENT_TIMESTAMP,勾选了根据当前时间戳更新。在insert into一条记录时,自动获取系统时间。当其它字段发生update时,自动更新为系统当前时间
-- );
-- select *from a9;
-- insert into a9(birthday,now)values('2022-10-29','2022-11-11 10:10:10');
-- #如果我们更新a9表的某条记录 job_time列会自动的以当前时间进行更新
--
-- #user增加一个address列 varchar类型(要求在name后面)
-- alter table `user` add address varchar(32) not null default '' after `name`
-- desc `user` #显示表结构,可以查看当前所有的列
-- alter table `user` modify `name` varchar(60) not null default ''#修改列
-- alter table `user` drop id#删除列
-- rename table `user` to test01 #修改表名
-- alter table test01 character set utf8#修改表的字符集为utf8
-- alter table test01 change `name` `user_name` varchar(10) not null default ''#修改列名
-- #数据库C(create)R(read)U(update)D(delete) Insert添加数据 Update更新数据 Delete删除数据 Select查找数据
-- insert into test01(user_name,address) values ('aoteman','guangzhiguo'),('haha','yuyan');#添加数据 字符和日期类型应在单引号里 values(),(),()可以添加多条语句
-- insert into test01 values('nihao','dazhaohu','2022-10-09');
-- insert into test01 values('niguolai','dazhaohu',null);#如果给表所有字段添加数据,则不用写前面的字段名称(user_name,address) 列可以插入null,前提是该字段允许为空 当不给某个字段默认值时, 如果有默认值就会添加默认值否则报错, 如果某个列没有not null ,当添加数据时,没有给定值,则会默认null
-- select *from test01;
-- update test01 set address = 'zhongguo'#将所有地址修改为zhongguo
-- update test01 set address='riben' where user_name='aoteman'#将姓名为aoteman的地址改为riben
-- alter table `test01` add number int after `user_name`#添加列
-- update test01 set number=500;
-- update test01 set number=number+100,address='pinyin' where user_name='haha'#给haha的number列增加100 也可以修改多个字段
-- #where子句指定更新那行 如果没有where则更新所有
-- delete from test01 where user_name='aoteman';#删除表中aoteman记录
-- delete from a9 #如果不使用where子句 ,则删除表中所有记录 delete不能删除某一列的值,可以update设为null或'' delete语句仅删除记录,不删除表本身 如果要删除表 则使用drop table语句
-- update test01 set birthday=null where user_name='nihao';
-- drop table a9;
-- select *from test01;#查询表中所有信息
-- select user_name,number from test01;#查询test01表中所有user_name,number
-- select distinct number from test01;#过滤重复的数据 distinct 查询的记录,每条字段都相同,才会去重
-- select distinct number,user_name from test01;
-- alter table `test01` add number1 int after `user_name`#添加列
-- alter table `test01` add number2 int after `number1`#添加列
-- select user_name,(number+number1+number2) from test01;#统计各number综合
-- select user_name,(number+number1+number2+10) from test01;#统计各number综合,每个人加10 #使用别名表示number和,别名也可以是中文
-- select user_name,(number+number1+number2) as total from test01;
-- select *from test01 where user_name ='nihao'#查询姓名为nihao的信息
-- select *from test01 where number1>190;#查询number1>190的信息
-- #查询number总和大于1000的信息 where过滤查询
-- select *from test01 where not(number1>190);# not 条件不成立
-- select *from test01 where (number+number1+number2)>1000;
-- select *from test01 where number>300 and number1>100 # and是并且
-- select *from test01 where number>100 and user_name like 'n%'# n%表示以n开头的字母就可以 like 'n%' 模糊查询 not like is null判断是否为空
-- select *from test01 where number>100 and user_name not like 'n%'
-- select *from test01 where number2 between 200 and 400#查询number2在200-400的信息 between...and...是闭区间 (显示在某一区间的值)
-- select *from test01 where number1=100 or number1=200 or number1=300#多个条件任意成立
-- select *from test01 where number1 in(100,200,300) #显示在in()列表的值
-- select *from test01 order by number1;#默认升序
-- select *from test01 order by number1 desc;#desc 降序 asc升序
-- select count(*) from test01;#统计有多少个
-- select count(*) from test01 where number1>100 #统计number1>100的信息有多少个
-- # conut(*)返回满足条件的行数 count(列)统计满足条件的某列个数,但会排除null的情况
-- select count(birthday) from test01
-- select sum(number),sum(number1),sum(number2)from test01#number number1 number2总分
-- select sum(number)/count(*) from test01#统计3个number的平均分
-- select avg(number) from test01# avg求平均值
-- select max(number),min(number) from test01
-- #求number最高分 最低分(数值范围在统计中特别有用)
-- select max(number+number1+number2),min(number+number1+number2) from test01
-- #group by子句对列进行分组 having子句对分组的结果进行过滤
-- select avg(number),min(number),user_name from test01 group by user_name having avg(number)>500;#显示
-- select charset(user_name) from test01 #返回字符串字符集
-- select concat(user_name,'name is','666') from test01#连接字串
-- select instr('nihaoshijian','sh') from dual#返回'sh'在'nihaoshijian'中出现的位置 dual 亚元表,系统表 可以作为测试表使用
-- select ucase('nihao') from dual #转换为大写
-- select lcase('NIHAO') from dual#转换成小写
-- select left('nihao',2) from dual#从nihao左边提取两个字符
-- select right('nihao',2) from dual#从nihao右边提取两个字符
-- select length('你好,world') from dual#返回string长度(按照字节)
-- select user_name,replace (user_name,'haha','my_haha') from test01 #repalce(在user_name中用'my_haha'替换'haha')
-- select * from test01
-- select strcmp('haha','hehe') from dual #逐字符比较字符串的大小
-- select substring('world',1,3) from dual# 'world'字符串从0开始计算,取出3个字符
-- select ltrim(' 你好世界 ') from dual#去除前端空格
-- select rtrim(' 你好世界 ') from dual#去除后端空格
-- select trim(' 你好世界 ') from dual#去除前后端空格
-- select abs(-10) from dual#绝对值
-- select bin(10) from dual #十进制转二进制
-- select ceiling(-1.1) from dual #向上取整
-- select conv(8,10,2) from dual # 进制转换 8是十进制转换为2进制
-- select floor(-1.1)from dual#向下取整
-- select format(3.1415926,2) from dual #保留2位小数位(四舍五入)
-- select hex(10) from dual#转16进制
-- select least(10,12,6) from dual#求最小值
-- select mod(10,3) from dual#求余数 10 % 3
-- select rand() from dual#返回随机数 其范围[0,1.0]
-- select rand(255) from dual# rand(这里面传值 如果值不变 随机数也不变)
-- select current_date() from dual#当前日期 年月日
-- select current_time() from dual#返回当前时间
-- select current_timestamp() from dual#返回当前时间戳 2022-10-29 21:45:29
-- select now() from dual#返回当前时间
-- create table news(
-- pin_dao varchar(30),
-- `time` datetime);
-- insert into news values('北京新闻',current_timestamp),('深圳新闻',now()),('上海新闻',now());
-- select *from news;
-- select *from news where date_add(`time`,interval 10 minute)>=now()#在`time`添加时间 查询在10分钟内发布的新闻
-- select *from news where date_sub(now(),interval 10 minute)<=`time`#查询在10分钟内发布的新闻 在`time`减少时间
-- select datediff('2021-11-12','1998-11-10') from dual #2021-11-12和1998-11-10相差多少天
-- select datediff(now(),'1998-11-10') from dual
-- select timediff('12:10:10','10:10:10') from dual #返回时间
-- select year(now()) from dual#返回当前年
-- select month(now()) from dual#返回当前月
-- select day(now()) from dual#返回当前天
-- select year('2021-10-13') from dual#返回指定的年
-- select unix_timestamp() from dual#返回1970-1-1到现在的秒数
-- select unix_timestamp()/(365*24*3600) from dual
-- #from_unixtime可以把一个unix_timestamp秒数转化为指定的格式日期 %Y-%m-%d格式是规定好的年月日 %H:%i:%s 时分秒 在开发中可以存放一个整数,然后表示时间,通过from_unixtime转换,还是有实用价值的
-- select from_unixtime(1618215,'%Y-%m-%d %H:%i:%s')from dual
-- select user() from dual#查询用户 用户-ip地址
-- select database();#查询当前使用数据库名称
-- select md5('haha')from dual#为字符串算出一个 md5 32的字符串 常用用户名加密
-- select length(md5('haha'))from dual
-- select password('haha')from dual#password加密函数 mysql数据库的用户密码就是password加密的
-- select if(true,'北京','上海')from dual#如果第一个参数是true 则返回北京 否则上海
-- select ifnull('广州','深圳')from dual#如果第一个参数不为空 则返回广州 为空则返回深圳
--
-- select case
-- when false then '你好'
-- when true then '呵呵'
-- else '滚' end
-- #类似多重分支 expr1为真则返回 你好 为假执行下面语句
-- select 'hahaha' from dual where 'hahaha' like '__h%'#显示第三个字符为小写h的成员
-- desc test01#查询表结构
-- select *from test01 order by number1 limit 0,3;#显示test01第一页 显示2条记录
-- select *from test01 order by number1 limit 3,3;#显示test01第二行 显示2条记录
-- select *from test01 order by number1 limit 6,3;#显示test01第三行 显示2条记录
-- # 每页显示记录数 * (第几页 - 1 )+ , 每页显示记录数
-- #如果语句很复杂,则顺序为 group by(分组),having(筛选),order by(排序),limit(取出分行)
-- select user_name,avg(number1) as `avg` from test01
-- group by user_name
-- having `avg` > 40
-- order by avg DESC
-- limit 0,2
-- #多表查询 是指基于两个和两个以上的表查询 多表查询的条件不能少于 表的个数-1 负责会出现笛卡尔集
-- select * from test01,news#默认情况下 两个表查询 一共返回的记录数 第一张表数*第二张表数 这种多表查询默认处理返回结果为笛卡尔集
-- select user_name,pin_dao from test01 , news where test01.number=news.number
-- #自连接 是在同一个表连接查询 特点:把同一张表当两张表用 需要给表取别名 列名不确定,要指定列的别名
-- select num1.number1 as '数字一', num2.number1 as '数字二',num1.user_name
-- from test01 num1,test01 num2
-- where num1.number1=num2.number1
-- #子查询是指嵌入在其他sql语句中的select语句 也叫嵌套查询
-- #单行子查询是指返回一行数据的子查询语句
-- select user_name from test01 where number=500;
-- select * from test01
-- where user_name=(select user_name from test01 where number=700)
-- #多行子查询 使用关键字 in #在数据库中不相等为 != 或者 <>
-- select * from test01
-- where user_name in(select user_name from test01 where number=500)
-- select number from test01 group by number#回顾分组
-- select max(number1) from test01
-- select user_name,number from test01 where number>(select max(number1) from test01)
-- #也可以这样写 all 返回number1的最大值
-- select user_name,number from test01 where number>all(select number1 from test01)
-- select user_name,number from test01 where number>(select min(number1) from test01)
-- #也可以这样写 any返回number1的最小值
-- select user_name,number from test01 where number>any(select number1 from test01)
--
-- select number,number1 from test01 where user_name='haha'
-- #把上面的查询当作子列表来使用 并且使用多列子查询的语法进行匹配
-- select * from test01 where(number, number1)=(select number,number1 from test01 where user_name='haha')
-- select test01.* from test01 # 表.*表示将该表所有的列都显示出来
-- #演示自我复制
-- create table test02(`name` varchar(40),number int,number1 int,number2 int,address varchar(40),birthday date);
-- #先把test01的表复制到test02中
-- insert into test02 (`name`,number,number1,number2,address,birthday)select user_name,number1,number2,number,address,birthday from test01
-- select * from test02
-- insert into test02 select * from test02
-- select count(*) from test02
-- #复制的第二种方法
-- create table test03 like test01#把test01表的结构复制到test03
-- desc test03
-- insert into test03 select * from test01
-- #通过distinct关键字处理去重复制到test04
-- create table test04 like test01
-- insert into test04 select distinct * from test03
-- delete from test03#清除掉test03记录
-- drop table test03,test04#删除表
-- select user_name,number1 from test01 where number1>100
-- union ALL select user_name,number from test01 where number>30
-- #union all就是两个查询结果合并不会去重 union去重
-- select user_name,number1 from test01 where number1>100
-- union select user_name,number from test01 where number>30
-- # 外连接 左外连接(左侧表完全显示) 右外连接
-- create table student(id int, `name` varchar(20));
-- insert into student values (1,'haha'),(6,'hehe'),(3,'hahe'),(4,'heha'),(5,'ee');
-- select * from student
--
-- create table score(id int, number int);
-- insert into score values (1,11),(2,22),(3,33);
-- select * from score
-- #左连接显示所有人number 如果没有成绩 也要写上该人的名字和id 成功显示是空
-- select `name`,student.id,number from student left join score on student.id=score.id
-- #右连接 select...from 表一 right join 表二 on 条件 (表一左表,表二右表)
-- select `name`,score.id,number from student right join score on student.id=score.id
-- #mysql约束 约束是用于确保数据库的数据满足特定的商业规则 primary key(主键)主键约束后该列不能重复 而且不能为空 一张表只有一个主键,但可以是复合主键
-- create table a1(id int primary key,`name` varchar(32));
-- create table a2(id int ,`name` varchar(32),primary key(id,`name`));#复合主键
-- desc a2# desc 表名 可以看到primary key的情况 在实际开发中,每个表往往都会设计一个主键
-- # not null(非空); unique(唯一)当有这个约束,该列值不能重复 如果没有指定not null,unique字段可以有多个null 一个表可以有多个unique字段
-- create table a3(id int unique,number int unique);
-- insert into a3 values (null,2),(null,3);
-- select * from a3# number1 unique not null 相当于primary key
--
-- #外键约束 用于主表和从表之间的关系 外键约束要定义在从表上 主表则必须要有主键约束或unique约束 当定义外键约束后,外键数组必须在主表的主键列存在或为null 外键指向表的字段要求是primary key或者是unique 表的类型(引擎)是innode,这样表才支持外键 外键字段的类型和主键字段类型一致(长度可以不同) 外键字段的值必须在主键字段中出现过,或者为null(前提外键字段允许为null) 一旦建立主外键关系,数据不能随便删除
-- create table zhu(id int primary key,`name` varchar(32) not null default '');
-- create table ci(id int primary key, `name` varchar(32)not null default '',number int, foreign key(number) references zhu(id))
-- insert into zhu values(100,'haha'),(200,'hehe');
-- #测试数据
-- insert into ci values(1,'a',100),(2,'b',200);#(3,'c',300) 这样会失败 因为300在主表不存在
-- insert into ci values (5,'c',null)#可以外键没有写not null
-- # check用于强制数据必须满足条件 但是mysql5.7还不支持check,只做语法校验,但不会生效
-- create table a4(id int primary key,number int check(number>100 and number<200),gender enum('男','女')not null);
-- insert into a4 values(1,88,'2')# 枚举类型是生效的
-- insert into a4 values(2,88,'1')
-- select* from a4
-- #自增长 在添加记录的时候,该列id从1开始 一般来说自增长是和primary key配合使用的 也可以但单独使用,但需要一个unique
-- create table a5(id int primary key auto_increment,`name` varchar(20));
-- desc a5
-- insert into a5 values(null,'hello')
-- insert into a5 (`name`) values('haha')
-- insert into a5 (id,`name`) values(66,'e')#添加数据 可以给自增长指定值 下面就指定值+1
-- insert into a5 (id,`name`) values(null,'ee')
-- insert into a5 values(null,'hehe')
-- select *from a5
-- #修改默认的自增长开始值
-- alter table a5 auto_increment =100
-- insert into a5 values(null,'100')
-- #mysql索引 不用加内存,不用改程序,不用调用sql ,查询速度就可以提高百倍
-- create index `name_index` on test02(`name`) # `name_index`索引名称 on test02(`name`)在test02表name列创建索引 创建索引后只对索引的列有效 索引的数据结构是二叉树 索引的代价:磁盘占用, 对update delete insert 语句效率有影响 索引的类型 主键索引(类型primary key) 唯一索引(unique) 普通索引(index) 全文索引(fulltext)
-- show indexes from a1#查询表是否有索引
-- create unique index id_index on a2(id)#添加唯一索引
-- create index id_index on a2(id)#添加普通索引方式一
-- alter table a2 add index name_index(`name`)#添加普通索引方式二
-- alter table a4 add primary key (id)#添加主键索引
-- drop index name_index on a2#删除索引
-- alter table a4 drop primary key #删除主键索引
-- show index from a1#查询索引方式一
-- show indexes from a2#查询索引方式二
-- show keys from a3#查询索引方式三
-- desc a5#方式四
-- #那些列上适合使用索引 查询较频繁 唯一性太差不适合索引 更新频繁也不适合索引
-- #事务(转账就是用事务来处理 用于保证数据统一性) 如果不开始事务,dml(插入更新删除)操作是自动提交的,不能回滚 mysql事务机制需要innodb的存储引擎,myisam不好使
-- create table a6(id int,`name` varchar(32)) #创建一个测试表
-- start transaction #开始事务
-- savepoint a#设置保存的点 保存点是事物中的点,用于取消部分事务,当commit结束事务,会自动删除该事务所定义的所有保存点,当回滚事务时,可以通过保存点回退到指定的点
-- insert into a6 values(1,'nihao')#执行dml操作
-- select * from a6
-- savepoint b
-- insert into a6 values(2,'hehe')#执行dml操作
-- rollback to b#回退到b 回滚
-- rollback#这样直接回到事物开始的状态
-- commit#提交事务
-- #事务隔离级别 脏读:当一个事务读取另一个事务尚未提交的修改时,产生脏读 不可重复读:同一查询在同一事务多次进行,由于其他事务所作的修改和删除,每次返回不同的结果集 幻读:同一查询在同一事务多次进行,由于其他事务所做的插入操作,每次返回不同的结果集 读未提交(Read uncommitted) 脏读,不可重复读,幻读都会出现 不加锁读
-- # 读已提交(Read committed) 不可重复读,幻读会出现 不加锁读
-- # 可重复读(Repeatable read) 脏读,不可重复读,幻读都不会出现 不加锁读
-- #可串行化(Serializable) 脏读,不可重复读,幻读都不会出现 加锁读
-- select @@tx_isolation#查看当前会话隔离级别
-- select @@global.tx_isolation#查看系统当前隔离级别
-- set session transaction isolation level read uncommitted#设置当前会话隔离级别
-- set global transaction isolation level read uncommitted#transaction isolation level你设置的级别 事务的acid特性 1.原子性(微信转账)2.一致性(事务必须从一个一致性状态变化到另一个一致性状态)3.隔离性 4.一旦提交事务,他对数据的改变是永久性的
-- #mysql的表类型是由存储引擎决定,mysql数据表支持六种类型 分别是CSV,Memory,ARCHIVE,MRG,MYISAM,innoBDB 这六种又分为两类,一类是事务安全型,另一类非事务安全性
-- show engines#查看所有存储引擎 Misam 和Memory批量插入的速度高 Archive批量插入非常高(数据放在内存,没有IO等待,由于是内存存储引擎,所做的任何修改在服务器重启后都会消失 经典用法用户的在线状态) innoDB批量插入低(支持事务安全)(支持外键)
-- #锁机制 Myisam(表锁) innoDB(行锁) Memory(表锁) Archive(行锁)
-- #存储限制 Myisam(没有) innoDB(64TB) Memory(有) Archive(没有)
-- create table a9(id int) engine myisam
-- alter table a1 engine=memory#指令修改搜索引擎
-- #视图是一个虚拟的表 其数据来自对应的真实表(基表) 通过视图可以修改基表数据,基表的改变也会影响到视图的数据 视图文件(.frm)
-- create view a10 as select user_name,number from test01#创建视图a10只能查询到test01中的user_name,number信息
-- show create view a10#查看视图指令
-- drop view a10#删除视图 视图中还可以再创建视图 视图:安全 一些数据有重要信息,不能让用户看到,通过创建一个视图,用户就不能查到保密的字段 性能:关系数据库的数据常常分表存储,使用外键建立连接,这样做不但麻烦,效率还低,如果创建一个视图,就可以避免使用JOIN查询数据 灵活:如果还有一张旧的表,即将被废弃,但很多应用都基于这张表,就可以建立一张视图
-- desc a10
-- #不同用户不同权限
-- create user 'testMySQL'@'localhost' identified by '123456'#创建新用户 'testMySQL'@'localhost' 用户名@允许登陆的位置 在创建用户的时候,不指定host,则为%,%表示所有ip都有连接的权限
-- create user longwang
-- create user 'person'@'192.168.1.%'#表示用户在'192.168.1.%'可以登录mysql
--
-- select * from mysql.user
-- drop user 'testMySQL'@'localhost'#删除用户
-- drop user longwang#默认就是drop user 'longwang'@ '%'
-- drop user 'person'@'192.168.1.%'#删除用户 如果host不是% 需要明确指定 用户.host值
-- set password =password('123')#修改自己密码
-- set password for 'testMySQL'@'localhost' =PASSWORD('666')#修改他人密码
-- grant select,insert on gsw_db01.a1 to 'testMySQL'@'localhost'#给创建的用户分配查看a1和添加a1的权限
-- revoke select,insert on gsw_db01.a1 from 'testMySQL'@'localhost'#回收查看a1和添加a1的权限
--
-- select 700 + null from dual#显示为null
-- select user_name,number from test01 where not (number>100)
-- select user_name,number2 from test01 where number2 is null
-- select last_day('1921-10-03')#返回当前日期最后一天
-- select last_day(now())
-- select last_day('1921-10-03')-2#19211029
-- select *from test01 where user_name like '%a%'#显示姓名任意位置包含'a'的所有员工姓名
333-333
package src.test.properties.j;
import com.alibaba.druid.support.ibatis.DruidDataSourceFactory;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mysql.jdbc.Driver;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.junit.jupiter.api.Test;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Scanner;
/**
* @author 耿世伟
* @version 1.0
*/
//public class jdbc0 {
/* @Test//方式一静态加载 灵活性差 依赖性强
public void jdbc01() throws SQLException {
//1.注册
Driver driver=new com.mysql.jdbc.Driver();//注册驱动 创建一个driver对象
//2.得到连接
String url="jdbc:mysql://localhost:3306/gsw_db01";
*//*jdbc:mysql:// 规定好的协议 通过jdbc的方式连接mysql
localhost:3306 主机,可以是ip地址 mysql监听的端口
gsw_db_01 连接到mysql dbms 的那个数据库
mysql连接的本质就是socket连接
*//*
Properties properties = new Properties();//将用户名和密码放到Properties对象
// user和password是规定好的
properties.setProperty("user","root");//用户
properties.setProperty("password","123456");//密码
Connection connect = driver.connect(url, properties);
//3.执行
//String sql="insert into actor values(null,'古力娜扎')";
//String sql="update actor set name='马儿扎哈' where id=1";
String sql="delete from actor where id=1";
Statement statement = connect.createStatement();//Statement用于执行静态sql语句并返回生成的结果
int rows=statement.executeUpdate(sql);//若果是dml语句 返回影响的行数
System.out.println(rows>0?"成功":"失败");
statement.close();
connect.close();
}
@Test
public void jdbc02() throws SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
//使用反射加载Driver 动态加载 更灵活
Class> aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver)aClass.newInstance();
String url="jdbc:mysql://localhost:3306/gsw_db01";
//将用户和密码放到Properties
Properties properties = new Properties();
properties.setProperty("user","root");//用户
properties.setProperty("password","123456");//密码
Connection connect = driver.connect(url, properties);
System.out.println("方式二"+connect);
}
@Test//使用DriverManager代替Driver
public void jdbc03() throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {//使用DriverManager
Class> aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver)aClass.newInstance();
String url="jdbc:mysql://localhost:3306/gsw_db01";
String user="root";
String password="123456";
DriverManager.registerDriver(driver);//注册Driver驱动
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("方式三"+connection);
}
@Test//使用Class.forName 自动完成注册驱动 简化代码
//mysql驱动5.1.6可以无需 Class.forName("com.mysql.jdbc.Driver");
//从jdk1.5以后使用了jdb4,无需在显示调用Class.forName注册驱动,而是自动调用驱动
public void jdbc04() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/gsw_db01";
String user="root";
String password="123456";
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("方式四"+connection);
}
@Test//在方式4的基础上改进 使用配置文件 连接数据库更灵活
public void jdbc05() throws IOException, ClassNotFoundException, SQLException {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\test.properties"));
String user=properties.getProperty("user");
String password=properties.getProperty("password");
String driver=properties.getProperty("driver");
String url=properties.getProperty("url");
Class.forName(driver);//建议写上
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println("方式五"+connection);
}*/
/*@Test//表示数据库结果集的数据表 ResultSet对象保持一个光标指向当前的数据行,如果resultSet对象没有更多行返回false 因此可以使用while来遍历数组
public void jdbc06() throws IOException, ClassNotFoundException, SQLException {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\test.properties"));
String user=properties.getProperty("user");
String password=properties.getProperty("password");
String driver=properties.getProperty("driver");
String url=properties.getProperty("url");
Class.forName(driver);//建议写上
Connection connection = DriverManager.getConnection(url, user, password);
Statement statement = connection.createStatement();//得到Statement 对象
String sql="select id,name from actor";//组织sql
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()){//让光标向下移动 如果没有更多行,则返回false
int id=resultSet.getInt(1);//读取该列第一行
String name=resultSet.getString(2);//读取该列第二行
System.out.println(id+"\t"+name);
}
resultSet.close();
statement.close();
connection.close();
}*/
/*
Statement对象 用于执行静态sql语句并返回生成结果的对象
在建立前对数据库进行访问 执行命令或是sql语句 可以通过 Statement[注入风险] ; PreparedStatement[预处理] ; CallableStatement[存储过程]
Statement 对象执行sql语句 有注入风险 要防范sql注入,只要用PreparedStatement(从Statement扩展而来)就可以了
*/
//注入风险
/*public static void main(String[] args) throws Exception{
Scanner scanner = new Scanner(System.in);
//让用户输入id和名字
System.out.println("请输入id");
String inputId=scanner.nextLine();//如果希望看到注入 这里需要用nextLine
System.out.println("请输入名字");
String inputName = scanner.nextLine();// next() 当接收到空格或 '就表示结束
Properties properties = new Properties();
properties.load(new FileInputStream("D:\\ShiWeiGeng\\新建文件夹 (11)\\Start\\Study\\code\\My_jdbc\\myjdbc\\src"));
String user=properties.getProperty("user");
String password=properties.getProperty("password");
String driver=properties.getProperty("driver");
String url=properties.getProperty("url");
Class.forName(driver);//建议写上
Connection connection = DriverManager.getConnection(url, user, password);
Statement statement = connection.createStatement();//得到Statement 对象
String sql="select id,name from actor where id= ' " +inputId +" 'and name=' "+inputName + " ' ";
ResultSet resultSet = statement.executeQuery(sql);
if(resultSet.next()){
System.out.println("查找成功");
}else{
System.out.println("查找失败");
}
resultSet.close();
statement.close();
connection.close();
}*/
/*
PreparedStatement 执行的Sql语句中的参数用问号(?)来表示,调用PreparedStatement对象的
setXxx()方法来设置参数 这个方法有两个参数 第一个参数是参数的索引 第二个参数是设置值
调用executeQuery() 返回ResultSet对象
调用executeUpdate() 执行更新,包括增删修改
预处理的好处 不再使用+拼接sql语句,减少了语法错误 有效的解决了sql注入问题 大大减小了编译次数,效率提高
*/
/* public static void main(String[] args) throws Exception{
Scanner scanner = new Scanner(System.in);
//让用户输入id和名字
System.out.println("请输入id");
String inputId=scanner.nextLine();//如果希望看到注入 这里需要用nextLine
System.out.println("请输入名字");
String inputName = scanner.nextLine();// next() 当接收到空格或 '就表示结束
Properties properties = new Properties();
properties.load(new FileInputStream("D:\\ShiWeiGeng\\新建文件夹 (11)\\Start\\Study\\code\\My_jdbc\\myjdbc\\src"));
String user=properties.getProperty("user");
String password=properties.getProperty("password");
String driver=properties.getProperty("driver");
String url=properties.getProperty("url");
Class.forName(driver);//建议写上
Connection connection = DriverManager.getConnection(url, user, password);
Statement statement = connection.createStatement();//得到Statement 对象
//String sql="select id,name from actor where id= ? and name= ? ";// ?相当于占位符
//添加记录
String sql="insert into actor values(?,?)";
//preparedStatement对象实现了PreparedStatement接口的实现类
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//给?赋值
preparedStatement.setString(1,inputId);
preparedStatement.setString(2,inputName);
//执行select使用executeQuery 如果执行dml 则用 executeUpdate()
//这里执行executeQuery 不要写 sql
//ResultSet resultSet = preparedStatement.executeQuery();
//if(resultSet.next()){
// System.out.println("查找成功");
//}else{
// System.out.println("查找失败");
//}
//执行dml语句 executeUpdate
int rows = preparedStatement.executeUpdate();
System.out.println(rows>0?"成功":"失败");
// resultSet.close();
preparedStatement.close();
connection.close();
}*/
/*
jdbc API
DriverManager驱动管理类 getConnection(url,user,pwd)获取到连接
Connection接口 createStatement 创建Statement对象
preparedStatement(sql) 生成预处理对象
Statement接口 executeUpdate(sql)执行dml语句,返回影响的行数
executeQuery(sql)执行查询,返回ResultSet对象
execute(sql)执行任意的sql,返回布尔值
PrepareStatement接口 executeUpdate() 执行dml
executeQuery() 执行查询,返回ResultSet对象
execute()执行任意的sql,返回布尔值
SetXxx(占位符索引 占位符值)
setObject(占位符索引,占位符的值)
*/
/*public void tsetUtils(){
Connection connection=null; //得到连接
String sql="update actor set name=? where id=?";//组织sql
PreparedStatement preparedStatement=null;
try {
connection = JdbcUtils.getConnection();
preparedStatement = connection.prepareStatement(sql);
//给占位符赋值
preparedStatement.setString(1,"周星驰");
preparedStatement.setInt(2,4);
//换行
preparedStatement.executeUpdate();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
JdbcUtils.close(null,preparedStatement,connection);
}
}*/
/*
JDBC程序中当一个Connection对象创建时,默认情况是自动提交事务,每执行一个sql语句,如果执行成功则自动提交,不能回滚
调用 Connection 的 connection.setAutoCommit(false) 可以取消自动提交事务
在所有sql语句都成功执行后,调用connection.commit();方法提交事务 connection.rollback方法回滚
*/
//}
class JdbcUtils{//jdbc中 获取链接和释放资源经常使用到,可以将其封为方法
//定义相关的四个属性 因为只需要一份 我们做出static
private static String user;//用户名
private static String password;//密码
private static String url;//
private static String driver;//驱动名
static{//在static代码块去初始化
try {
Properties properties = new Properties();
properties.load(new FileInputStream("D:\\\\ShiWeiGeng\\\\新建文件夹 (11)\\\\Start\\\\Study\\\\code\\\\My_jdbc\\\\myjdbc\\\\src"));
//读取相关属性
user=properties.getProperty("user");
password=properties.getProperty("password");
url=properties.getProperty("url");
driver=properties.getProperty("driver");
} catch (IOException e) {
//在实际开发中我们这样处理 将编译异常转为运行异常
// 使用者 可以捕获该异常,也可以选择默认处理异常,比较方便
throw new RuntimeException(e);
}
}
public static Connection getConnection(){//连接数据库
try {
return DriverManager.getConnection(url,user,password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//关闭相关资源
public static void close(ResultSet set,Statement statement,Connection connection ){
//判断是否为空
try {
if(set!=null){
set.close();
}
if(statement!=null){
statement.close();
}
if(connection!=null){
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
/*批处理 这一机制允许多条语句一次性提交给数据库批量处理 通常情况下比单独提交更有效率
add.Batch() 添加需要批量处理的sql语句或参数
executeBatch() 执行批量处理语句
clearBatch() 清空批处理包的语句
JDBC如果要使用批量处理功能请在url中加参数 rewriteBatchedStatements=true
*/
/*public class jdbc0 {
public void test0() throws SQLException {//传统方法
Connection connection = JdbcUtils.getConnection();
String sql = "insert into actor(null,?,?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
long start=System.currentTimeMillis();//开始时间
for (int i = 0; i < 50000; i++) {
preparedStatement.setString(1,"nihao"+i);
preparedStatement.setString(2,"world");
preparedStatement.addBatch();//将sql语句加入批量处理包
if((i+1)%1000==0){//当有1000行记录批量执行
preparedStatement.executeBatch();
//清空一把
preparedStatement.clearBatch();
}
preparedStatement.executeUpdate();
}
long end=System.currentTimeMillis();
//System.out.println("传统方法耗时="+(end-start));
System.out.println("批量处理方法耗时="+(end-start));
JdbcUtils.close(null,preparedStatement,connection);
}
}
*/
/*
传统的Jdbc数据库连接使用DriverManager来获取 每次向数据库建立连接的时候都要将Connection加载到
内存,再验证ip地址,用户名和密码 需要数据库连接的时候,就向数据库要求一个,频繁的进行数据库连接
操作将占用很多的系统资源 容易造成服务器崩溃
每一次数据连接 使用完后都要断开 如果程序发生异常而未能关闭 将导致数据库内存泄漏,最终导致重启数据库
传统获取连接方式 不能控制创建的连接数量 如果连接过多 也可能导致内存泄漏 mysql崩溃
解决传统数据库连接问题 可以采用数据库连接池问题
预先在缓冲池中放入一定量的连接 当需要建立连接只需从缓冲池取出一个,用完再放回
它允许程序重复使用一个现有的数据库连接,而不是重新创建一个
当应用程序向连接池请求的连接数量过大时,这些请求将被加入到等待队列中
jdbc的数据库连接使用javax.sql.DateSource来表示 DateSource只是一个接口
C3PO数据库连接池 速度相对较慢 稳定性不错
DBCP 速度相对C3PO较快 但不稳定
Proxool有监控连接池状态的功能,稳定性比C3PO差一点
BoneCP 速度快
Druid(德鲁伊)是阿里提供的数据库连接池 集C3PO, DBCP,Proxool优点为一身的数据库连接池
*/
/*
public class jdbc0 {
//相关参数 在程序中指定user url password
public void test0() throws Exception{
//创建一个数据源对象
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
//通过配置文件 获取相关信息
Properties properties = new Properties();
properties.load(new FileInputStream("D:\\\\ShiWeiGeng\\\\新建文件夹 (11)\\\\Start\\\\Study\\\\code\\\\My_jdbc\\\\myjdbc\\\\src"));
//读取相关属性
String user=properties.getProperty("user");
String password=properties.getProperty("password");
String url=properties.getProperty("url");
String driver=properties.getProperty("driver");
//给数据源 comboPooledDataSource设置相关参数
comboPooledDataSource.setDriverClass(driver);
comboPooledDataSource.setJdbcUrl(url);
comboPooledDataSource.setUser(user);
comboPooledDataSource.setPassword(password);
//设置初始化连接数
comboPooledDataSource.setInitialPoolSize(10);
//最大连接数
comboPooledDataSource.setMaxPoolSize(50);
//测试连接池的效率
long start =System.currentTimeMillis();
for (int i = 0; i < 50000; i++) {
//这个方法从DataSource接口实现
Connection connection = comboPooledDataSource.getConnection();
connection.close();
}
long end=System.currentTimeMillis();
System.out.println("C3P0连接耗时"+(end-start));
}
//使用配置文件来完成
//将c3p0提供的 c3p0.config.xml 拷贝到src目录下
//将文件指定连接数据库和连接池的相关参数
public void test1() throws Exception{
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("连接池name");
long start =System.currentTimeMillis();
for (int i = 0; i < 50000; i++) {
//这个方法从DataSource接口实现
Connection connection = comboPooledDataSource.getConnection();
connection.close();
}
long end=System.currentTimeMillis();
System.out.println("C3P0第二种方式连接耗时"+(end-start));
}
public void testDruid() throws Exception{
//1.加入 Druid jar包 加入相关配置文件 druid.properties 创建properties对象 读取配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\\druid.properties"));
//创建一个指定参数的数据库连接池 Druid连接池
DataSource dataSource=DruidDataSourceFactory.createDataSource(properties);
long start =System.currentTimeMillis();
for (int i = 0; i < 50000; i++) {
//这个方法从DataSource接口实现
Connection connection = dataSource.getConnection();
connection.close();
}
long end=System.currentTimeMillis();
System.out.println("druid方式连接耗时"+(end-start));
}
}
*/
/*
关闭 connection 后,resultSet结果集无法使用,不利于数据的的管理
结果集合 connection是关联的,及如果关闭连接就不能再使用结果集
如果我们将结果封装到ArrayList中,
再有一个Java类Actor 一个Actor对象对应表actor记录 ,将一条actor记录放到ArrayList集合
*/
class Actor{
private Integer id;
private String name;
private String sex;
private Date borndate;
private String phone;
public Actor() {
}
public Actor(Integer id, String name, String sex, Date borndate, String phone) {
this.id = id;
this.name = name;
this.sex = sex;
this.borndate = borndate;
this.phone = phone;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBorndate() {
return borndate;
}
public void setBorndate(Date borndate) {
this.borndate = borndate;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "Actor{" +
"id=" + id +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", borndate=" + borndate +
", phone='" + phone + '\'' +
'}';
}
}
/*public class jdbc0 {
public void testSelectToArray(){
System.out.println("使用druid方式完成");
Connection connection=null; //1.得到连接
//2.组织一个sql
String sql="select * from actor where id>=?";
PreparedStatement preparedStatement=null;
ResultSet set=null;
ArrayList list = new ArrayList();//创建ArrayList对象
//3.创建
try {
connection=JdbcUtils.getConnection();
System.out.println(connection.getClass());
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setInt(1,1);
//执行得到结果
set=preparedStatement.executeQuery();
connection.close();
//遍历该结果
while(set.next()){
int id=set.getInt("id");
String name =set.getString("name");
String sex = set.getString("sex");
Date borndate = set.getDate("borndate");
String phone = set.getString("phone");
//把得到的result的记录 封装到Actor对象 放到list集合
list.add(new Actor(id,name,sex,borndate,phone));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtils.close(set,preparedStatement,connection);
}
}
}*/
/*
commons-dbutils 是Apache组织提供的一个开源JDBC工具库类,它是对JDBC封装,使用dbutils能极大简化jdbc编码的工作量
QueryRunner类 线程安全 可以实现增删改查批量处理
ResultSetHandler接口:该接口用于处理java.sql.ResultSet,将数据要求转换为另一种形式
*/
/*public class jdbc0 {
public void testQueryMany() throws Exception {//结果返回多行情况
Connection connection = JdbcUtils.getConnection();//得到连接
//使用DBUtils类和接口 先引入DBUtils相关的jar 加到Project
QueryRunner queryRunner = new QueryRunner();//创建QueryRunner
String sql="select * from actor where id>=?";
//query 方法是执行sql语句 得到resultset 封装到 ArrayList集合中
List list = queryRunner.query(connection,sql,new BeanHandler<>(Actor.class),1);
System.out.println("输出集合信息");
for(Actor actor:list){
System.out.println(actor);
}
JdbcUtils.close(null,null,connection);
}
//演示apache-dbutils + druid 完成 返回结果单行记录(单个对象)
public void testQuerySingle(){
Connection connection = JdbcUtils.getConnection();
QueryRunner queryRunner = new QueryRunner();
// sql也可以查询部分列
String sql="select * from actor where id = ?";
//因为我们返回的是单行记录 单个对象使用的Hander 是 BeanHandler
Actor actor = queryRunner.query(connection,sql,new BeanHandler<>(Actor.class),1);
System.out.println(actor);
JdbcUtils.close(null,null,connection);
}
//演示apache-dbutils + druid 完成dml (update insert delete)
public void testDml(){
Connection connection = JdbcUtils.getConnection();
QueryRunner queryRunner = new QueryRunner();
//这里sql完成update insert delete
String sql="update actor set name =? where id=?";
//返回的值是受影响的行数
int row = queryRunner.update(connection, sql, "haha", 4);
System.out.println(row>0?"执行成功":"没有");
JdbcUtils.close(null,null,connection);
}
// JavaBean的类型映射关系
// int,double等在java中都用包装类,因为mysql中的所有类型都有可能是NULL,而Java中只有引用数据类型才有null
}*/
/*
apache-dbutils + druid简化了JDBC开发 但还有不足
sql的语句是固定的,不能通过参数传入,通用性不好,
对于select操作,如果有返回值,返回类型不能固定,需要使用泛型
将来表有很多 不能只靠一个java表
DAO 数据访问对象 这样的通用类称为BasicDao 是专门和数据库交互的
完成一个简单的设计
utils//工具类 domain//javabean dao//存放DAO和BasicDAO test//测试类
Mysql(里面有actor goods表)----domain(Actor类[javabean,domain,pojo] ; Goods类[javabean,domain,pojo])
---DAO(将DAO共同操作放到这里 简化代码,提高维护性和可读性)---(ActorDAO 完成对actor表的增删改查 可以有特有操作 GoodsDAO 完成对Goods表的增删改查 可以有特有操作)
*/
444
package moudle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author 耿世伟
* @version 1.0
*/
/*
正则表达式不只有java才有 java匹配默认是贪婪匹配 尽可能匹配多个
String regStr = " \\d" ; \\d表示任意一个数字
Pattern patter = Pattern.compile(regStr);
灵活运用正则表达式 必须了解其中个元字符的功能
转义号 \\(两个\\代表一个\) 需要用到转义字符有以下 . * ( ) $ \ / [ ] ^ { }
String content = "abc(.a";
String regStr = " \\."
Pattern patter = Pattern.compile(regStr);
[efgh] []在这字符列表都可以接受
[^efgh] [^]除在这字符列表都可以接受,包括数字和特殊符号
A-Z - 从A到Z任意大写字母
. 匹配除\n以外的任意字符 a..b 以a开头,b结尾 中间包括任意字符的长度为四的字符串
d{3}\\d 包含3个或四个数字的字符串
\\D 匹配非数字字符
\\w 匹配单个数字,大小写字符 相当于[0-9a-zA-Z]
\\W 匹配非单个数字,大小写字符
java正则表达式默认区分字母大小写的,如何实现不区分大小写
(?i)abc 表示abd不区分大小写
a(?i)bc 表示bc不区分大小写
Pattern patter = Pattern.compile(regStr,Pattern.CASE_INSENSITIVE);
\\s 匹配任何空白字符(空格 制表符)
\\S 和\\s相反
| 既可以匹配这个,也可以匹配那个 ab|cb ab或cb
* 指定字符重复0次或n次
+ 指定字符重复1次或n次 m+(abc)* 至少一个m开头,后面接任意个abc的字符串 mabc mabcabc
? 指定字符重复0次或n次 m+abc? 至少一个m开头,后面接ab或abc的字符串 mab mabc mmmabc
{n} 只能输入n个字符 [abcd]{n} 由abcd中字母组成的任意长度为3的字符串 abc bcd aab
{n,} 指定至少n次匹配
{n,m} 指定匹配在n到m之间
^ 指定起始字符 ^[0-9] 至少一个数字开头
$ 指定结束字符 ^[0-9]\\-[a-z]+$ 至少一个数字开头 后面加一个 - 并以至少一个字母结尾
\\b 匹配字符串的边界 nihao\\b 这里说的字符串边界是子字符串有空格,或目标字符串的结束位置
\B 匹配字符串的非边界 与\\b相反
String regStr = "nihaoworld | nihaopeople" 等价于 String regStr = "nihao(?:world|people)"
String regStr = "nihao(?=world|people)" 要求只查找nihaoworld 和 nihaopeople中包含的nihao
String regStr = "nihao(?!:world|people)" 要求查找不是 nihaoworld 和 nihaopeople中包含的nihao
String regStr = " \\d+" 默认贪婪匹配 String regStr = " \\d+?" 默认非贪婪匹配
String regStr = " ^[\u0391-\uffe5] " 匹配汉字
Pattern类没有公共构造方法 要创建一个Pattern对象,调用公共静态方法
Matcher类没有公共构造方法 要创建一个Matcher对象,调用公共静态方法
PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误
*/
/*public class zhengZeBiaoDaShi {
public static void main(String[] args) {
String content="Java看起来设计得很像C++,但是为了使语言小和容易熟悉," +
"设计者们把C++语言中许多可用的特征去掉了,这些特征是一般程序员很少使用的。" +
"例如,Java不支持goto语句,代之以提供break和continue语句以及异常处理。" +
"Java还剔除了C++的操作符过载(overload)和多继承特征,并且不使用主文件," +
"免去了预处理程序。因为Java没有结构,数组和串都是对象,所以不需要指针。Java能够" +
"自动处理对象的引用和间接引用,实现自动的无用单元收集,使用户不必为存储管理问题" +
"烦恼,能更多的时间和精力花在研发上。1";
//提取文章所有英语单词 传统方法,使用遍历方法,代码量大,效率不高
//Pattern patter = Pattern.compile("[a-zA-Z]");//先创建一个Pattern模式对象,可以理解为正则表达式对象
Pattern patter = Pattern.compile("([0-9]+)|([a-zA-Z])");//提起文章中的英文单词和数字
// Pattern patter = Pattern.compile("(?[0-9]+)|(?[a-zA-Z])");//命名捕获
//创建匹配对象 matcher匹配器按照pattern(模式/样式),到content文本去匹配
Matcher matcher = patter.matcher(content);//找到返回true 否则false
//开始循环匹配
while(matcher.find()){
//根据指定的规则,定位满足规则的子字符串 找到后,将字符串的开始索引记录到matcher对象的属性 int[] groups
//匹配内容 文本 放到m.group(0)
System.out.println("找到"+matcher.group(0));
//如果正则表达式有() 则表示分组
//group(0)表示匹配到的子字符串
//group(1)表示匹配到的子字符串的第一组字符串 但分组的数不能越界
System.out.println("第一组()匹配到的值"+matcher.group(1));
System.out.println("第二组()匹配到的值"+matcher.group(2));
//System.out.println("第一组()匹配到的值"+matcher.group("name1"));//命名捕获
//System.out.println("第二组()匹配到的值"+matcher.group("name2"));
System.out.println(matcher.start());
System.out.println(matcher.end());
System.out.println("找到"+content.substring(matcher.start(),matcher.end()));
}
//java提供了正则表达式技术 专门用于处理类似文本问题 正则表达式就是对字符串执行模式匹配技术
//整体匹配方法 常用于 去校验某个字符是否满足某个规则
System.out.println("整体匹配"+matcher.matches());
//完成如果content 有Java 替换成 awei
String regStr="Java";
patter=Pattern.compile(regStr);
matcher=patter.matcher(content);
// 返回的字符串是替换后的字符串 原来的content不变
String newContent=matcher.replaceAll("awei");
System.out.println(newContent);
}
}*/
/*
分组 : 一个小圆括号的部分我们可以认为是一个子表达式/一个分组
捕获 : 把分组的内容以数学编号或显式命名的组里,方便后期引用,从左向右,以分组的左括号为标志,第一个出现的分组组号为1,第二个为2,组0为整个表达式
反向引用 : 圆括号内容被捕获后 可以在这个括号后被使用 我们称这个为反向引用 内部反向引用\\分组号 外部反向引用$分组号
要匹配两个相同的数字 (\\d)\\1
要匹配五个个相同的数字 (\\d)\\1{4}
要匹配个位与千位相同的数字 十位与百位相同的数字 1221 (\\d)(\\d)\\2\\1
*/
public class zhengZeBiaoDaShi {
public static void main(String[] args) {
/* String content="我...我要....学学学....Java";
//去掉所有的.
Pattern pattern = Pattern.compile("\\.");
Matcher matcher = pattern.matcher(content);
content = matcher.replaceAll("");
System.out.println("content="+content);*/
/*//去掉重复的字 使用(.)\\1+ 使用反向引用$1来替换匹配到的内容
pattern=Pattern.compile("(.)\\1+");
matcher=pattern.matcher(content);
while(matcher.find()){
System.out.println("找到 "+matcher.group(0));
}
//使用反向引用 $1 来替换匹配的内容
content=matcher.replaceAll("$1");
System.out.println("content="+content);*/
//使用一条语句
/*content=Pattern.compile("(.)\\1+").matcher(content).replaceAll("$1");
System.out.println(content);*/
// String类中使用正则表达式 判断功能
String content = "000年5月,JDK1.3、JDK1.4和J2SE1.3相继发布,几周后其获得了Apple公司Mac OS X的工业标准的支持。" +
"2001年9月24日,J2EE1.3发布。" +
"2002年2月26日,J2SE1.4发布。自此Java的计算能力有了大幅提升,与J2SE1.3相比,其多了近62%的类和接口。" +
"在这些新特性当中,还提供了广泛的XML支持、安全套接字(Socket)支持(通过SSL与TLS协议)、全新的I/OAPI、" +
"正则表达式、日志与断言";
// 使用正则表达式 将JDK1\.3|JDK1\.4替换成 JDK
content = content.replaceAll("JDK1\\.3|JDK1\\.4", "JDK");
System.out.println(content);
//要求验证一个手机号 要求必须138 或139开头
content = "13865482151";
if (content.matches("1(38|39)\\d{8}")) {
System.out.println("验证成功");
} else {
System.out.println("验证失败");
}
content="hahhahahah-qqq123qqqqq~上海";
String[] split = content.split("#|~|\\d+");
for(String str:split){
System.out.println(str);
}
//String的matches是整体匹配的
}
}