JavaWeb 前端

Java基础知识

Junit单元测试:

*  测试分类:
	1. 黑盒测试: 不需要写代码,给输入值,看程序是否能够输出期望的值
	2. 白盒测试: 需要写代码,关注程序具体的执行流程
* Junit使用: 白盒测试
	* 步骤
		1. 定义一个测试类 (测试用例)
			* 建议: 
				* 测试类名: 被测试的类名 	 
				* 包名 : xxx.xxx.xx.test  cn.itcast.test
		2. 定义测试方法:可以独立运行
			* 建议:
				* 方法名: test测试的方法名 testAdd()
				* 返回值: void 
				* 参数列表: 空参
		3. 给方法加@Test 
		4. 导入junit依赖环境
	* 判定结果
		*  红色是错误
		*  绿色是正确
		* 一般我们会使用断言操作来处理结果
		 	Assert.assertEquals(期望值, 实际值);
	* 补充
		* @Before
			* 修饰的方法会在测试方法之前被自动的执行
		* @After
			* 修饰的方法会在测试方法执行之后被执行  
package cn.itcast.junit;

/**
 * 计算器类
 */
public class Calculator {
    /**
     * 加法
     * @param a
     * @param b
     * @return
     */
    public int add (int a, int b) {
//        int i = 3 / 0;
        return a + b;
    }


    /**
     * 减法
     * @param a
     * @param b
     * @return
     */
    public int sub (int a, int b) {
        return a - b;
    }
}
package cn.itcast.test;

import cn.itcast.junit.Calculator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class CalculatorTest {

    /**
     * 初始化方法:
     * 用于资源申请, 所有的测试方法在执行之前都会先执行该方法
     *
     */
    @Before
    public void init () {
        System.out.println("init....");
    }


    /**
     * 释放资源的方法
     * 在所有的测试方法执行完以后,都会自动执行改方法
     */
    @After
    public void close() {
        System.out.println("close...");
    }

    /**
     * 测试add方法
     */
    @Test
    public void testAdd(){
        //System.out.println("我被执行了");
        //1.创建计算器对象
        System.out.println("testAdd....");
        Calculator c = new Calculator();
        //2.调用add方法
        int result = c.add(1, 2);
//        System.out.println(result);
        //3.断言 我断言这个结果为3
        Assert.assertEquals(3, result);

    }

    @Test
    public void testSub() {
        //1.创建计算器对象
        Calculator c = new Calculator();
        int result = c.sub(1, 2);
        System.out.println("testSub....");
        Assert.assertEquals(-1, result);
    }
}

反射: 框架设计的灵魂

JavaWeb 前端_第1张图片

* 框架 : 半成品软件, 可以在框架的基础上进行软件开发,简化编码
* 反射: 将类的各个组成部分封装为其他对象,这就是反射机制
	* 好处
		1. 可以在程序的运行过程中,操作这些对象  
		2. 可以解耦, 提供程序的可扩展性
	
* 获取Class对象的方式
	1. Class.forName("全类名" ):将字节码文件加载进入内存,返回Class对象
		* 多用于配置文件,将类名定义在配置文件中,读取文件,加载类
	2. 类名.class: 通过类名的属性class获取
		* 多用于参数的传递
	3. 对象.getClass(): getClass() 方法在Object类中定义着
		* 多用于对象的获取字节码的方式 
* 结论:
		同一个字节码文件(*.class)在一次程序运行的过程中,只会被加载一次, 不论通过哪一种方式获取的Class对象都是同一个.
  • 使用Class对象功能:

    • 获取功能
      1. 获取成员变量们

        • Field[] getFields() //获取所有public修饰的成员变量

        • Field getField(String name) 获取所有指定名字的public修饰的成员变量

        • Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符

        • Field getDeclaredField(String name)

      2. 获取构造方法们

        • Constructor[] getConstructors() 获取所有public修饰的构造器
        • Constructor getConstructor(类… parameterTypes) 获取指定参数的public修饰的构造器
        • Constructor[] getDeclaredConstructors() 获取所有的构造器,不考虑修饰符
        • Constructor getDeclaredConstructor(类… parameterTypes)
      3. 获取成员方法们

        • Method[] getMethods()

        • Method getMethod(String name, 类… parameterTypes)

        • Method[] getDeclaredMethods()

        • Method getDeclaredMethod(String name, 类… parameterTypes)

      4. 获取类名

        • String getName()
  • Field: 成员变量

    • 操作:
      1. 设置值
      * void set(Object obj, Object value)
      2. 获取值
      * Object get(Object obj)
      3. 忽略访问权限修饰符的安全检查
      * setAccessible(true);//暴力反射
package cn.itcast.reflect;

import cn.itcast.domain.Person;

import java.lang.reflect.Field;

public class ReflectDemo2 {
    /**
     * * 使用Class对象功能:
     * 	* 获取功能
     * 		1. 获取成员变量们
     * 			* Field[] getFields()
     * 			* Field getField(String name)
     *
     * 			* Field[] getDeclaredFields()
     * 			* Field getDeclaredField(String name)
     *
     * 		2. 获取构造方法们
     * 			* Constructor[] getConstructors()
     * 			* Constructor getConstructor(类... parameterTypes)
     *
     * 			* Constructor[] getDeclaredConstructors()
     * 			* Constructor getDeclaredConstructor(类... parameterTypes)
     *
     * 		3. 获取成员方法们
     * 			* Method[] getMethods()
     * 			* Method getMethod(String name, 类... parameterTypes)
     *
     * 			* Method[] getDeclaredMethods()
     * 			* Method getDeclaredMethod(String name, 类... parameterTypes)
     *
     * 		4. 获取类名
     * 			*  String getName()
     */

    public static void main(String[] args) throws Exception {
        //0.获取Person的Class对象
        Class personClass = Person.class;

        /**
          1. 获取成员变量们
          	* Field[] getFields()
          	* Field getField(String name)
          	* Field[] getDeclaredFields()
          	* Field getDeclaredField(String name)
         */
        //1.Field[] getFields() 获取所有public修饰的成员变量
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        System.out.println("----------------------");
        //2. Field getField(String name)
        Field a = personClass.getField("a");
        //获取成员变量a的值
        Person p = new Person();
        Object value = a.get(p);
        System.out.println(value);

        //设置a的值
        a.set(p, "张三");
        System.out.println(p);

        System.out.println("=======================");
        //3. Field[] getDeclaredFields() : 获取所有的成员变量,不考虑修饰符
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        //4.Field getDeclaredField(String name)
        Field d = personClass.getDeclaredField("d");
        //访问私有的值,忽略访问权限修饰符的安全检查
        d.setAccessible(true);//暴力反射
        Object value2 = d.get(p);
        System.out.println(value2);

    }
}

  • Constructor:构造方法
    • 创建对象 :
      • T newInstance(Object… initargs)
      • 如果使用空参数构造方法创建对象,操作可以简化: Class对象的newInstance方法
package cn.itcast.reflect;

import cn.itcast.domain.Person;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class ReflectDemo3 {
    /**
     * * 使用Class对象功能:
     * 	* 获取功能
     * 		1. 获取成员变量们
     * 			* Field[] getFields()
     * 			* Field getField(String name)
     *
     * 			* Field[] getDeclaredFields()
     * 			* Field getDeclaredField(String name)
     *
     * 		2. 获取构造方法们
     * 			* Constructor[] getConstructors()
     * 			* Constructor getConstructor(类... parameterTypes)
     *
     * 			* Constructor[] getDeclaredConstructors()
     * 			* Constructor getDeclaredConstructor(类... parameterTypes)
     *
     * 		3. 获取成员方法们
     * 			* Method[] getMethods()
     * 			* Method getMethod(String name, 类... parameterTypes)
     *
     * 			* Method[] getDeclaredMethods()
     * 			* Method getDeclaredMethod(String name, 类... parameterTypes)
     *
     * 		4. 获取类名
     * 			*  String getName()
     */

    public static void main(String[] args) throws Exception {
        //0.获取Person的Class对象
        Class personClass = Person.class;

        /**
         2. 获取构造方法们
         * Constructor[] getConstructors()
         * Constructor getConstructor(类... parameterTypes)
         * Constructor[] getDeclaredConstructors()
         * Constructor getDeclaredConstructor(类... parameterTypes)
         */

        //Constructor getConstructor(类... parameterTypes)
        Constructor constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);
        //创建对象
        Object person = constructor.newInstance("张三", 23);
        System.out.println(person);


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

        Constructor constructor1 = personClass.getConstructor();
        System.out.println(constructor);
        //创建对象
        Object person1 = constructor1.newInstance( );
        System.out.println(person1);

        System.out.println("=================");
        Object o = personClass.newInstance();
        System.out.println(o);
    }
}
  • Method: 方法对象
    • 执行方法

      • Object invoke(Object obj, Object… args)
    • 获取方法名称

      • String getName : 获取方法名

package cn.itcast.reflect;

import cn.itcast.domain.Person;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ReflectDemo4 {
    /**
     * * 使用Class对象功能:
     * 	* 获取功能
     * 		1. 获取成员变量们
     * 			* Field[] getFields()
     * 			* Field getField(String name)
     *
     * 			* Field[] getDeclaredFields()
     * 			* Field getDeclaredField(String name)
     *
     * 		2. 获取构造方法们
     * 			* Constructor[] getConstructors()
     * 			* Constructor getConstructor(类... parameterTypes)
     *
     * 			* Constructor[] getDeclaredConstructors()
     * 			* Constructor getDeclaredConstructor(类... parameterTypes)
     *
     * 		3. 获取成员方法们
     * 			* Method[] getMethods()
     * 			* Method getMethod(String name, 类... parameterTypes)
     *
     * 			* Method[] getDeclaredMethods()
     * 			* Method getDeclaredMethod(String name, 类... parameterTypes)
     *
     * 		4. 获取类名
     * 			*  String getName()
     */

    public static void main(String[] args) throws Exception {
        //0.获取Person的Class对象
        Class personClass = Person.class;

        /**
         3. 获取成员方法们
         * Method[] getMethods()
         * Method getMethod(String name, 类... parameterTypes)
         * Method[] getDeclaredMethods()
         * Method getDeclaredMethod(String name, 类... parameterTypes)
         */

        Method eat_method = personClass.getMethod("eat");
        Person p = new Person();
        //执行方法
        eat_method.invoke(p);


        Method eat_method2 = personClass.getMethod("eat", String.class);
        //执行方法
        eat_method2.invoke(p, "饭");

        System.out.println("----------------");
        //获取所有的public修饰的方法
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
//            method.setAccessible(true);
            String name = method.getName();
            System.out.println(name);
        }

        //获取类名
        String classname = personClass.getName();
        System.out.println(classname);//cn.itcast.domain.Person
    }
}
  • 案例
    • 需求: 写一个"框架", 不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象, 并且执行其中任意方法.
      • 实现:
          1. 配置文件
          1. 反射
      • 步骤
        1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
        2. 在程序中加载读取配置文件
        3. 使用反射技术来加载类文件进内存
        4. 创建对象
        5. 执行方法
package cn.itcast.reflect;

import cn.itcast.domain.Person;
import cn.itcast.domain.Student;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * 框架类
 */
public class ReflectTest {
    public static void main(String[] args) throws Exception {
        //可以创建任意类的对象, 可以执行任意的方法

        /*
            前提: 不能改变该类的任何代码, 可以创建任意类的对象, 可以执行任意方法
        */
//        Person p = new Person();
//        p.eat();
//        Student stu = new Student();
//        stu.sleep();

        //1.加载配置文件
        //1.1创建Properties对象
        Properties pro = new Properties();
        //1.2加载配置文件,转换为一个集合(双列map)
        //1.2.1获取class目录下的配置文件
        ClassLoader classLoader = ReflectTest.class.getClassLoader();//获取这个类加载器
        InputStream is = classLoader.getResourceAsStream("pro.properties");//用这个类加载器获取同包下的资源得到字节流
        pro.load(is);

        //2.获取配置文件中定义的数据
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");

        //3.加载该类进内存
        Class cls = Class.forName(className);

        //4.创建对象
        Object obj = cls.newInstance();

        //5.获取方法对象
        Method method = cls.getMethod(methodName);

        //6.执行方法
        method.invoke(obj);
    }
}
className=cn.itcast.domain.Student
methodName=sleep

注解

  • 概念:说明程序的,给计算机看的

  • 注释: 用文字描述程序的,给程序员看的

  • 定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

  • 概念描述

    • JDK1.5之后的新特性
    • 说明程序的
    • 使用注解: @注解名称
  • 作用分类:
    ①编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
    ② 代码分析:通过代码里标识的注解对代码进行分析【使用反射】
    ③编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】

  • JDK中预定义的一些注解

    • @Override: 检测被该注解标注的方法是否是继承自父类(接口)的
    • @Deprecated: 该注解标注的内容,表示已过时
    • @SuppressWarnings: 压制警告
      • 一般传递参数all @SuppressWarnings(“all”)
  • 自定义注解

    • 格式
      元注解
      public @interface 注解名称 {
      属性列表;
      }

    • 本质: 注解本质上就是一个接口, 该接口默认继承 Annotation接口

      • public interface MyAnno extends java.lang.annotation.Annotation {
        }
    • 属性: 接口中的抽象方法

      • 要求:
        1. 属性的返回值类型有下列取值
          • 基本数据类型
          • String
          • 枚举
          • 注解
          • 以上类型的数组
        2. 定义了属性,在使用时候,需要给属性赋值
          1. 如果定义属性时, 使用default关键字给属性默认初始化值,则使用注解时, 可以不进行属性赋值
          2. 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可
          3. 数组赋值时,值使用{}包裹,如果数组中只有一个值,则{}省略
    • 元注解:用于描述注解的注解

      • @Target : 描述注解能够作用的位置
        • ElementType取值
          • TYPE: 可以作用于类上
          • METHOD: 可以作用于方法上
          • FIELD: 可以作用于成员变量上
      • @Retention: 描述注解被保留的阶段
        • @Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
        • @Retention(RetentionPolicy.CLASS):当前被描述的注解,会保留到class字节码文件中,但不会被JVM读取到
        • @Retention(RetentionPolicy.SOURCE):当前被描述的注解,不会保留到class字节码文件中
      • @Documented: 描述注解是否被抽取到api文档中
      • @Inherited:描述注解是否被子类继承
  • 在程序中使用(解析)注解: 获取注解中定义的属性值

      1. 获取注解定义的位置的对象 (Class, Method, Field)
      1. 获取指定的注解
*getAnnotation(Class) 
 //其实就是在内存中生成了一个该注解接口的子类实现对象

    public class ProImpl implements Pro{
        public String className() {
            return "cn.itcast.annotation.Demo1";
        }
        public String methodName() {
            return "show";
        }
    }

* 3.调用注解中的抽象方法获取配置的属性值
package cn.itcast.annotation;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * 框架类
 */
@Pro(className = "cn.itcast.annotation.Demo1", methodName = "show")
public class ReflectTest {
    public static void main(String[] args) throws Exception {
        //可以创建任意类的对象, 可以执行任意的方法

        /*
            前提: 不能改变该类的任何代码, 可以创建任意类的对象, 可以执行任意方法
        */
        //1.解析注解
        //1.1获取该类的字节码文件对象
        Class<ReflectTest> reflectTestClass = ReflectTest.class;
        //2.获取上边的注解对象
        //其实就是在内存中生成了一个该注解接口的子类实现对象

        /*
            public class ProImpl implements Pro{
                public String className() {
                    return "cn.itcast.annotation.Demo1";
                }
                public String methodName() {
                    return "show";
                }
            }
         */
        Pro an = reflectTestClass.getAnnotation(Pro.class);
        //3.调用注解对象中定义的抽象方法,获取返回值
        String className = an.className();
        String methodName = an.methodName();
        System.out.println(className);
        System.out.println(methodName);

        //4.加载该类进内存
        Class cls = Class.forName(className);

        //5.创建对象
        Object obj = cls.newInstance();

        //6.获取方法对象
        Method method = cls.getMethod(methodName);

        //7.执行方法
        method.invoke(obj);


    }
}

  • 注解小结:
    1. 以后大多数时候,我们会使用注解,而不是自定义注解
    2. 注解给谁用?
      1. 编译器
      2. 给解析程序用
    3. 注解不是程序的一部分,可以理解为注解就是一个标签
package cn.itcast.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}

package cn.itcast.annotation;

/**
 * 小明定义的计算器类
 */
public class Calculator {
    //加法
    @Check
    public void add() {
        String str = null;
        str.toString();
        System.out.println("1 + 0 =" + (1 + 0));
    }

    //减法
    @Check
    public void sub() {
        System.out.println("1 - 0 =" + (1 - 0));
    }

    //乘法
    @Check
    public void mul() {
        System.out.println("1 * 0 =" + (1 * 0));
    }

    //除法
    @Check
    public void div() {
        System.out.println("1 / 0 =" + (1 / 0));
    }

    public void show() {
        System.out.println("永无bug");
    }

}

package cn.itcast.annotation;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 简单的测试框架
 *
 * 当主方法执行后,会自动自行被检测的所有方法(加了Check注解的方法),判断方法是否有异常,记录到文件中
 */
public class TestCheck {

    public static void main(String[] args) throws IOException {
        //1.创建计算器对象
        Calculator c = new Calculator();
        //2.获取字节码文件对象
        Class cls = c.getClass();
        //3.获取所有方法
        Method[] methods = cls.getMethods();

        int number = 0; //出现异常的次数
        BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));


        for (Method method : methods) {
            //4.判断方法上是否有Check注解
            if (method.isAnnotationPresent(Check.class)) {
                //5.有,执行
                try {
                    method.invoke(c);
                } catch (Exception e) {
                    //6.捕获异常

                    //记录到文件中
                    number++;

                    bw.write(method.getName() + " 方法出异常了");
                    bw.newLine();
                    bw.write("异常的名称:" + e.getCause().getClass().getSimpleName());
                    bw.newLine();
                    bw.write("异常的原因:" + e.getCause().getMessage());
                    bw.newLine();
                    bw.write("---------------------");
                    bw.newLine();

                }
            }
        }

        bw.write("本次测试一共出现 " + number + " 次异常");
        bw.flush();
        bw.close();
    }
}

JavaWeb

  1. 什么是JavaWeb?
    • 使用Java语言开发互联网项目,用Java语言开发网站
      2.内容
    1. 数据库
    2. 网页前端
    3. web核心技术
    4. 旅游管理系统

数据库

数据库的基本概念

1. 数据库的英文单词: DataBases 简称:DB
2. 什么是数据库 
	* 用于存储和管理数据的仓库
3.数据库特点 
	1. 持久化存储数据,数据库就是一个文件系统
	2. 方便存储和管理数据
	3. 使用了统一的方式操作数据库 -- SQL
  4.常见的数据库软件
  	* 参见<>

MySQL数据库软件

	1.安装
	2.卸载
			1.去MySQL的安装目录找到my.ini
		* 复制 datadir=D:\Environment\mysql-5.7.19\data\
			2.卸载MySQL
			3.删除 datadir=D:\Environment\mysql-5.7.19\data\下的MySQL文件夹
	3.配置
		* MySQL服务启动
			1. 计算机管理 ->服务和应用程序->服务
			2. cmd -> services.msc 打开服务的窗口
			3. 使用管理员打开cmd
					* net stop mysql : 关闭mysql服务 
					* net start mysql :启动mysql服务

		* MySQL登录
			1. mysql -uroot -p密码
			2. mysql -h127.0.0.1 -uroot -p连接目标的密码
				-h后连ip127.0.0.1
				密码为123456
			3.mysql --host=ip --user=root --password=连接目标的密码
	
		* MySQL退出
			1. exit
			2. quit
		* MySQL的目录结构
			1.MySQL安装目录
				* 配置文件 my.ini
			2.MySQL数据目录
				* 几个概念
					* 数据库: 文件夹
					* 表: 文件
					* 数据 : 文件里的数据

JavaWeb 前端_第2张图片

SQL

1. 什么是SQL?
	Structured Query Language : 结构化查询语言
	其实就是定义了操作所有关系型数据库的规则.每一种数据库操作的方式存在不一样的地方,称为"方言"
2. SQL通用语法
	1.SQL语句可以单行或者多行书写,以分号结尾
	2.可以使用空格或者缩进来增强语句的可读性
	3. MySQL的数据库的 SQL语句不区分大小写,关键字建议使用大写
	4. 3种注释 
		* 单行注释: -- 注释内容 或者 # 注释内容(MySQL特有)
		* 多行注释: /* 注释 */
		
3.SQL分类
	1.DDL 数据库定义语言
		用来定义数据库对象: 数据库,表, 列等.关键字:create,drop,alter等
	2.DML 数据库操作语言
		用来对数据库中表的数据进行增删改.关键字: insert,delete,update等
	3.DQL 数据库查询语言
		用来查询数据库中表的记录(数据),关键字: select,where等
	4.DCL 数据库控制语言
	 	用来定义数据库的访问权限和安全级别,及创建用户,关键字:GRANT,REVOKE等

JavaWeb 前端_第3张图片

DDL : 操作数据库,表

1. 操作数据库: CRUD
	1. C(Create): 创建
		* 创建数据库
			* create database 数据库名称;
		*  创建数据库,判断不存在
			* create database if not exists 数据库名称;
		* 创建数据库,并去指定字符集
			* create database 数据库名称 character set 字符集名称; 
		*	练习: 创建db4数据库,判断是否存在,并知道字符集为gbk
			*  create database if not exists db4 character set gbk;
	2. R(Retrieve): 查询
		* 查询所有数据库的名称:
			* show databases;
		* 查询某个数据库的字符集: 查询某个数据库的创建语句
			* show create database 数据库名称;  
	3. U(Update):修改
		* 修改数据库的字符集
			* alter database	数据库名称 character set 字符集名称;
	4. D(Delete): 删除
		* 删除数据库
			* drop database 数据库名称; 
		* 判断数据库存在,存在再删除
			* drop database if exists 数据库名称; 
	5. 使用数据库
		* 查询当前正在使用的数据库名称
			*  select database();
		* 使用数据库
			* use 数据库名称;
				 
		
2. 操作表
	1. C(Create): 创建
		1. 语法:
			create table 表名(
					列名1	数据类型1,
					列名2	数据类型2,
					...
					列名n	数据类型n
			);
			* 注意:最后一列, 不需要加逗号(,)
			* 数据库类型 : 
					1. int : 整数类型
						* age int,
					2. double: 小数类型
						* score double(5,2)
					3. date: 日期,只包含年月日, yyyy - MM -dd
					4. datatime: 日期,包含年月日时分秒 yyyy - MM -dd HH:mm:ss
					5. timestamp: 时间戳类型 包含年月日时分秒 yyyy - MM -dd HH:mm:ss
						* 如果将来不给\这个字段赋值,或者赋值为null, 则默认使用当前的系统时间,来自动赋值
					6. varchar : 字符串
						* name varchar(20) : 姓名最大20个字符
						* zhangsan 8 个字符 张三 2个字符
						* 
			* 创建表
				create table student(
					id int,
					name varchar(32),
					age int,
					score double(4,1),
					birthday date,
					insert_time timestamp
				);
			* 复制表
				* create table 表名 like 被赋值的表名;
	2. R(Retrieve): 查询 
		* 查询某个数据库中的所有表的名称
			* show tables;
		* 查询表结构
			* desc   表名;
	3. U(Update):修改
		1. 修改表名
			alter table 表名 rename to 新的表名;
			
		2. 修改表的字符集
			alter table 表名 character set 字符集名称 ;
		3. 添加一列
			alter table 表名 add 列名 数据类型;
		4. 修改列名称 类型
		  	alter table 表名 change 列名 新列名 新数据类型;
		  	alter table 表名 modify 列名  新数据类型;
		5. 删除列	
		 alter table 表名 drop 列名;
	4. D(Delete): 删除
		* drop table 表名;
		* drop table if exists 表名;

DML : 增删改表中数据的

1. 添加数据
	* 语法 : 
		* insert into 表名(列名1, 列名2, ..., 列n) values (值1, 值2, ..., 值n);
	* 注意:
		* 1. 列名和值要一一对应
		* 2. 如果表名后, 不定义列名, 则默认给所有列添加值
			*    insert into 表名 values (值1, 值2, ..., 值n);
		* 3. 除了数字类型,其他类型 需要使用引号(单双都可以)引起来
2. 删除数据
	* 语法
		* delete from 表名 [where 条件] 
	*  注意:
		1. 如果不加条件, 则删除表中的所有记录
		2. 如果要删除所有记录 
			1. delete from 表名; -- 不推荐使用, 有多少条记录就会执行多少次删除操作
			2. TRUNCATE TABLE 表名; -- 推荐使用,效率更高,删除表,然后再创建一张一模一样的新表
3. 修改数据
	* 语法:
		* update 表名  set 列名1 = 值1, 列名2 = 值2,...[where 条件];
	* 注意
		1. 如果不加任何条件, 则会将表中的所有记录全部修改

DQL : 查询表中的记录

* select * from 表名;
  1. 语法:
    select
    字段列表
    from
    表名列表
    where
    条件列表
    group by
    分组字段
    having
    分组之后的条件
    order by
    排序
    limit
    分页限定

  2. 基础查询

    1. 多个字段的查询
      select 字段名1, 字段名2… from 表名;
      • 注意
        • 如果查询所有字段, 则可以使用* 来代替字段列表
    2. 去除重复
      • distinct
    3. 计算列
      • 一般可以使用size运算计算一些列的值. (一般只会进行数组型的计算)
        • ifnull(表达式1, 表达式2) : null 参与的运算,计算结果都为null
        • 如果该字段为null后的替换值
    4. 起别名
      • as : as也可以省略
  3. 条件查询

    1. where子句后跟条件
    2. 运算符
      • , <, <=, >=, =, <>

      • BETWEEN … AND
      • IN(集合)
      • LIKE : 模糊查询
        • 占位符:
          • _ : 单个任意字符
          • % : 多个任意字符
      • IS NULL
      • and 或 &&
      • or 或 ||
      • not 或 !
CREATE TABLE student (
id INT, -- 编号
NAME VARCHAR(20), --  姓名
age INT, -- 年龄
sex VARCHAR(5), -- 性别
address VARCHAR(100), -- 地址
math INT, -- 数学
english INT -- 英语
);


INSERT INTO student(id, NAME, age, sex, address, math, english) VALUES
(1, '马云', 55, '男', '杭州', 66, 78),
(2, '马化腾', 45, '女', '深圳', 98, 87),
(3, '马景涛', 55, '男', '香港', 56, 77),
(4, '柳岩', 20, '女', '湖南', 76, 65),
(5, '柳青', 20, '男', '湖南', 86, NULL),
(6, '刘德华', 57, '男', '香港', 99, 99),
(7, '马德', 22, '女', '香港', 99, 99),
(8, '德玛西亚', 18, '男', '南京', 56, 65);```

```sql

SELECT * FROM student; 

-- 查询 姓名 和 年龄

SELECT 
	NAME, -- 姓名
	age -- 年龄
FROM student; -- 学生表

SELECT * FROM student;

SELECT address FROM student;

-- 去除重复的结果集
SELECT DISTINCT address FROM student;

SELECT DISTINCT NAME, address FROM student;

-- 计算 math 和 english 的分数之和

SELECT NAME, math, english, math + english FROM student;

-- 如果 有null 参与的运算, 计算结果都为null
SELECT NAME, math, english, math + IFNULL(english, 0) FROM student;

-- 起别名
SELECT NAME, math, english, math + IFNULL(english, 0) AS 总分 FROM student;
SELECT NAME, math 数学, english 英语, math + IFNULL(english, 0) 总分 FROM student;


SELECT * FROM student;
-- 查询年龄大于20岁
SELECT * FROM student WHERE age > 20;
-- 查询年龄大于等于20岁
SELECT * FROM student WHERE age >= 20;

-- 查询年龄等于20岁
SELECT * FROM student WHERE age = 20;

-- 查询年龄不等于20岁
SELECT * FROM student WHERE age != 20;
SELECT * FROM student WHERE age <> 20;

-- 查询年龄大于等于20岁 小于等于30岁
SELECT * FROM student WHERE age >= 20 && age <= 30;
SELECT * FROM student WHERE age >= 20 AND age <= 30;
SELECT * FROM student WHERE age BETWEEN 20 AND 30;



-- 查询年龄22岁, 18岁, 25岁的信息
SELECT * FROM student WHERE age = 22 OR age = 18 OR age = 25;
SELECT * FROM student WHERE age IN (22, 18, 25);


-- 查询英语成绩为null
SELECT * FROM student WHERE english = NULL; -- 不对的, null值不能用 = (!=) 判断
SELECT * FROM student WHERE english IS NULL;

-- 查询英语成绩为null
SELECT * FROM student WHERE english IS NOT NULL;


-- 查询姓马的有哪些? like
SELECT * FROM student WHERE NAME LIKE '马%';
-- 查询姓名第二个字是化的人
SELECT * FROM student WHERE NAME LIKE "_化%"; 
-- 查询姓名是三个字的人
SELECT * FROM student WHERE NAME LIKE "___";

-- 查询姓名中包含德的人
SELECT * FROM student WHERE NAME LIKE "%德%";

DQL : 查询语句

1. 排序查询
	* 语法: order by 子句
		* order by 排序字段1 排序方式1, 排序字段2 排序方式2 ...
	* 排序方式
		* ASC: 升序,默认的.
		* DESC: 降序
* 注意:
	* 如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件 
	
2. 聚合函数: 将一列数据作为一个整体, 进行纵向的计算
	1. count : 计算个数 
		1. 一般选择非空的列: 主键
		2. count(*)
	2. max: 计算最大值
	3. min: 计算最小值	
	4. sum: 计算和
	5. avg: 计算平均值
	
	* 注意: 聚合函数的计算, 排除了null值
		*解决方案 :
			1. 选择了不包含非空的列进行计算
			2. IFNULL函数
3. 分组查询
	1. 语法: group by 分组字段;
	2. 注意:
		1. 分组之后 查询的字段: 分组字段, 聚合函数
		2. where 和 having的区别
			1. where 在分组之前进行限定, 如果不满足条件, 则不参与分组.  having在分组之后限定,如果不满足结果,则不会被查询出来
			2. where 后不可跟聚合函数, having可以进行聚合函数的判断
4. 分页查询 
	1. 语法: limit 开始的索引, 每页查询的条数;
	2.  公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数
-- 每页显示3条记录

SELECT *FROM student LIMIT 0,3; -- 第一页

SELECT *FROM student LIMIT 3,3; -- 第二页

SELECT *FROM student LIMIT 6,3; -- 第三页
3. limit 是一个MySQL"方言"
SELECT * FROM student ORDER BY math ASC; -- 默认排序方式是升序
SELECT * FROM student ORDER BY math DESC; -- 默认排序方式是升序

-- 按照属性成绩排名, 如果数学成绩一样, 则按照英语成绩排名
 
SELECT * FROM student ORDER BY math ASC, english DESC;


SELECT COUNT(NAME) FROM student;
SELECT COUNT(IFNULL(english, 0)) FROM student;


SELECT MAX(math) FROM student;
SELECT MIN(math) FROM student;
SELECT SUM(math) FROM student;

SELECT AVG(math) FROM student;


SELECT * FROM student;

-- 按照性别分组, 分别查询男, 女同学的平均分
SELECT sex, AVG(math) FROM student GROUP BY sex;

-- 按照性别分组, 分别查询男, 女同学的平均分, 人数
SELECT sex, AVG(math), COUNT(id) FROM student GROUP BY sex;


-- 按照性别分组, 分别查询男, 女同学的平均分, 人数, 分数低于70分的不参与分组
SELECT sex, AVG(math), COUNT(id) FROM student WHERE math > 70 GROUP BY sex ;

-- 按照性别分组, 分别查询男, 女同学的平均分, 人数, 分数低于70分的不参与分组, 分组之后, 人数要大于2
SELECT sex, AVG(math), COUNT(id) FROM student WHERE math > 70 GROUP BY sex HAVING COUNT(id) > 2;

SELECT sex, AVG(math), COUNT(id) 人数 FROM student WHERE math > 70 GROUP BY sex HAVING 人数 > 2;

-- 每页显示3条记录

SELECT *FROM student LIMIT 0,3; -- 第一页

SELECT *FROM student LIMIT 3,3; -- 第二页

SELECT *FROM student LIMIT 6,3; -- 第三页


-- 公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数

约束

* 概念: 对表中数据进行限定, 保证数据的正确性, 有效性和完整性.
* 分类:
	1. 主键约束 : primary key
	2. 非空约束 : not null
	3. 唯一约束 : unique
	4. 外键约束 : foreign key
  • 非空约束 : not null 某一列的值不能为null
    1. 创建表时添加约束
CREATE TABLE stu(
		id INT,
		NAME VARCHAR(20) NOT NULL -- name为非空
); 
  1. – 创建表完后, 添加非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;
  1. 删除 name 非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20);
-- 创建表添加非空约束
CREATE TABLE stu(
	id INT,
	NAME VARCHAR(20) NOT NULL -- name为非空
); 
SELECT *FROM stu;

-- 删除name 的非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20);

-- 创建表完后, 添加非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;

INSERT INTO stu(id, NAME) VALUES(1, "张三丰");
INSERT INTO stu(id, NAME) VALUES(2,NULL), (3,"ss");

  • 唯一约束:unique, 某一列的值不能重复
    1. 注意 :
      • 唯一约束可以用NULL值, 但是只能有一条记录为NULL
    2. 在创建表时候添加
CREATE TABLE stu(
	id INT,
	phone_number VARCHAR(20) UNIQUE -- 手机号
);
3. 删除唯一约束
ALTER TABLE stu DROP INDEX phone_number;
  1. 在表创建完后, 添加唯一约束
ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;
DROP TABLE stu;

-- 在创建表时候添加
CREATE TABLE stu(
	id INT,
	phone_number VARCHAR(20) UNIQUE -- 手机号
);

SELECT * FROM stu;
INSERT INTO stu(id, phone_number) VALUES(1, "13812345678");
INSERT INTO stu(id, phone_number) VALUES(2, "13812345679");

-- 在表创建完后, 添加唯一约束
ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;

-- 删除唯一约束
ALTER TABLE stu DROP INDEX phone_number;

  • 主键约束 : primary key.
    1. 注意 :
      1. 含义 : 非空且唯一
      2. 一张表只能有一个字段为主键
      3. 主键就是表中记录的唯一标识
    2. 在创建表时,添加主键约束
create table stu(
	id int primary key, -- 给id添加主键约束
	name varchar(20)
); 

  1. 删除主键
-- 错误 alter table stu modify id int;
ALTER TABLE stu DROP PRIMARY KEY;
  1. 创建完表后,添加主键约束
ALTER TABLE stu MODIFY id INT PRIMARY KEY;
  1. 自动增长:
    1. 概念 : 如果某一列是数值类型的, 使用auto_increment 可以来完成值得自动增长
    2. 在创建表时,添加主键约束,并且完成主键的自增长
create table stu(
	id int primary key auto_increment, -- 给id添加主键约束
	name varchar(20)
); 

  1. 删除自动增长
ALTER TABLE stu MODIFY id INT;
  1. 添加自动增长
ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;
  • 外键约束 : foreign key
    1. 在创建表时, 可以添加外键, 让表与表产生关系,从而保证数据的正确性
      • 语法 :
create table 表名(
	...
	外键列
	constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称)
);
2. 删除外键
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
3. 创建表之后,添加外键
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称)
  1. 级联操作

    1. 添加级联操作
      语法 : ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON DELETE CASCADE;
      
  2. 分类 :

    1. 级联更新 : ON UPDATE CASCADE
    2. 级联删除 : ON DELETE CASCADE

数据库的设计

  1. 多表之间的关系
    1. 分类
      1. 一对一 (了解):
      * 如 : 人和身份证
      * 分析 : 一个人只有一个身份证, 一个身份证只能对应一个人
      2. 一对多(多对一) :
      * 如: 部门和员工
      * 分析: 一个部门有多个员工, 一个员工只能对应一个部门
      3. 多对多:
      * 如: 学生和课程
      * 分析: 一个学生可以选择很多门课程, 一个课程也可以被很多学生选择

    2. 实现关系 :

      1. 一对多(多对一) :
        • 如 : 部门和员工
        • 实现方式 : 在多的一方建立外键,指向一的一方的主键
          JavaWeb 前端_第4张图片
    3. 多对多:

      • 如: 学生和课程
      • 实现方式 : 多对多关系实现需要借助第三张中间表, 中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键
        JavaWeb 前端_第5张图片
    4. 一对一(了解)

      • 如: 人和身份证
      • 实现方式: 一对一关系实现, 可以在任意一方添加唯一外键指向另一方的主键
        JavaWeb 前端_第6张图片
    5. 案例
      JavaWeb 前端_第7张图片
      联合主键
      把两个部分作为主键的一部分

– 把中间表的两个字段合起来作为联合主键

  1. 数据库设计的范式
    • 概念 : 设计数据库时,需要遵循的一些规范, 要遵循后边的范式要求, 必须先遵循前边的所有范式要求

    • 设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
      关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。

    • 分类 :
      1. 第一范式(1NF): 每一列都是不可分割的原子数据项

        2. 第二范式(2NF): 在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)
        	* 几个概念:
        		1. 函数依赖 : A---> B,如果通过A属性(属性组)的值. 可以确定唯一B属性的值,则称B依赖于A
        			例如: 学号 ---> 姓名 (学号, 课程名称) ---> 分数
        		2. 完全函数依赖 :A--->B, 如果 A 是一个属性组, 则 B 属性值得确定需要依赖于A属性组中所有的属性值
        				例如:(学号, 课程名称) --->分数
        		3. 部分函数依赖:A--->B, 如果 A 是一个属性组, 则 B 属性值得确定只需要依赖于A属性组中某一些值即可
        				例如:(学号, 课程名称) --->姓名
        		4. 传递函数依赖 : A ---> B, B --->C ,如果通过A属性(属性组)的值,可以确定唯一B属性的值,在通过B属性(属性组)的值可以确定唯一C属性的值,则称C传递函数依赖A
        			例如; 学号 --->系名, 系名 --- >系主任
        		5. 码: 如果在一张表中,一个属性或者属性组, 被其他所有属性所完全依赖,则称这个属性(属性值)为该表的码
        			例如: 该表中码为:(学号,课程名称)
        			* 主属性:码属性组中的所有属性
        			* 非主属性:除过码属性组的属性
      
        3. 第三范式(3NF): 在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)![在这里插入图片描述](https://img-blog.csdnimg.cn/318df73ba31d4caa88f90bcf029e293b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5YGa5Liq56yo576K,size_20,color_FFFFFF,t_70,g_se,x_16)
      

JavaWeb 前端_第8张图片
JavaWeb 前端_第9张图片
JavaWeb 前端_第10张图片

数据库的备份和还原

  1. 命令行:

    • 语法 :
      * 备份 : mysqldump -u用户名 -p密码 数据库名称 > 保存的路径
      * 还原 :
      1. 登录数据库
      2. 创建数据库
      3. 使用数据库
      4. 执行文件 source 文件路径
  2. 图形化工具:

多表查询

* 查询语法 : 
		select
			列名列表
		from
			表名列表
		where......
* 准备sql
 # 创建部门表
ALTER TABLE dept CHARACTER SET utf8;
CREATE TABLE dept(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20)

);
SELECT * FROM dept;
INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部');

# 创建员工表
CREATE TABLE emp(
		id INT PRIMARY KEY AUTO_INCREMENT,
		NAME VARCHAR(10),
		gender CHAR(1), -- 性别
		salary DOUBLE, -- 工资
		join_date DATE, -- 入职日期
		dept_id INT,
		FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键, 关联部门表(部门表的主键)
);

INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013-02-24',1);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010-12-02',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008-08-08',2);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015-10-07',3);
INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1);
  • 笛卡尔积

    • 有两个集合 A,B 取这两个集合的所有组成情况
    • 要完成多表查询,需要消除无用的数据
  • 多表查询的分类

    1. 内连接查询

      1. 隐式内连接: 使用where条件消除无用数据
        • 例子:
          SELECT 
          	t1.name, -- 员工表的姓名
          	t1.`gender`, -- 员工表的性别
          	t2.`name` -- 部门表的姓名
          FROM 
          	emp t1, 
          	dept t2
          WHERE
          	t1.`dept_id` = t2.`id`
          
      2. 显示内连接:
        • 语法 : select 字段列表 from 表名1 [inner] join 表名2 on 条件
        • 例如 :
          SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`;
          SELECT * FROM emp JOIN dept ON emp.`dept_id` = dept.`id`;
          
      3. 内连接查询
        1. 从哪些表中查询数据
        2. 条件是什么
        3. 查询哪些字段
    2. 外连接查询

      1. 左外连接

        • 语法: select 字段列表 from 表1 left [outer] join 表2 on 条件;
        • 查询的是左表所有数据及交集部分
      2. 右外连接

        • 语法: select 字段列表 from 表1 right [outer] join 表2 on 条件;
        • 查询的是右表所有数据及交集部分
        SELECT t1.*, t2.`name` FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`;
        
        SELECT t1.*, t2.`name` FROM emp t1 RIGHT JOIN dept t2 ON t1.`dept_id` = t2.`id`;
        
        SELECT t1.*, t2.`name` FROM dept t2 RIGHT JOIN emp t1 ON t1.`dept_id` = t2.`id`;
        
        
    3. 子查询:

      • 概念 : 查询中嵌套查询, 称嵌套查询为子查询
        -- 查询工资最高的员工信息
        
        -- 1. 查询最高的工资是多少 9000
        
        SELECT MAX(salary) FROM emp;
        
        -- 2. 查询员工信息, 并且工资等于9000的
        SELECT * FROM emp WHERE emp.`salary` = 9000;
        
        -- 一条SQL就完这个操作. 子查询
        SELECT * FROM emp WHERE emp.`salary` = (SELECT MAX(salary) FROM emp);
        
      • 子查询的不同情况
        1. 子查询的结果是单行单列的 :
          *子查询可以作为条件,使用运算符去判断, 运算符: > >= < <= =
          -- 查询员工工资小于平均工资的人
          SELECT * FROM emp WHERE emp.`salary` < (SELECT AVG(salary) FROM emp);
          
        2. 子查询的结果是多行单列的 :
          • 子查询可以作为条件,使用运算符 in 进行判断
            – 查询’财务部’ 和 '市场部’所有的员工信息
            SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部'; 
            SELECT * FROM emp WHERE dept_id = 3 OR dept_id = 2;
            
            SELECT * FROM emp WHERE dept_id IN (3,2);
            -- 子查询
            SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部');
            
        3. 子查询的结果是多行多列的 :
          • 子查询可以作为一张虚拟表
            – 查询员工的入职日期2011-11-11日之后的员工信息和部门信息

            -- 查询员工的入职日期2011-11-11日之后的员工信息和部门信息
            -- 子查询
            SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11';
            SELECT * FROM dept t1, (SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11') t2 
            WHERE t1.`id` = t2.dept_id;
            
            -- 普通内连接
            SELECT * FROM emp t1, dept t2 WHERE t1.`dept_id` = t2.`id` AND t1.`join_date` > '2011-11-11';
            

多表查询练习

#多表查询练习
#创建练习用表

-- 部门表
CREATE TABLE dept(
	id INT PRIMARY KEY, -- 部门ID
	dname VARCHAR(50), -- 部门名称
	loc VARCHAR(50) -- 部门地址
);

-- 添加4个部门
INSERT INTO dept VALUES
( 10, '研发部', '北京' ),
( 20, '学工部', '上海' ),
( 30, '销售部', '广州' ),
( 40, '财务部', '深圳' );

-- 职务表,职务名称,植物描述
CREATE TABLE job(
	id INT PRIMARY KEY, -- 职务ID
	jname VARCHAR(20), -- 职务名称
	descripition VARCHAR(50) -- 职责
);

-- 添加4个职务
INSERT INTO job VALUES
(1,'董事长','管理整个公司,接单'),
(2,'经理','管理部门员工'),
(3,'销售员','向客人推销产品'),
(4,'文员','使用办公软件');



-- 工资等级表
CREATE TABLE salarygrade(
	grade INT PRIMARY KEY, -- 级别
	losalary INT, -- 最低工资
	hisalary INT -- 最高工资
);

-- 添加工资信息
INSERT INTO salarygrade VALUES
(1,7000,12000),
(2,12000,14000),
(3,14000,20010),
(4,20010,30010),
(5,30010,99990);

-- 员工表
CREATE TABLE emp(
	id INT PRIMARY KEY, -- 员工ID
	ename VARCHAR(50), -- 员工姓名
	job_id INT, -- 职务id
	mgr INT, -- 上级领导
	joindate DATE, -- 入职日期
	salary DECIMAL(7,2), -- 工资
	bonus DECIMAL(7,2), -- 奖金
	dept_id INT, -- 所在部门编号
	FOREIGN KEY(job_id) REFERENCES job(id), -- 职务ID外连接
	FOREIGN KEY(dept_id) REFERENCES dept(id) -- 部门ID外连接
);

-- 添加员工信息
INSERT INTO emp VALUES
(1001,'孙悟空',4,1004,'2000-12-17',8000.00,NULL,20),
(1002,'卢俊义',3,1006,'2001-02-20',16000.00,3000.00,30),
(100,'林冲',3,1006,'2001-02-22',12500.00,5000.00,30),
(1004,'唐僧',2,1009,'2001-04-02',29750.00,NULL,20),
(1005,'李逵',4,1006,'2001-09-28',12500.00,14000.00,30),
(1006,'宋江',2,1009, '2001-05-01',28500.00,NULL,30),
(1007,'刘备',2,1009,'2001-09-01',24500.00,NULL,10),
(1008,'猪八戒',4,1004,'2007-04-19',30000.00,NULL,20),
(1009,'罗贯中',1,NULL,'2001-11-17',50000.00,NULL,10),
(1010,'吴用',3,1006,'2001-09-08',15000.00,0.00,30),
(1011,'沙僧',4,1004,'2007-05-23',11000.00,NULL,20),
(1012,'李逵',4,1006,'2001-12-03',9500.00,NULL,30),
(1013,'小白龙',4,1004,'2001-12-03',30000.00,NULL,20),
(1014,'关羽',4,1007,'2002-01-23',13000.00,NULL,10);

-- 需求:

-- 1. 查询所有员工信息, 查询员工编号,员工姓名, 工资, 职务名称, 职务描述
/*

分析 :
	1.查询员工编号,员工姓名, 需要查询emp表, 工资, 职务名称, 职务描述 需要查询job表
	2.查询的条件 emp.jobid = job.id		
	
*/
SELECT
	t1.`id`, -- 员工编号
	t1.`ename`, -- 员工姓名
	t1.`salary`, -- 工资
	t2.`jname`, -- 职务名称
	t2.`descripition` -- 职务描述
FROM 
	emp t1, 
	job t2
WHERE
	t1.`job_id` = t2.`id`;

-- 2. 查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
	

/*

分析 :
	1.查询员工编号,员工姓名, 需要查询emp表, 工资, 职务名称, 职务描述 需要查询job表 部门名称,部门位置 需要查询dept表
	
	2.查询的条件 emp.job_id = job.id and emp.dept_id = dept.id	
	
*/

SELECT
	t1.`id`, -- 员工编号
	t1.`ename`, -- 员工姓名
	t1.`salary`, -- 工资
	t2.`jname`, -- 职务名称
	t2.`descripition`, -- 职务描述
	t3.`dname`,
	t3.`loc`
	
FROM 
	emp t1, 
	job t2,
	dept t3
WHERE
	t1.`job_id` = t2.`id`
	AND  t1.`dept_id` = t3.`id`;



-- 3.查询员工姓名,工资,工资等级

/*
分析: 
	1. 员工姓名, 工资 emp 工资等级 salarygrade
	2. 条件 emp.salary >= salarygrade.losalary and emp.salary <= salarygrade.hisalary
		emp.salary BETWEEN salarygrade.losalary and salarygrade.hisalary
*/
SELECT 
	t1.`ename`,
	t1.`salary`,
	t2.`grade`
FROM 
	emp t1,
	salarygrade t2
WHERE	
	t1.`salary` BETWEEN t2.`losalary` AND t2.`hisalary`;


-- 4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级

/*
分析:	
1. 员工姓名, 工资 emp, 职务名称, 职务描述 job, 部门名称,部门位置, dept, 工资等级 salarygrade
2. 条件: 查询的条件 emp.job_id = job.id and emp.dept_id = dept.id and emp.salary BETWEEN salarygrade.losalary and salarygrade.hisalary	

*/
SELECT 
	t1.`ename`,
	t1.`salary`,
	t2.`jname`,
	t2.`descripition`,
	t3.`dname`,
	t3.`loc`,
	t4.`grade`
	
FROM 
	emp t1, job t2, dept t3, salarygrade t4
WHERE
	t1.`job_id` = t2.`id` 
	AND t1.`dept_id` = t3.`id`
	AND t1.`salary` BETWEEN	t4.`losalary` AND t4.`hisalary`;
	
-- 5.查询出部门编号,部门名称,部门位置,部门人数
/*
	分析:
		1.部门编号,部门名称,部门位置 dept表, 部门人数 emp表
		2.分组查询,按照 emp.dept_id 完成分组,查询count(id)
		3.使用子查询将第二部的查询结果和dept表进行关联查询
	
*/
SELECT
	t1.`id`, t1.`dname`, t1.`loc`, t2.total
FROM
	dept t1,
	(SELECT
		dept_id, COUNT(id) total
	FROM 
		emp
	GROUP BY dept_id) t2
WHERE t1.`id` = t2.`dept_id`;
	 

-- 6. 查询处所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询
/*
	分析:
		1.查询所有员工的姓名 emp,直接上级的姓名 emp
			*emp表的id 和 mgr 是自关联的
		2. 条件 emp.id = emp.mgr
		3. 查询左表的所有数据, 和交集数据
			*使用左外连接查询
*/
/*
select
	t1.`ename`,
	t1.`mgr`,
	t2.`id`,
	t2.`ename`
from emp t1, emp t2
where t1.`mgr` = t2.`id`;
*/
SELECT
	t1.`ename`,
	t1.`mgr`,
	t2.`id`,
	t2.`ename`
FROM 
	emp t1
LEFT JOIN
	emp t2
ON 
	t1.`mgr` = t2.`id`;

事务

  1. 事务的基本特征

  2. 概念:

    • 如果一个包含多个步骤的业务操作, 被事务管理, 那么这些操作要么同时成功, 要么同时失败
      JavaWeb 前端_第11张图片
  3. 操作:

    1. 开启事务: start transaction;
    2. 回滚: rollback;
    3. 提交: commit;
      4.MySQL数据库中事务默认自动提交
    • 一条DML(增删改) 语句会自动提交一次事务
    • 事务提交的两种方式:
      • 自动提交:
        * musql就是自动提交的
        * 一条DML(增删改)语句会自动提交一次事务
      • 手动提交 :
        * Oracle 数据库默认是手动提交事务
        * 需要先开启事务, 再提交
      • 修改事务的默认提交方式 :
        * 查看事务的默认提交方式 : SELECT @@autocommit; – 1 代表自动提交, 0 代表手动提交
        * 修改默认提交方式: SET @@autocommit = 0;
  4. 事务的四大特征

    1. 原子性 : 是不可分割的最小操作单位, 要么同时成功, 要么同时失败
    2. 持久性: 当事务提交或回滚后, 数据库会持久化的保存数据
    3. 隔离性: 多个事务之间, 相互独立.
    4. 一致性: 事务操作前后, 总量不变
  5. 事务的隔离级别(了解)

    • 概念: 多个事务之间隔离的, 相互独立的, 但是如果多个事务操作同一批数据,则会引发一些问题, 设置不同的隔离级别就可以解决这些问题

    • 存在问题:
      1. 脏读: 一个事务, 读取到另一个事务中没有提交的数据
      2. 不可重复读(虚读): 在同一个事务中,两次读取到的数据不一样
      3. 幻读: 一个事务操作(DML)数据表中所有记录, 另一个事务添加了一条数据, 则第一个事务查询不到自己的修改.
      (事务在插入已经检查过不存在的记录时,惊奇的发现这些数据已经存在了,之前的检测获取到的数据如同鬼影一般。)

    • 隔离级别 :
      1. read uncommitted : 读未提交
      * 产生的问题 : 脏读,不可重复读,幻读
      2. read committed : 读已提交 (Oracle默认)
      * 产生的问题 : 不可重复读,幻读
      3. repeatable read : 可重复读 (MySQL默认)
      * 产生的问题 : 幻读
      4. serializable : 串行化 (把表加锁, 同时只能一个去访问操作)
      * 可以解决所有的问题

        * 注意 :隔离级别从小到大安全性越来越高,但是效率越来越低
        
        * 数据库查询隔离级别 :
        	* select @@tx_isolation;
        * 数据库设置隔离级别 :
        	* set global transaction isolation level 级别字符串; 
      
  • 演示 :
    set global transaction isolation level read uncommitted;
    start transaction;
    – 转账操作
    update account set balance = balacnce - 500 where id = 1;
    update account set balance = balacnce + 500 where id = 2;

DCL

  • SQL 分类:
    1. DDL : 操作数据库和表
    2. DML : 增删改表中的数据
    3. DQL : 查询表中的数据
    4. DCL : 管理用户,授权

  • DBA : 数据库管理员

  • DCL : 管理用户,授权

    1. 管理用户

      1. 添加用户 :

        • CREATE USER ‘用户名’@‘主机名’ IDENTIFIED BY ‘密码’;
      2. 删除用户

        • DROP USER ‘用户名’@‘主机名’;
      3. 修改用户密码
        SET PASSWORD FOR ‘用户名’@‘主机名’ = PASSWORD(‘新密码’);
        SET PASSWORD FOR ‘lisi’@‘localhost’ = PASSWORD(‘123’);

        • mysql 中忘记了root 用户的密码?
          1. cmd —> net stop mysql 停止mysql 服务
            • 需要管理员运行改cmd
          2. 使用无验证方式启动mysql服务 : mysqld --skip-grant-tables
          3. 打开新的cmd窗口,直接输入mysql命令,敲回车,就可以登录成功
          4. use mysql;
          5. UPDATE USER SET PASSWORD = PASSWORD(‘新密码’) WHERE USER = ‘root’;
          6. 关闭两个窗口
          7. 打开任务管理器,手动结束mysqld.exe的进程
          8. 启动mysql 服务 cmd —> net start mysql
          9. 使用新密码登录
      4. 查询用户
        – 1.切换到mysql 数据库
        USE mysql;
        – 2. 查询user表
        SHOW TABLES;
        DESC USER;
        SELECT * FROM USER;

         * 通配符 : % 表示可以在任意主机使用用户登录数据库
        
    2. 权限管理:

      1. 查询权限:
        – 查询权限
        SHOW GRANTS FOR ‘用户名’@‘主机名’;
        SHOW GRANTS FOR ‘lisi’@‘localhost’;

         SHOW GRANTS FOR 'root'@'localhost';
         
         SHOW GRANTS FOR 'root'@'%';
        
      2. 授予权限:
        – 授予权限
        grant 权限列表 on 数据库.表名 to ‘用户名’@‘主机名’;

        – 给root用户授予所有权限,在任意数据库任意表上
        GRANT ALL ON . TO ‘root’@’%’;

      3. 收回权限:
        – 撤销权限:
        REVOKE 权限列表 ON 数据库.表名 FROM ‘用户名’@‘主机名’;
        REVOKE SELECT,DELETE,UPDATE ON db3.account FROM ‘lisi’@‘localhost’;

JDBC

  • 概念 : Java DataBase Connectivity : Java 数据库连接, Java语言操作数据库
  • JDBC本质:其实是官方(Sun公司)定义的一套操作所有关系型数据库的规则, 即接口. 各个数据库厂商去实现这套接口, 提供数据库驱动jar包. 我们可以使用这套接口(JDBC)编程, 真正执行的代码是驱动jar包中的实现类
    Person 接口 Worker实现类 Person p = new Worker(); p.eat();
    JavaWeb 前端_第12张图片
  1. 快速入门:
    • 步骤 :
      1. 导入驱动jar包 mysql-connector-java-5.1.47-bin.jar
        1. 复制 mysql-connector-java-5.1.47-bin.jar 到项目的libs目录下
        2. 右键 —> Add As Library
      2. 注册驱动
      3. 获取数据库连接对象 Connection
      4. 定义sql
      5. 获取执行sql语句的对象 Statement
      6. 执行sql , 接受返回结果
      7. 处理结果
      8. 释放资源
package cn.itcast.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

/**
 * JDBC快速入门
 */
public class JdbcDemo1 {
    public static void main(String[] args) throws Exception {

        //1.导入驱动jar包
        //2.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        	// 将字节码文件加载进入内存,返回Class对象,
            // 多用于配置文件,将类名定义在配置文件中,读取文件,加载类
        //3.获取数据库的连接对象
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3?useSSL=false", "root", "123456");
        //4.定义sql语句
        String sql = "update account set balance = 500 where id = 1";
        //5.获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();
        //6.执行方法
        int count = stmt.executeUpdate(sql);
        //7.处理结果
        System.out.println(count);
        //8.释放资源
        stmt.close();
        conn.close();
    }
}

  1. 详解各个对象:
    1. DriverManager : 驱动管理对象

      • 功能 :
        1. 注册驱动 : 告诉程序该使用哪一个数据库驱动jar包
          static void registerDriver(Driver driver) : 注册与给定的驱动程序 DriverManager 。
          写代码使用 : Class.forName(“com.mysql.jdbc.Driver”);
          通过查看源码发现: 在com.mysql.jdbc.Driver类中存在静态代码块
          static {
          try {
          java.sql.DriverManager.registerDriver(new Driver());
          } catch (SQLException E) {
          throw new RuntimeException(“Can’t register driver!”);
          }
          }
          注意: mysql5之后的驱动jar包可以省略注册驱动的步骤, 因为可以在mysql-connector-java的包下获取配置文件
        2. 获取数据库连接 :
          • 方法 : static Connection getConnection(String url, String user, String password) 尝试建立与给定数据库URL的连接
          • 参数 :
            • url : 指定连接的路径
              • 语法 : jdbc:mysql://ip地址(域名):端口号/数据库名称
              • 例子 : jdbc:mysql://localhost:3306/db3
              • 细节 :如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为 : jdbc:mysql:///数据库名称
            • user : 用户名
            • password : 密码
    2. Connection : 数据库连接的对象
      1. 功能 :
      1. 获取执行的对象
      * Statement createStatement()
      * PreparedStatement prepareStatement(String sql)
      2. 管理事务:
      * 开启事务 : void setAutoCommit(boolean autoCommit) : 调用改方法设置参数为false, 即开启事务
      * 提交事务 : void commit()
      * 回滚事务 : void rollback()

    3. Statement : 执行sql的对象
      1. 执行sql
      1. boolean execute(String sql) : 可以执行任意的sql 了解
      2. int executeUpdate(String sql) : 执行DML(insert, update, delete)语句, DDL(create, alter, drop)语句
      * 返回值 : 影响的行数 , 可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功, 反之, 则失败
      3. ResultSet executeQuery(String sql) :执行DQL(select)语句
      2. 练习
      1. account表 添加一条记录
      2. account表 修改记录
      3. account表 删除一条记录

    4. ResultSet : 结果集对象, 封装查询结果

      • boolean next() : 游标向下移动一行, 判断当前行是否最后一行末尾(是否有数据), 如果是, 则返回false, 如果不是则返true

      • getXxx(参数) : 获取数据

        • Xxx : 代表数据类型 如: int getInt(), String getString()
        • 参数:
          1. int : 代表列的编号, 从1开始 如: getString(1)
          2. String : 代表列名称 如: getDouble(“balance”)
      • 注意 :
        * 使用步骤
        1. 游标向下移动一行
        2. 判断是否有数据
        3. 获取数据

         	```java
         	            //6.处理结果
         	            //6.1 让光标向下移动一行
         	            //循环判断游标是否是最后一行末尾
         	            while (rs.next()) {
         	                //6.2 获取数据
         	                int id = rs.getInt(1);
         	                String name = rs.getString("name");
         	                double balance = rs.getDouble(3);
         	                System.out.println(id + "---" + name + "---" + balance);
         	            }
         	```
         * 练习 :
         	* 定义一个方法, 查询emp表的数据, 将其封装为 对象,然后装载集合, 返回.
         		1. 定义Emp类
         		2. 定义方法 Public List findAll() {}
         		3. 实现方法 select * from emp;
        
    5. PreparedStatement :执行sql的对象

      1. SQL注入问题 : 在拼接sql时, 有一些sql的特殊关键字参与字符串的拼接, 会造成安全性问题

        1. 输入用户随便, 输入密码 : a’ or ‘a’ = 'a
        2. SQL: select * from user where username = ‘dadsadasd’ and password = ‘a’ or ‘a’ = ‘a’
      2. 解决sql注入问题 :使用 PreparedStatement 对象解决SQL注入问题

      3. 预编译的SQL :参数使用?作为占位符

      4. 步骤 :
        1. 导入驱动jar包 mysql-connector-java-5.1.47-bin.jar
        1. 复制 mysql-connector-java-5.1.47-bin.jar 到项目的libs目录下
        2. 右键 —> Add As Library
        2. 注册驱动
        3. 获取数据库连接对象 Connection
        4. 定义sql
        * 注意 :SQL的参数使用?作为占位符 , 如: select * from user where username = ?’ and password = ?
        *
        5. 获取执行sql语句的对象 PreparedStatement Connection.PreparedStatement(String sql)
        6. 给?赋值:
        * 方法 : setXxx(参数1, 参数2)
        * 参数1 : ? 的位置编号 从1开始
        * 参数2 : ? 的值
        7. 执行sql , 接受返回结果 ,不需要传递sql语句
        8. 处理结果
        9. 释放资源

    6. 注意 : 后期都会使用PreparedStatement 来 完成增删改查的所有操作

      1. 可以防止SQL注入
      2. 效率更高
package cn.itcast.jdbc;

import cn.itcast.util.JDBCUtils;

import java.sql.*;
import java.util.Scanner;

/**
 * * 练习
 * 	* 需求 :
 * 		1. 通过键盘录入用户名和密码
 * 		2. 判断用户是否登录成功
 */
public class JDBCDemo9 {
    public static void main(String[] args) {
        //1.键盘录入,接受用户名和密码
        Scanner in = new Scanner(System.in);
        System.out.println("请输入用户名: ");
        String username = in.nextLine();
        System.out.println("请输入密码: ");
        String password = in.nextLine();
        //2.调用方法
        boolean flag = new JDBCDemo9().login2(username, password);
        //3.判断结果, 输出不同语句
        if (flag) {
            //登录成功
            System.out.println("登录成功!");
        } else {
            //登录失败
            System.out.println("用户名或密码错误!");
        }
    }

    /**
     * 登录方法一, 使用Statement实现
     * @param username
     * @param password
     * @return
     */
    public boolean login(String username, String password) {
        if (username == null || password == null) {
            return false;
        }
        // 连接数据库判断是否登录成功
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();

            //2.定义sql
            String sql = "select * from user where username = '" + username + "' and password = '"+ password + "' ";
            System.out.println(sql);
            //3.获取执行sql的对象
            stmt = conn.createStatement();
            //4.执行查询
            rs = stmt.executeQuery(sql);
            //5.判断
            /*if (rs.next()) { // 如果有下一行,则返回true
                return true;
            } else {
                return false;
            }*/
            return rs.next();// 如果有下一行,则返回true
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, stmt, conn);
        }
        return false;
    }

    /**
     * 登录方法二,使用PreparedStatement 实现
     * @param username
     * @param password
     * @return
     */
    public boolean login2(String username, String password) {
        if (username == null || password == null) {
            return false;
        }
        // 连接数据库判断是否登录成功
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();

            //2.定义sql
            String sql = "select * from user where username = ? and password = ?";
            //3.获取执行sql的对象
            pstmt = conn.prepareStatement(sql);
            //给? 赋值
            pstmt.setString(1, username);
            pstmt.setString(2, password);
            //4.执行查询,不需要传递sql
            rs = pstmt.executeQuery();
            //5.判断
            /*if (rs.next()) { // 如果有下一行,则返回true
                return true;
            } else {
                return false;
            }*/
            return rs.next();// 如果有下一行,则返回true
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, pstmt, conn);
        }
        return false;
    }

}

抽取JDBC的工具类 : JDBCUtils

* 目的 : 简化书写
* 分析 : 
				1. 注册驱动也抽取
				
				2. 抽取一个方法获取连接对象
					* 需求:不想传递参数(麻烦), 还得保证工具类的通用性
					* 解决:配置文件
						jdbc.properties
							url = 
							user = 
							password = 
				3. 抽取一个方法释放资源
package cn.itcast.util;

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

/**
 * JDBC 工具类
 */
public class JDBCUtils {
    private static String url;
    private static String user;
    private static String password;
    private static String driver;

    /**
     * 文件的读取, 只需要读取一次即可拿到这些值, 使用静态代码块来完成
     */
    static {

        try {

            //读取资源文件, 获取值.
            //1. 创建Properties集合类
            Properties pro = new Properties();

            //获取src路径下的文件的方式 ---> ClassLoader 类加载器
            //类加载器可以把字节码文件加载进内存
            //而且可以获取src路径下的资源路径

            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            URL res = classLoader.getResource("jdbc.properties");
            //统一资源定位符
            String path = res.getPath();
            //获取字符串路径
            System.out.println(path);
            //  /E:/Java_Project/itcast/out/production/day04_jdbc/jdbc.properties

            //2.加载文件
            //pro.load(new FileReader("E:\\Java_Project\\itcast\\day04_jdbc\\src\\jdbc.properties"));
            pro.load(new FileReader(path));
            //3.获取数据, 赋值
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //4.注册驱动
            Class.forName(driver);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     * @return 连接对象
     */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }

    /**
     * 释放资源
     * @param stmt
     * @param conn
     */
    public static void close(Statement stmt, Connection conn) {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 释放资源重载
     * @param rs
     * @param stmt
     * @param conn
     */
    public static void close(ResultSet rs, Statement stmt, Connection conn) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

    /**
     * 演示JDBC工具类
     * @return
     */

    public List<Emp> findAll2() {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        List<Emp> list = null;
        try {
            /*//1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql:///db3?useSSL=false", "root", "123456");*/


            conn = JDBCUtils.getConnection();
            //3.定义sql
            String sql = "select * from emp";
            //4.获取执行sql的对象
            stmt = conn.createStatement();
            //5.执行sql
            rs = stmt.executeQuery(sql);
            //6.遍历结果集,封装对象,装载结合
            Emp emp = null;
            list = new ArrayList<Emp>();
            while (rs.next()) {
                //获取数据
                int id = rs.getInt("id");
                String ename = rs.getString("ename");
                int job_id = rs.getInt("job_id");
                int mgr = rs.getInt("mgr");
                Date joindate = rs.getDate("joindate");
                double salary = rs.getDouble("salary");
                double bonus = rs.getDouble("bonus");
                int dept_id = rs.getInt("dept_id");
                //创建emp对象,并赋值
                emp = new Emp();
                emp.setId(id);
                emp.setEname(ename);
                emp.setJob_id(job_id);
                emp.setMgr(mgr);
                emp.setJoindate(joindate);
                emp.setSalary(salary);
                emp.setBonus(bonus);
                emp.setDept_id(dept_id);

                //装载集合
                list.add(emp);
            }
        }  catch (SQLException e) {
            e.printStackTrace();
        } finally {
            /*if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }


            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }*/
            JDBCUtils.close(rs, stmt, conn);
        }
        return list;
    }
  • 练习
    • 需求 :
      1. 通过键盘录入用户名和密码
      2. 判断用户是否登录成功
        • select * from user where username = “” and password = “”;
        • 如果这个sql有查询结果,则成功,反之则失败
    • 步骤 :
      1. 创建数据库表 user
        CREATE DATABASE db4;
        CREATE TABLE USER(
        	id INT PRIMARY KEY AUTO_INCREMENT,
        	username VARCHAR(32),
        	PASSWORD VARCHAR(32)
        );
        
        SELECT * FROM USER;
        
        INSERT INTO USER VALUES(NULL, 'zhangsan', '123'),(NULL, 'lisi', '234');
        
package cn.itcast.jdbc;

import cn.itcast.util.JDBCUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

/**
 * * 练习
 * 	* 需求 :
 * 		1. 通过键盘录入用户名和密码
 * 		2. 判断用户是否登录成功
 */
public class JDBCDemo9 {
    public static void main(String[] args) {
        //1.键盘录入,接受用户名和密码
        Scanner in = new Scanner(System.in);
        System.out.println("请输入用户名: ");
        String username = in.nextLine();
        System.out.println("请输入密码: ");
        String password = in.nextLine();
        //2.调用方法
        boolean flag = new JDBCDemo9().login(username, password);
        //3.判断结果, 输出不同语句
        if (flag) {
            //登录成功
            System.out.println("登录成功");
        } else {
            //登录失败
            System.out.println("用户名或密码错误!");
        }
    }

    /**
     *
     */
    public boolean login(String username, String password) {
        if (username == null || password == null) {
            return false;
        }
        // 连接数据库判断是否登录成功
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();

            //2.定义sql
            String sql = "select * from user where username = '" + username + "' and password = '"+ password + "' ";
            //3.获取执行sql的对象
            stmt = conn.createStatement();
            //4.执行查询
            rs = stmt.executeQuery(sql);
            //5.判断
            /*if (rs.next()) { // 如果有下一行,则返回true
                return true;
            } else {
                return false;
            }*/
            return rs.next();// 如果有下一行,则返回true
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, stmt, conn);
        }
        return false;
    }
}

package cn.itcast.jdbc;

import cn.itcast.util.JDBCUtils;

import java.sql.*;
import java.util.Scanner;

/**
 * * 练习
 * 	* 需求 :
 * 		1. 通过键盘录入用户名和密码
 * 		2. 判断用户是否登录成功
 */
public class JDBCDemo9 {
    public static void main(String[] args) {
        //1.键盘录入,接受用户名和密码
        Scanner in = new Scanner(System.in);
        System.out.println("请输入用户名: ");
        String username = in.nextLine();
        System.out.println("请输入密码: ");
        String password = in.nextLine();
        //2.调用方法
        boolean flag = new JDBCDemo9().login2(username, password);
        //3.判断结果, 输出不同语句
        if (flag) {
            //登录成功
            System.out.println("登录成功!");
        } else {
            //登录失败
            System.out.println("用户名或密码错误!");
        }
    }

    /**
     * 登录方法一, 使用Statement实现
     * @param username
     * @param password
     * @return
     */
    public boolean login(String username, String password) {
        if (username == null || password == null) {
            return false;
        }
        // 连接数据库判断是否登录成功
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();

            //2.定义sql
            String sql = "select * from user where username = '" + username + "' and password = '"+ password + "' ";
            System.out.println(sql);
            //3.获取执行sql的对象
            stmt = conn.createStatement();
            //4.执行查询
            rs = stmt.executeQuery(sql);
            //5.判断
            /*if (rs.next()) { // 如果有下一行,则返回true
                return true;
            } else {
                return false;
            }*/
            return rs.next();// 如果有下一行,则返回true
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, stmt, conn);
        }
        return false;
    }

    /**
     * 登录方法二,使用PreparedStatement 实现
     * @param username
     * @param password
     * @return
     */
    public boolean login2(String username, String password) {
        if (username == null || password == null) {
            return false;
        }
        // 连接数据库判断是否登录成功
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();

            //2.定义sql
            String sql = "select * from user where username = ? and password = ?";
            //3.获取执行sql的对象
            pstmt = conn.prepareStatement(sql);
            //给? 赋值
            pstmt.setString(1, username);
            pstmt.setString(2, password);
            //4.执行查询,不需要传递sql
            rs = pstmt.executeQuery();
            //5.判断
            /*if (rs.next()) { // 如果有下一行,则返回true
                return true;
            } else {
                return false;
            }*/
            return rs.next();// 如果有下一行,则返回true
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, pstmt, conn);
        }
        return false;
    }

}

JDBC控制事务 :

  1. 事务 : 一个包含多个步骤的业务操作, 如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败.
  2. 操作 :
    1. 开启事务

    2. 提交事务

    3. 回滚事务

  3. 使用Connection对象来管理事务
    • 开启事务 : void setAutoCommit(boolean autoCommit) : 调用改方法设置参数为false, 即开启事务
      • 在执行sql之前开启事务
    • 提交事务 : void commit()
      • 当所有sql都执行完提交事务
    • 回滚事务 : void rollback()
      • 在catch中回滚事务

数据库连接池

1. 概念 :其实就是一个容器 (集合), 存放数据库连接的容器
	当系统初始化好后, 容器被创建, 容器中会申请一些连接对象,当用户来访问数据库时,从容器获取连接对象,用户访问完之后,会将连接对象归还给容器.
2. 好处 :
	1. 节约资源
	2. 用户访问高效
3. 实现 :
	1. 标准接口 :DataSource javax.sql 包下的
		1. 方法 : 
			* 获取连接 : getConnection()
			* 归还连接 : Connection.close() .如果连接对象Connection是从连接池中获取的, 那么调用Connection.close()方法,则不会再关闭连接了,而是归还连接
		2. 
	2. 一般我们不去实现它, 有数据库厂商来实现
		1. C3P0 : 数据库连接池技术
		2. Druid: 数据库连接池实现技术, 由阿里巴巴提供的
4. C3P0 : 数据库连接池技术
	* 步骤
		1. 导入jar包(两个) c3p0-0.9.5.2.jar 和 mchange-commons-java-0.2.12.jar
			 * 不要忘记导入数据库的驱动jar包 : mysql-connector-java-5.1.37-bin.jar
		2.  定义配置文件 :
			* 名称 : c3p0.properties or c3p0-config.xml
			* 路径 : 直接将文件放在src目录下即可.
		3. 创建核心对象 数据库连接池对象 ComboPooledDatasource 
		4. 获取连接 ;getConnection

JavaWeb 前端_第13张图片

package cn.itcast.datasource.c3p0;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * c3p0的演示
 */
public class C3P0Demo1 {
    public static void main(String[] args) throws SQLException {
        //1.创建数据库连接池对象
        DataSource ds = new ComboPooledDataSource();
        //2.获取连接对象
        Connection conn = ds.getConnection();

        //3.打印
        System.out.println(conn);
    }
}

package cn.itcast.datasource.c3p0;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.Test;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * c3p0的演示
 */
public class C3P0Demo2 {
    public static void main(String[] args) throws SQLException {
        //1.创建数据库连接池对象, 使用默认配置
        DataSource ds = new ComboPooledDataSource();

        //2.获取连接对象
        for (int i = 1; i <= 11; i++) {
            Connection conn = ds.getConnection();
            System.out.println(i + ":" + conn);
            if (i == 5) {
                conn.close();//归还连接到连接池中
            }
        }
        //testNamedConfig();

    }


    public static void testNamedConfig() throws SQLException {
        //1.1 获取DataSource, 使用指定名称的配置
        DataSource ds = new ComboPooledDataSource("otherc3p0");

        //2.获取连接对象
        for (int i = 1; i <= 10; i++) {
            Connection conn = ds.getConnection();
            System.out.println(i + ":" + conn);

        }
    }
}

<c3p0-config>
  
  <default-config>
  	
    <property name="driverClass">com.mysql.jdbc.Driverproperty>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db4property>
    <property name="user">rootproperty>
    <property name="password">123456property>
    
    
    
    <property name="initialPoolSize">5property>
    
    <property name="maxPoolSize">10property>
    
    <property name="checkoutTimeout">3000property>
  default-config>

  <named-config name="otherc3p0"> 
    
    <property name="driverClass">com.mysql.jdbc.Driverproperty>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db4property>
    <property name="user">rootproperty>
    <property name="password">123456property>
    
    
    <property name="initialPoolSize">5property>
    <property name="maxPoolSize">8property>
    <property name="checkoutTimeout">1000property>
  named-config>
c3p0-config>
  1. Druid: 数据库连接池实现技术, 由阿里巴巴提供的
    1. 步骤 :
      1. 导入jar包 druid-1.0.9.jar
        * 不要忘记导入数据库的驱动jar包 : mysql-connector-java-5.1.37-bin.jar
      2. 定义配置文件
        • 是properties形式的
        • 可以叫任意名称, 可以放在任意目录下
      3. 加载配置文件,Properties
      4. 获取数据库连接池对象 : 通过工厂类来获取 DruidDataSourceFactory
      5. 获取连接 : getConnection
    2. 定义工具类
      1. 定义一个工具类 JDBCUtils
      2. 提供静态代码块加载配置文件,初始化连接池对象
      3. 提供方法
        1. 获取连接方法 : 通过数据库连接池获取连接
        2. 释放资源
        3. 获取连接池的方法
package cn.itcast.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * Druid连接池的工具类
 */
public class JDBCUtils {
    //1.定义成员变量 DataSource
    private static DataSource ds;

    static {


        try {
            //1.加载配置文件
            Properties pro = new Properties();
            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //2.获取DataSource
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 获取连接
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();

    }

    /**
     * 释放资源
     * @param stmt
     * @param conn
     */
    public static void close(Statement stmt, Connection conn) {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();//归还连接
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 释放连接
     * @param rs
     * @param stmt
     * @param conn
     */
    public static void close(ResultSet rs, Statement stmt, Connection conn) {
        /*if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }


        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }*/
        close(stmt, conn);

        if (conn != null) {
            try {
                conn.close();//归还连接
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 返回连接池
     * @return
     */
    public static DataSource getDataSource() {

        return ds;
    }

}

package cn.itcast.datasource.druid;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;

/**
 * Druid演示
 */
public class DruidDemo1 {

    public static void main(String[] args) throws Exception {
        //1.导入jar包
        //2.定义配置文件

        //3.加载配置文件
        Properties pro = new Properties();
        InputStream is = DruidDemo1.class.getClassLoader().getResourceAsStream("druid.properties");
        pro.load(is);
        //4.获取连接池对象
        DataSource ds = DruidDataSourceFactory.createDataSource(pro);
        //5.获取连接
        Connection conn = ds.getConnection();
        System.out.println(conn);
    }
}
package cn.itcast.datasource.druid;

import cn.itcast.utils.JDBCUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * 使用新的工具类
 */
public class DruidDemo2 {
    public static void main(String[] args) {
        /**
         * 完成添加操作 :给account表添加一条记录
         */
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            //1.获取连接
            conn = JDBCUtils.getConnection();
            //2.定义sql
            String sql = "insert into account values(null, ? , ?)";
            //3.获取pstmt对象
            pstmt = conn.prepareStatement(sql);
            //4.给?赋值
            pstmt.setString(1, "王五");
            pstmt.setDouble(2, 3000);
            //5. 执行sql
            int count = pstmt.executeUpdate();
            System.out.println(count);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(pstmt, conn);
        }
    }
}

Spring JDBC : JDBC Template

  • Spring 框架对JDBC的简单封装, 提供了一个JDBCTemplate对象简化了JDBC 的开发
  • 步骤 :
    1. 导入jar包

    2. 创建JdbcTemplate 对象, 依赖源DataSource

      • JdbcTemplate template = new JdbcTemplate(ds);
    3. 调用JdbcTemplate 的方法来完成CRUD操作

      • update() :执行DML语句 增删改语句
      • queryForMap() : 查询结果将结果集封装为map集合, 将列名作为key, 将值作为value 将这条记录封装为map集合
        • 注意: 这个方法查询的结果集长度只能是 1
      • queryForList() : 查询结果将结果集封装为list集合
        • 注意: 将每一条记录封装为一个Map集合, 再将Map集合装载到List集合中
      • query() : 查询结果,将结果集封装为JavaBean对象
        • querry的参数 :RowMapper
          • 一般我们使用BeanPropertyRowMapper实现类, 可以完成数据到JavaBean的自动封装
          • new BeanPropertyRowMapper<类型>(类型.class)
      • queryForObject() : 查询结果,将结果集封装为对象(基本数据集)
        * 一般用于聚合函数的查询
  1. 练习 :
    • 需求 :
      1. 修改 1 号数据的 salary 的工资为 10000
      2. 添加一条记录
      3. 删除刚才添加的记录
      4. 查询id 为 1001的所有的记录, 将其封装为Map集合
      5. 查询所有记录, 将其封装为List
      6. 查询所有记录, 将其封装为Emp对象的List集合
      7. 查询总的记录数
package cn.itcast.datasource.jdbcTemplate;

import cn.itcast.datasource.domain.Emp;
import cn.itcast.utils.JDBCUtils;
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class JdbcTemplateDemo2 {
    //Junit单元测试, 可以退让方法独立执行


    //1.获取JDBCTemplate对象
    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

    /**
     * 1. 修改 1 号数据的 salary为 10000
     */
    @Test
    public void test1() {


        //2.定义sql
        String sql = "update emp set salary = 10000 where id = 1001";

        //3.执行sql
        int count = template.update(sql);
        System.out.println(count);
    }

    /**
     * 2. 添加一条数据
     */
    @Test
    public void test2() {
        //2.定义sql
        String sql = "insert into emp(id, ename, dept_id) values(?, ?, ?)";
        //3.执行sql
        int count = template.update(sql, 1015, "郭靖", 10);
        System.out.println(count);


    }

    /**
     * 3.删除刚刚添加的记录
     */
    @Test
    public void test3() {
        //2.定义sql
        String sql = "delete from emp where id = ?";

        //3.执行sql
        int count = template.update(sql, 1015);
        System.out.println(count);

    }

    /**
     * 4. 查询id 为 1001的所有的记录, 将其封装为Map集合
     * 注意:这个方法查询的结果集长度只能是 1
     */
    @Test
    public void test4() {
        String sql = "select * from emp where id = ?";
        Map<String, Object> map = template.queryForMap(sql, 1001);
        System.out.println(map);
        //{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}
    }


    /**
     * 5. 查询所有记录, 将其封装为List
     */
    @Test
    public void test5() {
        String sql = "select * from emp";
        List<Map<String, Object>> list = template.queryForList(sql);
        for (Map<String, Object> stringObjectMap : list) {
            System.out.println(stringObjectMap);
        }
    }


    /**
     * 6. 查询所有记录, 将其封装为Emp对象的List集合
     */
    @Test
    public void test6_1() {
        String sql = "select * from emp";
        List<Emp> list = template.query(sql, new RowMapper<Emp>() {

            @Override
            public Emp mapRow(ResultSet rs, int i) throws SQLException {
                Emp emp = new Emp();
                int id = rs.getInt("id");
                String ename = rs.getString("ename");
                int job_id = rs.getInt("job_id");
                int mgr = rs.getInt("mgr");
                Date joindate = rs.getDate("joindate");
                double salary = rs.getDouble("salary");
                double bonus = rs.getDouble("bonus");
                int dept_id = rs.getInt("dept_id");


                emp.setId(id);
                emp.setEname(ename);
                emp.setJob_id(job_id);
                emp.setMgr(mgr);
                emp.setJoindate(joindate);
                emp.setSalary(salary);
                emp.setBonus(bonus);
                emp.setDept_id(dept_id);

                return emp;
            }
        });
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }

    /**
     * 6. 查询所有记录, 将其封装为Emp对象的List集合
     */
    @Test
    public void test6_2() {
        String sql = "select * from emp";
        List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }

    /**
     * 7.查询总记录数
     */
    @Test
    public void test7() {
        String sql = "select count(id) from emp";
        Long total = template.queryForObject(sql, Long.class);
        System.out.println(total);
    }
}

WEB 前端

web概念概述

  • JavaWeb :

    • 使用Java语言开发基于互联网的项目
  • 软件架构 :

    1. C/S : Client/Server 客户端/服务器端
      • 在用户本地有一个客户端程序, 在远程有一个服务器端程序
      • 如 : QQ, 迅雷…
      • 优点 :
        1. 用户体验好
      • 缺点 :
        1. 开发, 安装, 部署, 维护 麻烦
    2. B/S :Browser/Server 浏览器端/服务器端
      • 只需要一个浏览器, 用户通过不同的网络(URL), 客户访问不同的服务器端程序
      • 优点 :
        1. 开发, 安装, 部署, 维护 简单
      • 缺点 :
        1. 如果应用过大, 用户的体验可能会受到影响
        2. 对硬件要求过高
    • B/S架构详解
      • 资源分类 :
        1. 静态资源 :
        * 使用静态网页开发技术发布的资源
        * 特点 :
        * 所有用户访问, 得到的结果是一样的
        * 如 : 文本, 图片, 音频, 视频, HTML, CSS, JavaScript
        * 如果用户请求的是静态资源, 那么服务器会直接将静态资源发送给浏览器, 浏览器中内置了静态资源的解析引擎, 可以展示静态资源们

          2. 动态资源 :
          	* 使用动态网页技术发布的资源
          	* 特点 :
          		* 所有用户访问, 得到的结果可能不一样
          		* 如: jsp/servlet,php,asp...
          		* 如果用户请求的是动态资源,那么服务器会执行动态资源,转换为静态资源,再发送给浏览器
        
      • 我们要学习动态资源, 必须先学习静态资源!

      • 静态资源 :

        • HTML : 用于搭建基础网页,展示页面内容,用于描述页面的结构
        • CSS : 用于美化页面, 布局页面,用于控制页面中的元素的样式
        • JavaScript : 控制页面的元素,让页面有一些动态的效果,用于响应用户操作
          JavaWeb 前端_第14张图片

HTML

1. 概念 : 最基础的网页开发语言
	* Hyper Text Markup Language 超文本标记语言
		* 超文本 :
			* 超文本是用超链接的方法, 将各种不同空间的文字信息组织在一起的网状文本
		* 标记语言 : 
			* 由标签构成的语言 <标签名称>( <标签>) 如 html, xml
			* 标记语言不是编程语言

JavaWeb 前端_第15张图片

  1. 快速入门 :
    • 语法 :
      1. html文档后缀名 .html 或者 .htm

      2. 标签分为

        1. 围堵标签 : 有开始标签 和 结束标签 , 如 内容
        2. 自闭和标签 : 开始标签和结束标签在一起, 如
      3. 标签可以嵌套:
        需要正确嵌套,不能你中有我,我中有你
        错误 :
        正确 :

      4. 在开始标签中可以定义属性,属性是由键值对构成,值需要用引号(单双都可)引起来

      5. html的标签不区分大小写,但是建议使用小写

<html>
	<head>
		<title>titletitle>
	head>
	
	<body>
		<font color = 'red'>Hello worldfont><br/>
		<font color = 'green'>Hello worldfont>
	body>

html>
  1. 标签学习
    1. 文件标签: 构成html的最基本标签

      • html : html文档的根标签
      • head : 头标签, 用于指定html文档的一些属性,引入外部资源
      • title : 标题标签
      • body: 体标签
      • : html5中定义该文档是html文档的标签
    2. 文本标签: 和文本有关的标签

      • 注释 :

        • to : 标题标签
        • h1 ~ h6 : 字体大小逐渐递减
      • : 段落标签


      • : 换行标签


      • : 展示一条水平线 * 属性 : * color : 颜色 * width : 宽度 * size : 高度 * align : 对齐方式 * center : 居中 * left : 左对齐 * right : 右对齐
      • : 字体加粗

      • : 字体斜体

      • : 字体标签

        • 属性 :
          • color : 颜色
          • size : 大小
          • face : 字体
      • 属性定义 :

        • color :
          1. 英文单词 : red, green, blue
          2. rbg(值1, 值2, 值3) : 值的范围 : 0 ~ 255 如 rgb(0, 0, 255)
          3. #值1值2值3 : 值得范围 : 00~FF 之间 如: #FF00FF
        • width :
          1. 数值 : width = ‘20’, 数值的单位, 默认是 px(像素)
          2. 数值% : 占比相对于父元素的比例
      • : 文本居中

      JavaWeb 前端_第16张图片

      • 案例 : 公司简介
    3. 图片标签: 和图片有关的标签

      • img : 展示图片
        • 属性 :
          • src : 指定图片的位置
            相对路径
      • 以.开头的路径
        • ./ : 代表当前目录 ./image/1.jpg
        • …/ : 代表上一级目录
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图片标签title>
head>
<body>
    
    <img src="./image/jingxuan_2.jpg" align="right" alt="古镇" width="500" height="500"/>
    
    <img src="./image/jiangwai_1.jpg">

    <img src="../image/jiangwai_1.jpg">
body>
html>
4. 列表标签: 
	* 有序列表 :
		* ol
		* li
	* 无序列表 :
		* ul
		* li
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>列表标签title>
head>
<body>
    
    早上起床干的事情
    <ol type="1" start="5">
        <li>睁眼li>
        <li>看手机li>
        <li>穿衣服li>
        <li>洗漱li>
    ol>

    
    早上起床干的事情
    <ul type="disc">
        <li>睁眼li>
        <li>看手机li>
        <li>穿衣服li>
        <li>洗漱li>
    ul>

    
    早上起床干的事情
    <ul type="square">
        <li>睁眼li>
        <li>看手机li>
        <li>穿衣服li>
        <li>洗漱li>
    ul>

    
    早上起床干的事情
    <ul type="circle">
        <li>睁眼li>
        <li>看手机li>
        <li>穿衣服li>
        <li>洗漱li>
    ul>
body>
html>
5. 链接标签:
	* a : 定义一个超链接
		* 属性 :
			* href :  指定访问资源的 URL(统一资源定位符)
			* target : 指定打开资源的一个方式
				* _self : 默认值 , 在当前页面打卡开
				* _blank : 在空白页面打开
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>链接标签title>
head>
<body>
    
    <a href="http://www.itcast.cn">点我a>
    <br>

    <a href="http://www.itcast.cn" target="_self">点我a>
    <br>
    <a href="http://www.itcast.cn" target="_blank">点我a>
    <br>

    <a href = "./5_列表标签.html">列表标签a>
    <br>
    <a href = "mailto:[email protected]">联系我们a>
    <br>
    <a href="http://www.itcast.cn"><img src="image/jiangxuan_1.jpg">a>
body>
html>
6. div 和 span 块标签 : 
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>块标签title>
head>
<body>
    
    <span>黑马程序员span>
    <span>传智播客span>

    <hr>

    <div>黑马程序员div>
    <div>传智播客div>
body>
html>
7. 语义化标签 ; html5中为了提高程序的可读性, 提供了一些标签
		1. 
2.
8. 表格标签: * table : 定义表格 * width 宽度 * border 边框 * cellpadding : 定义内容和单元格的距离 * cellspacing : 定义单元格之间的距离, 如果指定为0 ,则单元格的线会合为一条 * bgcolor : 背景色 * align : 对齐方式 * tr : 定义行 * bgcolor ;背景色 * align : 对齐方式 * td : 定义单元格 * colspan : 合并列 * rowspan : 合并行 * th : 定义表头单元格 * : 表格标题 * : 表示表格的头部分 * : 表示表格的体部分 * : 表示表格的脚部分

JavaWeb 前端_第17张图片

案例 : 旅游网站首页

1. 确定使用table完成布局
2. 如果某一行只有一个单元格, 则使用
3. 如果某一行有多个单元格,则使用
	 
		
			

HTML表单标签: 表单标签

* 表单 :
	* 概念 : 用于采集用户输入的数据的, 用于和服务器进行交互.
	* 使用的标签 :form
	* form : 用于定义表单的, 可以定义一个范围, 范围代表采集用户数据的范围
         * 属性 :
            * action : 指定提交数据的URL
            * method : 指定提交方式
                * 分类: 一共7种, 两种比较常用
                    * get: 
                    	1. 请求参数会在地址栏中显示,会封装到请求行中(HTTP协议讲解)
                    	2. 请求参数长度有限制的
                    	3. 不太安全
                    * post:
                    	1. 请求参数不会再地址栏中显示 ,会封装在请求体中(HTTP协议讲解)
                    	2.请求参数的大小没有限制 
                    	3.较为安全
         	* 表单项中的数据要想被提交 : 必须指定其name属性
* 表单项标签 : 
	* input : 可以通过type属性值,改变元素展示的样式
		* type 属性 :
			* text : 文本输入框, 默认值
				* placeholder:  指定输入框的提示信息,当输入框的内容发生变化,会自动情况提示信息
			* password:密码输入框
			* radio : 单选框 :
					* 注意: 
						1. 要想让多个单选框实现单选的效果, 则多个单选框的name属性值必须一样
						2. 一般会给每一个单选框提供value属性,指定其被选中后提交的值
				 		3. checked 属性,可以指定默认值
			* checkbox : 复选框
					* 注意: 
						1. 要想让多个复选框实现复选的效果, 则多个单选框的name属性值必须一样
						2. 一般会给每一个单选框提供value属性,指定其被选中后提交的值
						3.checked 属性,可以指定默认值
		
			* file :文件选择框 
			* hidden: 隐藏域,用于提交一些信息
			* 按钮:
				* submit 登录按钮
				* button : 普通按钮
				* image:图片提交按钮
				* src属性指定 图片的路径
					取色器: 
生日:
生日:
邮箱:
年龄: * label : 指定输入项的文字描述信息 * 注意: * label 的 for 属性 一般会和 input 的 id 属性值对应,如果对应了,则点击label区域,会让input输入框获取焦点 * select : 下拉列表 * 子元素 : option,指定列表项 * textarea : 文本域 * cols: 指定列数,每一行有多少字符 * rows: 默认多少行

后期学习路径

JavaWeb 前端_第18张图片

你可能感兴趣的:(JaveWeb,前端,java,单元测试)