Spring笔记
1.Spring是轻量级的开源的javaEE框架
2.Spring可以解决企业应用开发的复杂性
3.Spring有两个核心部分:IOC和AOP
(1):IOC控制反转 把创建对象过程交给Spring进行管理
(2):AOP:面向切面编程 不修改源码进行功能增强
4.Spring特点
(1)方便解耦 简化开发
(2)Aop编程支持
(3) 方便程序测试
(4)方便和其他框架整合
(5)方便进行事务操作
(6)降低API开发难度
IOC容器:
(1)IOC底层原理:
(2) IOC接口(BeanFactory)
(3)IOC操作Bean管理(基于xml)
(4)IOC操作Bean管理(注解方式
1.什么是IOC(概念)
1.控制反转 把对象创建和对象之间的调用过程,交给Spring进行管理
2.使用Ioc目的:为了降低耦合度
IOC底层原理
- xml解析 工厂模式 反射
1.优点:
1.Spring是一个开源免费的框架,容器
2.Spring是一个轻量级的框架,非侵入式
Spring是一个轻量级的控制反转和面向切面的容器框架
一.组成
Spring框架是一个分层架构,由7个定义良好的模块组成.Spring模块构建在核心容器之上,核心容器定义了创建,配置和管理bean的方式
组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
- 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
- Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
- Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能 , 集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理任何支持 AOP的对象。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖组件,就可以将声明性事务管理集成到应用程序中。
- Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
- Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
- Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
- Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
扩展
Spring Boot与Spring Cloud
- Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务;
- Spring Cloud是基于Spring Boot实现的;
- Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;
- Spring Boot使用了约束优于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置 , Spring Cloud很大的一部分是基于Spring Boot来实现,Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。
- SpringBoot在SpringClound中起到了承上启下的作用,如果你要学习SpringCloud必须要学习SpringBoot。
2.IOC本质
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
spring 需要导入commons-logging进行日志记录 . 我们利用maven , 他会自动下载对应的依赖项 .
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.10.RELEASE</version>
</dependency>
编写一个Hello实体类
public class Hello {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("Hello,"+ name );
}
}
编写我们的spring文件 , 这里我们命名为beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework/schema/beans"
xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework/schema/beans
http://www.springframework/schema/beans/spring-beans.xsd">
<!--bean就是java对象 , 由Spring创建和管理-->
<bean id="hello" class="com.kuang.pojo.Hello">
<property name="name" value="Spring"/>
</bean>
</beans>
我们可以去进行测试了 .
@Test
public void test(){
//解析beans.xml文件 , 生成管理相应的Bean对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//getBean : 参数即为spring配置文件中bean的id .
Hello hello = (Hello) context.getBean("hello");
hello.show();
}
- Hello 对象是谁创建的 ? hello 对象是由Spring创建的
- Hello 对象的属性是怎么设置的 ? hello 对象的属性是由Spring容器设置的
这个过程就叫控制反转 :
- 控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的
- 反转 : 程序本身不创建对象 , 而变成被动的接收对象 .
依赖注入 : 就是利用set方法来进行注入的.
IOC是一种编程思想,由主动的编程变成被动的接收
可以通过newClassPathXmlApplicationContext去浏览一下底层源码 .
我们在案例一中, 新增一个Spring配置文件beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework/schema/beans"
xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework/schema/beans
http://www.springframework/schema/beans/spring-beans.xsd">
<bean id="MysqlImpl" class="com.kuang.dao.impl.UserDaoMySqlImpl"/>
<bean id="OracleImpl" class="com.kuang.dao.impl.UserDaoOracleImpl"/>
<bean id="ServiceImpl" class="com.kuang.service.impl.UserServiceImpl">
<!--注意: 这里的name并不是属性 , 而是set方法后面的那部分 , 首字母小写-->
<!--引用另外一个bean , 不是用value 而是用 ref-->
<property name="userDao" ref="OracleImpl"/>
</bean>
</beans>
测试!
@Test
public void test2(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserServiceImpl serviceImpl = (UserServiceImpl) context.getBean("ServiceImpl");
serviceImpl.getUser();
}
OK , 到了现在 , 我们彻底不用再程序中去改动了 , 要实现不同的操作 , 只需要在xml配置文件中进行修改 , 所谓的IoC,一句话搞定 : 对象由Spring 来创建 , 管理 , 装配 !
4.IOC创建对象方式
4.1.通过无参构造方法来创建
1.通过无参构造方法来创建
User.java
public class User {
private String name;
public User() {
System.out.println("user无参构造方法");
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+ name );
}
}
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework/schema/beans"
xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework/schema/beans
http://www.springframework/schema/beans/spring-beans.xsd">
<bean id="user" class="com.kuang.pojo.User">
<property name="name" value="kuangshen"/>
</bean>
</beans>
测试类
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//在执行getBean的时候, user已经创建好了 , 通过无参构造
User user = (User) context.getBean("user");
//调用对象的方法 .
user.show();
}
结果可以发现,在调用show方法之前,User对象已经通过无参构造初始化了!
2.通过含参构造方法来创建
UserT . java
public class UserT {
private String name;
public UserT(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name="+ name );
}
}
beans.xml 有三种方式编写
<!-- 第一种根据index参数下标设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
<!-- index指构造方法 , 下标从0开始 -->
<constructor-arg index="0" value="kuangshen2"/>
</bean>
<!-- 第二种根据参数名字设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
<!-- name指参数名 -->
<constructor-arg name="name" value="kuangshen2"/>
</bean>
<!-- 第三种根据参数类型设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
<constructor-arg type="java.lang.String" value="kuangshen2"/>
</bean>
测试
@Test
public void testT(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserT user = (UserT) context.getBean("userT");
user.show();
}
结论:在配置文件加载的时候。其中管理的对象都已经初始化了!
Spring配置
1.别名
alias 设置别名 , 为bean设置别名 , 可以设置多个别名
<!--设置别名:在获取Bean的时候可以使用别名获取-->
<alias name="userT" alias="userNew"/>
Bean的配置
<!--bean就是java对象,由Spring创建和管理-->
<!--
id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
class是bean的全限定名=包名+类名
-->
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
<property name="name" value="Spring"/>
</bean>
import
团队的合作通过import来实现 .
<import resource="{path}/beans.xml"/>
依赖注入
Dependency Injection
概念
-
依赖注入(Dependency Injection,DI)。
-
依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 .
-
注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配 .
集合
泛型
泛型通常与集合一起使用,用来约束集合中元素的类型
泛型< type >必须写引用类型而不是基本类型
泛型方法 public static == < E > == void get(E[] e){},两处位置都出现了泛型,缺一不可
集合被称作Collection,是一个可以存放多个数据的容器,而且集合中提供了丰富的方法来操作集合中的元素
是集合层次的根接口,学习抽象父级的公共方法
Collection集合方法总结
List接口的特点
List集合是有下标的
List集合是有顺序的
List集合可以存放重复的数据
List接口的两个常用实现类
ArrayList的特点:
1)底层的数据结构是数组,内存空间是连续的
2)元素有下标,通常可以根据下标进行操作
3)增删操作比较慢,查询操作比较快【数据量大时】
LinkedList的特点:
1)底层的数据结构是链表,内存空间是不连续的
2)元素有下标,但是通常首尾节点操作比较多
3)增删操作比较快,查询操作比较慢【数据量大时】
注意:LinkedList查询慢也不是都慢,首尾操作还是比较快的
Map接口
Map接口的特点
map集合的结构是:键值对、KEY与VALUE、Map.Entry<K,V>的映射关系
map中key值不允许重复,如果重复,对应的value会被覆盖
map中的映射关系是无序的
map没有自己的迭代器,所以迭代时通常需要转成set集合来迭代
Set接口
Set接口的特点
set集合没有重复的元素
set集合的元素是无序的
set集合可以存null值,并且null最多有一个
我们自定义对象如果想去重,需要在自定义类中添加重写的equals()与hashCode()
集合学习的方法
学习父级的公共方法,学习子类的创建方式,学习各种集合的特点
关于List大多都是与下标有关的操作
关于Set通常都是去重的操作
关于map通常都是映射关系,也就是键值对
API要常练习,方法互相之间没有任何关系,用哪个,查哪个
进程与线程
程序:数据与指令的集合,而且程序是静态的
进程:运行中的程序,给程序加入了时间的概念,不同时间进程有不同的状态,进程是动态的,代表OS中正在运行的程序
进程有独立性,动态性,并发性
并行:相对来说资源比较充足,多个CPU同时并发处理多个不同的进程
串行:相对来说资源不太充足,多个资源同时抢占公共资源,比如CPU
线程:线程是OS能够进行运算调度的最小单位
一个进程可以拥有多个线程,当然,也可以只拥有一个线程,只有一个线程的进程称作单线程程序
注意:每个线程也有自己独立的内存空间,当然也有一部分共享区域用来保存共享的数据
线程的几种状态以及线程状态之间的切换
1)新建状态:创建线程对象,申请PCB,对应的是new线程对象
2)就绪状态/可运行状态:万事俱备,只欠CPU,刚刚创建好的线程对象所有资源已经准备好,并且加入到了就绪队列之中
唯有等待操作系统的调度,只要分配了CPU,也就是时间片,当前线程可立即执行,对应的是start()
注意:调用start()并不会立即执行线程对象,这个是由OS的调度规则决定的。我们控制不了
3)执行/运行状态:就绪队列中的线程对象被OS选中,分配了时间片,正在执行
注意:只有就绪状态才能变成运行状态
4)阻塞状态:线程在执行过程中遇到了问题,比如锁阻塞、休眠阻塞、等待阻塞…
注意:我们的阻塞状态,等问题解决了以后/获取了临界资源【要抢占的公共资源】后
是加入到就绪队列中的,转为就绪状态,而不是转为运行状态直接执行
5)终止状态:线程成功执行完毕,释放资源,归还PCB
6)线程的挂起:正在运行中的线程,由于CPU分配的时间片已经用完,所以需要冻结当前线程运行的状态与各项信息
把它插入到就绪队列中,直到下次这个线程被调度执行时,重新恢复现场,继续执行
多线程编程实现方案一:extends Thread继承方式
1)自定义一个多线程类用来继承Thread类
2)重写run()里的业务【这个业务是自定义的】
3)创建线程对象【子类对象】
4)通过刚刚创建好的自定义线程类对象调用start()
注意1:不能调用run(),因为这样调用只会把run()看作一个普通的方法,并不会以多线程的方式启动程序
而且调用start()时,底层JVM会自动调用run(),执行我们自定义的业务
注意2:我们除了可以调用默认的父类无参构造以外,还可以调用Thread(String name),给自定义的线程对象起名字,相当于super(name);
多线程编程实现方案二:implements Runnable 实现方式
1)自定义一个类实现接口Runnable
2) 实现接口中唯一一个抽象方法run()
3) 创建接口实现类的对象,这个对象是作为我们的目标业务对象【因为这个自定义类中包含了我们的业务】
4)创建Thread类线程对象,调用的构造函数是Thread(Runnable target)
5)通过创建好的Thread类线程对象调用start(),以多线程的方式启动同一个业务target
注意1:由于Runnable是一个接口,无法创建对象,所以我们传入的目标业务类,也就是接口实现类的对象
注意2:只有调用start()才能把线程对象加入到就绪队列中,以多线程的方式启动,但是:
接口实现类与接口都没有这个start(),所以我们需要创建Thread类的对象来调用start(),并把接口实现类对象交给Thread(target);
大家可以理解成“抱大腿”,创建的是Thread类的线程对象,我们只需要把业务告诉Thread类的对象就好啦
使用方式二的优势:
1)耦合性不强,没有继承,后续仍然可以继承别的类
2)采用的是实现接口的方式,后续仍然可以实现别的接口
3)可以给所有的线程对象统一业务,业务是保持一致的
4)面向接口编程,有利于我们写出更加优雅的代码
多线程编程实现方案三:Executors 创建线程池的方式
1)创建线程池的工具类:Executors.newFixedThreadPool(int n);可以创建包含最多n个线程的线程池对象
2)创建好的线程池对象:ExecutorService
使用pool.excute()来讲线程池中的线程以多线程的方式启动,每次调用都会将一个线程对象加入到就绪队列之中
这个线程池对象负责: 新建/启动/关闭线程,而我们主要负责的是自定义的业务
注意:线程池是不关闭的,实现的效果就是线程池中线程对象的随取随用,这样就避免了频繁的创建与销毁线程,不会造成资源浪费
3)合理利用线程池可以拥有的优势:
1. 降低系统的资源消耗:减少系统创建与销毁线程对象的次数,每个线程都可以重复利用,执行多次任务
2. 提高响应速度:当任务到达时,任务可以不用等待线程创建就能立即执行
3. 提高线程的可管理性:可以根据系统的承受能力,调整线程池中线程的数目
防止因为创建多个线程消耗过多的内存导致服务器的崩溃
【每个线程大约需要1MB的内存,线程开的越多,消耗的内存也就越大,最后死机】
多线程数据安全隐患的解决方案
1)出现数据安全问题的原因:多线程程序 + 多个线程拥有共享数据 + 多条语句操作共享数据
2)解决:加锁synchronized同步关键字
1. 同步方法【不太常用】,格式:在方法的定义上加synchronized
同步代码块,格式:
synchronized(唯一的锁对象){
可能会出现数据不安全问题的所有代码
}
注意1:锁对象必须唯一!!!
比如:如果是实现接口的方式,只需要创建一个接口实现类对象。而这个对象当做的是目标业务对象,类中定义的锁对象自然也只有一个
比如:如果是继承Thread类的方式,我们需要创建多个子类对象作为线程对象
那这个时候不同的线程对象间应该共享同一把锁,所以需要把锁设置为静态,被全局所有对象共享
而且建议,此种方式使用的锁对象是本类的字节码对象:类名.class
注意2:加锁时,同步代码块的范围需要考虑, 不能太大,太大效率太低;也不能太小,太小锁不住
注意3:加锁时,锁对象的类型不做限制,只要保证锁对象唯一即可
同步与异步
异步:是多个线程抢占资源的效果,不排队,所以效率高,但是数据不安全
同步:每次只有一个线程独占资源,排队,所以效率低,但是安全,为了安全必要应该牺牲一部分资源
注解
JDK自带的注解(5个)
要求大家掌握的是@Override注解,这个注解可以加在方法上,用来表示这是一个重写的方法
元注解5个:
元注解是用来定义其他注解的注解,也就是说,注解的语法与JAVA不同,是靠注解来定义的
定义注解的格式:@interface 注解名
可以根据元注解对注解进行设置:
表示被描述的注解可以使用的位置:值可以多选 @Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
表示被描述的注解的声明周期:注意值只能3选1 @Retention(RentionPolicy.RUNTIME/SOURCE/CLASS)
自定义注解
我们也可以根据自己的需求来定义个性化的注解:使用@interface 注解名来定义的,主要使用的就是上面的两个元注解
除此之外,我们还可以给注解加功能,比如注解的属性:
格式:属性类型 属性名(); 比如:int age();
注意:定义了注解的普通属性以后,使用注解时必须给属性赋值,格式:@Rice(age=10)
如果给属性设置了默认值,那么使用注解时就不需要给属性赋值了,格式:int age() default 0;
我们还可以给注解添加特殊的属性value,注意这个属性名字必须是value,类型不作限制
注意:特殊属性如果不设置默认值,使用注解时也需要赋值,不过赋值可以简写,比如@Rice(“apple”)
特殊属性赋予默认值后,就可以直接使用注解了,赋予默认值的格式:String value() default “apple”;
注意:如果有多个属性,并且都没有赋予默认值,那么使用注解时的格式:@Rice(value=“apple”,age=10)
设计模式
概念:是一些前人总结出来的值得学习的编程“套路”,设计模式一共有23种
单例设计模式:确保代码中本类的实例只有一个
实现思路:
方案一:饿汉式
1)把本类的构造方法私有化–为了不让外界调用构造函数来创建对象
2)通过本类的构造方法创建对象,并把这个对象也私有化,为了防止外界调用
3)提供公共的全局访问点向外界返回本类的唯一的一个对象
注意:公共方法需要设置成静态–需要跳过对象,通过类名直接调用这个返回本类对象的公共方法
对象也需要设置成静态的–这个对象需要在静态方法中被返回,而静态只能调用静态
方案二:懒汉式
==延迟加载的思想:==我们有的时候有些资源并不是需要第一时间就创建出来,所以需要延迟到需要时再创建,这样既可以提升性能,又可以节省资源
1)把本类的构造方法私有化–为了不让外界调用构造函数来创建对象
2)创建了一个本类类型的引用类型变量【这个变量后续用来保存创建出来的对象的地址值】
3)提供公共的全局访问点向外界返回本类的唯一的一个对象
注意:这个公共的方法里,需要做判断
如果引用类型的变量值为null,说明:之前没有创建过本类对象–创建后再赋值给引用类型变量,并把它返回
如果引用类型的变量值不为null,说明:
之前有创建过本类对象,这个引用类型变量保存就是地址值,本次不再新建对象,直接返回
反射
反射的概念
反射是Java这门语言中比较有特点的一个特征,反射非常强大,我们可以通过反射获取目标类当中的资源,甚至是私有资源
不仅仅如此,我们甚至还可以使用资源,并且创建对象,所以反射是一个经常被使用到的技术
开发过程中,我们有的时候并不能拿到源代码,但是又需要使用资源,那这个时候反射的出现就很有必要了
反射需要用到的API:
获取字节码对象:
Class.forName(“类的全路径”); 注意:传入的是类的全路径名,包含包名.类名,而且会抛出异常
类名.class 注意:这个写法需要自己手动接一下获取到的字节码对象,不能用快捷方式的
对象.getClass(); 注意:经常与匿名对象一起使用
获取包名 类名
clazz.getPackage().getName()//包名
clazz.getSimpleName()//类名
clazz.getName()//完整类名
获取成员变量定义信息:
getFields()//获取所有公开的成员变量,包括继承变量
getDeclaredFields()//获取本类定义的成员变量,包括私有,但不包括继承的变量
getField(变量名)
getDeclaredField(变量名)
获取构造方法定义信息:
getConstructor(参数类型列表)//获取公开的构造方法
getConstructors()//获取所有的公开的构造方法
getDeclaredConstructors()//获取所有的构造方法,包括私有
getDeclaredConstructor(int.class,String.class)
获取方法定义信息:
getMethods()//获取所有可见的方法,包括继承的方法
getMethod(方法名,参数类型列表)
getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法
getDeclaredMethod(方法名,int.class,String.class)
反射新建实例
clazz.newInstance();//执行无参构造创建对象
clazz.getConstructor(int.class,String.class)//要先获取构造方法
c.newInstance(666,”海绵宝宝”);//通过获取到的构造函数对象,创建目标类对象
反射调用成员变量:
clazz.getDeclaredField(变量名);//获取变量
field.setAccessible(true);//使私有成员允许访问
field.set(实例,值);//为指定实例的变量赋值,静态变量,第一参数给null
field.get(实例);//访问指定实例变量的值,静态变量,第一参数给null
反射调用成员方法:
Method m = Clazz.getDeclaredMethod(方法名,参数类型列表);
m.setAccessible(true);//使私有方法允许被调用
m.invoke(实例,参数数据);//让指定实例来执行该方法
第二阶段
- 数据库
- 概述:
- 就是用来存储数据的和管理数据,本质上就是需要安装MySQL软件.
- 分类:关系型数据库MySQL和非关系型数据库Redis,主要观察数据之间的关系
- 使用:
- 安装服务器端:存数据管理数据
- 核心步骤 设置字符集/编码成 utf-8,端口号3306,设置服务名称MySQL,设置密码root
- 安装客户端 连接服务器 操作服务器里的数据
- Win+r 输入cmd
- 发起MySQL命令 -u是指定用户名(root) -p是指定密码(自定义的) mysql -uroot -proot 图形化的工具sqlyog
- 数据库的结构
- 数据库->表(行和列)->数据
- SQL语言
- 结构化查询语言,用来操作数据库的语言,是一种标准.
- 增删改查里将来发生最多的业务就是 “查”
- 分类
- DML是数据操作语言
- DDL是数据定义语言
- DCL是数据控制语言
- DQL数据查询语言
- 数据库的常见操作
- 增删改查 CRUD
- 创建库
- 也可以简写成 create database cgb charset utf8;
创建库:
Create:创建 database:数据库 MIAN:数据库名称
查询库:
Show: 展示 databases:所有的数据库
删除库:
Drop :删除 database:数据库 mian 库名
三.表的常见操作
使用数据库:
use 使用 mian:数据库名
创建表:
语法: 字段名 类型(长度),字段,字段
Create table mian_zc(cai varchar(20),TRJ varchar(20),TWT varchar(20));
查看表:
Show tables
修改表:
Alter table mian_zc add column moeny numeric(7,2);
描述表结构:
删除表:
Drop table main_zc;
- 数据的常见操作
- 增删改查:
- 查询数据/记录
- 增删改查:
Select * from main_zc
-
- 插入数据/记录
语法:insert into 表名 values(1,2,,3,4,5,6)
注意:
- 需要设置几个值?要看表里有几个字段
- 值的顺序要和字段的顺序保持一致
- 如果字段是字符串类型,设置值时必须要有””的标记
修改数据/记录:
Update mian_zc set C=1;
删除数据/记录:
Delete from mian_zc_m
- 数据库的使用细节
- 命名规范
- 以字母开头,不要以数字开头
- 不能使用保留字:select/from/update/delete/insert into
- MySQL数据库不区分大小写,多个单词用下划线分开
- 数据类型
- 整型:int
- 小数:double(不精确)/numeric(a,b)/decimal(a,b)-a是数字的位数b是小数位数
- 时间:data(年月日)/time(时分秒)/datetime(年月日时分秒)/timestamp(时间戳,毫秒数)
- 字符串:char/varchar
- 命名规范
区别:
Char是固定长度,浪费空间char(10)
Varchar是可变长度,节省空间varchar(10)
特殊场景:数据长度如果就是固定的,有限选char,因为查得快
-
- 图片:如果想存入数据库,只会存文件的磁盘路径D:/abc/1.jpg,不是存文件本身
- 字段约束
使用的时间:通常在设计表创建表时就已经确定了
-
- 非空约束
- 哪个字段添加了非空约束从此,字段值不能为空 使用 not null
- 非空约束
Create table b (password varchar(100) not null);
-
- 主键约束
- 每个表都应该设计主键,主键是每条记录/数据的唯一标识.
- 主键约束
-
-
- 主键自增策略:使用auto_increment让主键的值交给数据库自动维护
- 现象是:字段的值必须唯一且不能为空,使用primary key
- 唯一约束 那个字段添加了唯一约束,从此,字段不能相同,使用unique
-
- 基本函数
- 工具的使用
Sqlyog
- 基础函数的使用
- Lower-全转小写
- Upper-全转大写
- Length-求长度
- Substr-截取子串
- Concat-拼接字符串
- Replace-替换
- 条件查询
- 基础语法
- MySQL数据备份
- 用工具直接备份就行
- 如果是SQL,直接ctrl s 保存就行
- 也可以把表或者数据库一整行导出--右键--导出-以SQL转储文件
- 练习
- Null的数据用is/not关键字来过滤
- 用工具直接备份就行
SELECT * FROM dept WHERE loc IS NOT NULL:过滤掉为null的数据
-
- Between and区间
SELECT * FROM dept WHERE deptno
BETWEEN 1 AND 2:过滤掉这个区间以外的数据
-
- Limit 分页
SELECT * FROM dept LIMIT 0,3:第0条开始的前三条数据
Order by排序
SELECT * FROM dept ORDER BY deptno DESC:将deptno这个字段里的数据进行降序排列 不写DESC 就时升序排列
-
- 统计案例
统计每个员工的年薪=月薪*16+如果是null就看作零奖金*16
SELECT sal,comm,sal*16+IFNULL(comm,0)*16 FROM
emp
统计19年之前入职的员工信息
SELECT * FROM emp WHERE YEAR(hiredate)<2019
- 聚合函数
- 概述:
- 基础函数:
- Upper/lower/length/concat/substr/replace/ifnull/now()/data()/year()
- 基础函数:
- 概述:
-
- 聚合函数
- 把一字段的值聚合起来,进行获取最大值,最小值,平均值,求和,求个数
- Max()/min()/sum()/avg()/count()
- 聚合函数
- 分组
- 把表里的所有数据 按照合理的维度分成不同的组
- Group by
- 聚合函数和非聚合函数有混合的情况下,分组是按照非聚合函数来进行分组
- Having
- 把分组后的数据还想继续过滤,使用group by 的固定搭配having
- 但是不高效,一般为了高效都是用where代替having 因为执行时机要早一些
- Whre里不能有别名,也不能出现聚合函数
- Group by
- 把表里的所有数据 按照合理的维度分成不同的组
- 事务
- 概述
- 数据库事务用来保证 多少个SQL 要么全成功,要么全失败,英文叫 Transaction.
- MySQL数据库会自动管理事务,Oracle数据库需要程序员管理事务.
- MySQL也允许程序员手动管理事务
- 事务的四大特征:ACID
- 原子性:把多条SQL看做一个原子密不可分,要么全成功,要么全失败
- 一致性:保证数据守恒,将来广泛的应用到分布式系统里
- 隔离性:MySQL数据库可以支持高并发,可能会有数据安全隐患,也有复杂的隔离级别
- 持久性:对数据库的操作增删改,有持久影响
- 隔离级别:
- Read uncommitted读未提交:性能好,但是安全性差
- Read commited读已提交:是Oracle数据库的默认隔离级别,性能再差一点,但是安全性特别好
- Serializable串行化:性能非常差,但是安全性比较好
- 概述
- 字段约束
- 默认约束
- 哪个字段添加了默认约束,从此字段值就有默认值了
- 检查约束
- 哪个字段添加了检查约束,从此,字段值必须符合检查的条件才可以
- 外键约束
- 使用明确的一段代码表示,两个表之间的关系
- 约束子表的主键值,必须 取自 主表的主键值
- 约束主表的记录不能随便删除,要保证没有被子表使用才可以删除
- 默认约束
- 多表联查
- 准备表和数据
- 方式一:笛卡尔积:用,表示
- 方式二:连接查询:用join表示
- 方式三:子查询:又叫嵌套查询,把上次查询的结果当这次的条件来用
- 数据库的扩展
- 索引
- 好处是:提高查询效率
- 坏处是:本身是单独的空间来存储
- 分类:
- 单值索引:一个索只包含一列
- 唯一索引:一个索只包含一列,值不能重复
- 复合索引:一个索引包含多个列
- 索引
单值索引:
Create index 索引名 on 表名(字段名)
查看索引
SHOW INDEX FROM emp
创建索引
CREATE INDEX nameindex ON emp(sal)
检查是否使用了单值索引
EXPLAIN SELECT * FROM emp WHERE job='员工'
唯一索引
Create unique index 索引名 on 表名(字段名)
一个索引包含一个列,列的值不能重复
创建唯一索引
CREATE UNIQUE INDEX dnameindex ON dept(dname)
查看索引
SHOW INDEX FROM dept
使用索引
EXPLAIN SELECT * FROM dept WHERE dname='research
复合索引
Create index 索引名 on 表名(字段1,字段2,字段3)
一个是索引包含多个字段,用时要遵循最左原则,否则复合索引失效,失效的情况:按照2 3 23没有包含最左边的
创建复合索引
CREATE INDEX fuheindex ON emp(ename,job,deptno)
删除索引
Alter table表名drop index 索引
Show index from 表名
使用explain关键字检查,SQL中是否使用了索引(检查SQL的执行性能)
总结:
缺点:索引本身也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也要占用空间,索引表中的内容,在业务表中都有,数据重复的,空间是”浪费的”
虽然索引大大提高了查询的速度,但对数据的增删改的操作需要更新索引表信息,如果数据量非常巨大,更新效率就很慢,因为更新表时,MySQL不仅要保存数据,也要保存一下索引文件
随着业务的不断变化,之前建立的索引可能不能满足查询需求,需要消耗我们的时间去更新索引
-
- 视图
- 概念
- 是一个特殊的表,存了上次查询的结果
- 视图的创建:Create view emppp AS 加sql语句
- 视图的使用:select * from 视图的名字 emppp
- 好处:提高了SQL的复用性+屏蔽了业务表的复杂性+数据共享
- 坏处:是一张单独的表存了业务表的数据造成了数据重复+无法优化.
- 概念
- SQL优化
- 用字段名称代替 “*”
- Where里 尽量不用”and”不用”or”,尽量不用”=”不用”!=” “<>”,条件越精确越好.
- 表设计:
- 表里的索引不要超过5个,给where后或者order by经常用的字段加索引,复合索引要遵循最左特性不然就失效了,索引表即使删除掉多余的索引.用varchar代替char,用数字代替字符串,用默认值代替null.
- 使用explain分析的SQL执行计划
- 批量处理:
- 批量查,批量删,最好使用分页
- 查询尽量避免返回大量的数据
- 是否使用了索引及其扫描类型
- ALL全表扫描,没有优化,最慢的方式
- Index索引全扫描
- Range索引范围扫描
- Ref使用唯一索引扫描或唯一前缀扫描,返回单记录,常出现在关联查询中
- eq_ref类似ref 区别在与使用的是唯一索引,使用主键关联查询
- Const/system单条记录,系统会把匹配行中的其他列作为常数处理,如主键或唯一索引查询
- NullMySQL不访问任何表或索引,直接返回结果
- Key:
- 真正的使用索引方式
- Alter table student add index_name(name)
- 优化like语句
- 模糊查询,程序员最喜欢的就是使用like,但是like很可能让你的索引失效:%必须是在后面,不能在前面或者前后.
- 字符串怪象
- 视图
SELECT * FROM student WHERE NAME=123
理由:为什么这条语句未加单引号就不走索引了呢?
这是因为不加单引号是,是字符串跟数字的比较,他们类型不匹配,MySQL会做隐式的类型的转换,把他们转换为数值类型爱做比较
-
- 索引不宜太多,一般5个以内
- 索引并不是越对越好,虽其提高了查询的效率,但却会降低插入和更新的效率
- 索引可以理解为一个就是一表的,其可以存储数据,其数据就要占空间
- 再者,索引表的特点,其数据是排序的,那排序要不要花时间呢? 肯定要
- Insert或update是有可能会重建索引,如果数据量巨大,重建将进行记录的重新排序,所以建索引需要慎重考虑,视具体情况来定
- 一个表的索引数最好不要超过5个,若太多需要考虑一些索引是否存在的必须要
- 索引不适合建在大量重复数据的字段上
- 如性别字段.因为SQL优化器是根据表中数据量来进行查询优化的,如果索引列有大量重复的数据,MySQL查询优化器推算发现不走索引的成本更低,很可能就放弃索引了.
- Where限定查询的数据
- 数据中假定就是一个男的记录
- 索引不宜太多,一般5个以内
反例:SELECT id,NAME FROM student WHERE sex='男'
正例:SELECT id,NAME FROM student WHERE id=1 AND sex='男'
理由;需要什么数据,就去查什么数据,避免返回不必要的数据,节省开销
-
- 避免在where中对字段进行表达式操作
- 反例:
- SELECT * FROM student WHERE id+1-1=+1
- 正例:
- SELECT * FROM student WHERE id=+1-1+1
- SELECT * FROM student WHERE id=1
- 理由:SQL解析时,如果字段相关的是表达式就进行全面扫描
- 避免在where子句中使用!=或<>操作符
- 应尽量避免在where子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描.记住实现优先是在没办法,就只能使用,并不是不能使用,如果不能使用,SQL也就无需使用了.
- 反例:
-
SELECT * FROM student WHERE salary!=3000 SELECT * FROM student WHERE salary<>3000
理由:
-
使用!=和<>很可能会让索引失效
-
去重distinct过滤字段要少
-
-
索引生效
-
-
SELECT DISTINCT id,NAME FROM student SELECT DISTINCT NAME FROM student
- 避免在where中对字段进行表达式操作
4. 索引失败
SELECT DISTINCT * FROM student
理由:
带distinct的语句占用cpu时间高于不带distinct的语句,因为当查询很多字段时,如果使用distinct,数据库引擎就会对数据进行比较,过滤掉重复的数据,然而和这个比较过滤的过程会占用胸系统资源如CPU时间
5.where中使用默认值替代null
1.修改表,增加age字段,类型int 非空,默认值0
ALTER TABLE student ADD age INT NOT NULL DEFAULT 0;
6.批量插入性能提升
1.大量数据提交,上千,上完,批量性能非常快,mysql独有
多条数据提交:
INSERT INTO student (id,NAME) VALUES(4,'齐雷');
INSERT INTO student (id,NAME) VALUES(5,'刘昱江');
批量提交:
INSERT INTO student (id,NAME) VALUES(4,'齐雷'),(5,'刘昱江');
理由:
1.默认新增SQL有事务控制,导致每条事务开启和事务提交;而批量提交是一次事务开启和提交.自然速度飞升.
2.数据量体现不出来
7.批量删除优化
避免同时修改或删除过多数据,因为会造成cpu利用率过高,会造成锁表操作,从而影响别人对数据的访问
反例:
一次性删除10万或者100万+
delete from student where id <100000;
采用单一循环操作,效率低,时间漫长
for(User user:list){
delete from student;
}
正例:
分批进行删除,如每次500
for(){
delete student where id<500;
}
delete student where id>=500 and id<1000;
理由:
一次性删除太多数据,可能造成锁表,会有lock wait timeout exceed的错误,所以建议分批操作
8.伪删除设计
商品状态 (state):1-上架/2-下架/3=删除
理由:
1.这里的删除只是一个标识,并没有从数据库中真正删除,可以作为历史记录备查
2.同事,一个大型系统中,表关系是非常复杂的,如电商系统中,商品作废了,但直接删除商品,其他商品详情,物流信息中可能都有其引用
3.通过where state=1或者where state=2过滤掉数据,这样伪删除的数据用户就看不到了,从而不影响用户的使用
4.操作速度快,特别数据量很大情况下
9.提高group by语句的效率
1.可以在执行到该语句前,把不需要的记录过滤掉
反例:先分组,在过滤
select job,avg(salary) from employee
group by job
having job ='president' or job = 'managent';
正例:先过滤,后分组
select job,avg(salary) from employee
where job ='president' or job = 'managent'
group by job;
10.复合索引最左特性
创建复合索引,也就是多个字段
ALTER TABLE student ADD INDEX idx_name_salary (NAME,salary)
满足复合索引的左侧顺序,哪怕只是部分,符合索引失效
EXPLAIN SELECT * FROM student WHERE NAME='陈子枢'
没有出现左边的字段,则不满足最左特性,索引失效
EXPLAIN
SELECT * FROM student WHERE salary=3000
复合索引全使用,按最左侧顺序出现name,salary,索引生效
EXPLAIN
SELECT * FROM student WHERE NAME='陈子枢' AND salary=3000
虽然违背了最左特性,但MySQL时会进行优化,底层进行点到优化
EXPLAIN
SELECT * FROM student WHERE salary=3000 AND NAME='陈子枢'
理由:
1.复合索引也称为联合索引
2.当我们创建一个联合索引的时候,如(k1,k2,k3),相当于创建了(k1),(k1,k2)和(k1,k2,k3)三个索引,这就是最左匹配原则
3.联合索引不满足最左原则,索引一般会失效,但是这个还跟Mysql优化器有关的
11.排序字段创建索引
什么样的字段才需要创建索引呢?
1.原则就是where和order by 中常出现的字段就创建索引
使用 “*” 包含了为索引的字段,导致索引失效
EXPLAIN
SELECT * FROM student ORDER BY NAME;
12.三范式
1.数据库的专业术语,用来设计表要遵循的原则,范式NF
2.分为六大范式,通常只遵循前三大范式就可以了
3.第一范式1NF:
表里的字段,不可分割,是指字段的值就是最小单位,简而言之,第一范式就是无重复的列
第二范式2NF:
基于第一范式的基础上产生的,指表里都应该设计主键/主关键字/主属性,每行都应该围绕着主键,描述数据,总之,第二范式就是非主属性完全依赖于主关键字.
第三范式3NF:
基于第二范式的基础上产生的,是指表里的字段之间尽量不要产生依赖,总之,第三范式就是属性不依赖于其他非主属性.
一.JDBC
1.概述
1.sun公司提供的一套java操作数据库的标准
2.专门用来完成java和数据库交互的技术,全程:java database connectivity
2.使用步骤
1.提供了丰富的工具包jar包,项目中导入jar包
复制粘贴到spring5然后右键-add as libarary… ok
2.连接数据库:端口号3306 库名cgb2109 用户名 root 密码root
3.写SQL语句
4.处理数据库返回给java的结果
二.HTM
1.概念
超文本标记语言
网页中的元素类型可以超过文本内容
标记语言:HTML中提供了大量标记/标签,开始标签和结束标签
三.HTML的常见标签
1.概念
1.输入框:单元多选
2.图片
3.按钮
4.视频
5.超链接
2.标题,列表,图片
CSS选择器
–1,分组选择器,属性选择器
分组选择器:选择器1,选择器2,选择器3{声明样式}
属性选择器:根据属性选中元素
三,盒子模型
–1,概述
CSS把HTML里的元素看做是一个一个的盒子.
内边距padding: 一个盒子里的现象,内容和边框的距离
外边距margin: 盒子和盒子间的距离
边框border:是指盒子可以设置边框
五,Git
–1,概述
完成版本控制,可以实时上传代码到码云服务器上.
日常操作:
1,上传: add -> commit -> push
add : 把即将上传的资源,从工作空间添加到本地索引
commit: 把已经添加了索引的文件,从本地索引提交到本地仓库
push: 把本地仓库的 推送到 Gitee上
2,下载: clone/pull
clone: 把Gitee上的代码下载到你的电脑里
–2,准备工作
安装Git(下一步下一步就行了)
去码云注册账号(记住账号密码,并激活邮箱)
–3,Git日常操作
1,远程仓库:
需要登录Gitee网站,在网站上创建仓库(右上角的加号–新建仓库–输入仓库名字选成开源–创建)
二,Javascript
–1,概述
简称是js,是一种脚本语言,只能在浏览器中执行
特点:
直译式,不需要编译的过程.
js是一种弱类型的语言,用来提高网页与用户的交互性
事件驱动: 指JS代码以什么方式来触发执行
基于对象: JS也有类似于OOP的思想,可以自己new对象
脚本语言: 只能在特定场景执行的语言,JS只能在浏览器来执行
JS的出现的位置:
行内JS,内部JS,外部JS
三,JS语法
–1,数据类型和变量
变量类型 变量名=变量值
练习:交换变量的值(首尾相连)
var c = 10;
var d = 20;
var e = c;
c = d;
d = e;
四,JS语句
–1,分支结构
2.循环结构
一,JS的数组
–1,概述
1,特点: 长度可变,数据类型可以存的非常丰富.
2,创建:
var a = new Array(1,2,3,4.1);
var a = [1,2,3,4.1];
3,遍历:
//i是下标,a[i]是数据
for(var i=0;i<a.length;i++){}
for(var i in a){}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试 js数组</title>
<script>
//JS数组的特点:存的数据类型丰富,也有下标0,也有length,随时改长度
//1.创建数组的方式一:
var a = new Array();
console.log(a);
console.log(a.length);//获取数组的长度
var b = new Array(1,1.1,true,'hello');
console.log(b);
console.log(b.length);
console.log(b[2]);
console.log(b[3]);
console.log(b[4]);//undefined!!!
//2.创建数组的方式二:
var c = [];
console.log(c.length);//0
c = [1,1.1,true,'abc'];
console.log(c.length);//4
c[99]=true;
console.log(c);
console.log(c.length);//100
//3.遍历数组
for(var i=0;i<c.length;i++){
//i是下标,c[i]是通过下标获取c数组里的数据
console.log(c[i]);
}
//java的foreach:for (Object o : y) {o是数据}
for (var o in c) {//forin,o是下标
console.log(c[o]);
}
</script>
</head>
<body>
</body>
</html>
二,JS函数
–1,概述
和java里的方法一样,也是有()的标记,也可以有参数列表,也可以有返回值
//定义函数
function a(参数名){ return b; }
var a = function(参数名){return b; }
//调用a函数,并传入参数,并用c记录返回值
var c = a(传参);
三,JS对象
–1,概述
分成两类: 内置对象 , 自定义对象!!!
内置对象: String Array Math…JSON Document
四,DOM
–1,概述
是用来 利用JS代码,操作HTML的每个元素的
利用document对象,
一.JSON
1.概念
1.是一种轻量级的数据交换格式,本质就是在一个字符串,用来规定浏览器和服务器之间 数据交换的一个格式.
二.vue
1.概述
1.是一个轻量级的前端框架,封装了HTML CSS JS的代码
2.特点:
1.是一个轻量级的 渐进式的框架,按需配置
2.实现了数据驱动/双向绑定和组件化的思想(高内聚)
3.vue框架可以避免了DOM的API
4.遵循了MVVM设计模式,实现前端代码的松耦合
M是Model,是指数据
V是view,是指视图
VM是ViewModel,是指在指定视图里渲染指定数据
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试 vue框架</title>
<!-- 1.引入vue.js来用vue框架的核心功能
src用来指定js文件的位置
-->
<script src="vue.js"></script>
</head>
<body>
<!-- 2.准备解析vue的数据
{{message}}是插值表达式,用来获取message的值
-->
<div id="app"> {{message}} </div>
<!-- 3.给第二步准备数据 -->
<script>
var a={
message:"hello vue~"
}
//1,创建Vue对象
new Vue({
//el挂载点,意思是,把数据挂载到指定位置
el:"#app",//利用CSS的id选择,选中了网页中的元素
//data是vue为挂载点准备好的数据
data:a
})
</script>
</body>
</html>
四.vue的指令
1.概述
1.就是Vue框架提供的一些有特殊意义的代码,都有-v的前缀
2.常见的指令:v-if v-for v-on...
3.使用方式:在开始标签处,添加新的属性,有v-的前缀的标识
1..v-cloak指令:解决插值表达式的闪现问题
2.v-model指令:双向绑定,是指V和M的数据可以实时同步 address值是指你的数据要和哪个属性进行绑定. 可以获取也可设置属性的值
3.v-text和v-html 指令 都是用来获取属性值的, 区别是:前者无法解析HTML标签只能当做一个普通文本展示 后者可以解析数据中出现的HTML标签
4.v-if指令,判断条件满足时就展示元素,不满足就不展示 了解:v-if和v-show区别?都可以判断,不满足时前者干脆不会解析元素 后者会解析这个元素但是结合css代码来隐藏style="display: none
5.v-if指令的复杂使用 if...else if...else语法同java
6.v-for指令用来循环遍历,通常用来遍历数组,语法类似forin, i是获取遍历得到的数据,in是固定语法,hobby是数组名,index是下标
,v-on & v-bind
1.v-on指令:给元素绑定不同的事件,可以简写成@
<button v-on:click="show()">按钮2</button>
<button v-on:dblclick="print(100)">按钮3</button>
<button @click="add(1,2,3)">按钮4</button>
问题:跳转时404,没有把url当变量,而是直接把整体当做跳转路径
<a href="{{url}}">百度一下1</a>
2.v-bind指令:把url当变量,去获取了变量的值进行跳转 v-bind:href可以简写成:href,意思是后面出现的url是变量不是字符串
<a v-bind:href="url">百度一下2</a>
<a :href="url">百度一下3</a>
调用代码
<script>
new Vue({
el:"#app",
data:{
url:"http://www.baidu/"
},
methods:{
//函数名:函数声明(参数列表){函数体}
show:function(){
console.log(100)
} ,
print:function(a){
console.log(a);
},
//函数名(参数列表){函数体},是上面函数的简写方式
add(a,b,c){
console.log(a+b+c);
}
}
})
</script>
五.Vue组件Component
1.概述
1.好处:可以提高前端代码的复用性
2.使用步骤:
(1):定义组件:全局组件+局部组件
(2):使用组件:就像使用HTML的标签一样
一.Vue路由Router
1.概述
1.基于Vue组件化的思想
2.用户从发起一个请求,一直到展示指定组件,这个过程就是Vue路由负责的
3.使用步骤:Vue.js+Vue-router.js引入到网页中
4.整个路由调用过程
三.Vue的ajax
1.概述
1.可以避免刷新整个网页,而实现了局部刷新的效果,异步访问的
2.提高了网页的动态性,提高了网页的响应速度.
3.在Vue框架中,封装了Ajax的复杂语法,技术命名叫axios
4.使用步骤:导入vue.js+axios.js文件
5.语法:axios.get(java程序的访问方式).then(a=>{console.log(a);})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试 axios的语法</title>
<!-- 1.导入js文件:
vue.js核心 + vue-router.js是路由 + axios.js使用vue封装好的Ajax技术
-->
<script src="vue.js"></script>
<script src="axios.min.js"></script>
</head>
<body>
<div id="app">
<button @click="show()">按钮</button>
</div>
<script>
//Vue的属性:el挂载点 + data数据区 + methods方法区
//components局部组件 + router创建路由
new Vue({
el:"#app" ,
methods:{
show(){
//vue提供的对象,get函数是指即将发起一个get请求
//参数是一段java程序的访问方式
//当程序访问成功时,then函数是vue自动调用的函数
axios.get('http://www.baidu/').then(
//a记录着java程序的返回值return
//=>叫箭头函数
a => {
//在函数体重,处理返回的结果
console.log(a.data);
}
)
}
}
})
</script>
</body>
</html>
四.Vue-cli
1.概述
1.npm:包管理器,npm命令会去指定的网址下载/安装好多的包(文件夹结构)
2.webpack:自动化构建项目的命令,可以自动下载项目相关的资源(html css js 图片),而且可以自动压缩,打包
六.在项目中添加自己资源
1.Hbuilder打开下载好的项目
2.文件-打开目录-浏览项目位置-打开
3.目录结构
JVM内存模型jdk1.7和jdk1.8的区别
永久代和元空间的区别
永久代:在运行时数据区域开辟空间实现方法区
元空间:在本地内存区域开辟空间实现方法区
为什么要移除永久代呢?
永久代中的元数据信息在每次FullGc时可能被收集,为永久代分配多少空间很难确定,超出指定空间容易造成内存泄漏
元空间的特点
-
类及相关的元数据的生命周期与类加载器的一致
-
每个加载器有专门的存储空间
-
只进行线性分配
-
不会单独回收某个类
-
省掉了GC扫描及压缩的时间
-
元空间里的对象的位置是固定的
-
如果GC发现某个类加载器不再存活了,会把相关的空间整个回收掉
SpringMvc的工作流程:
1.用户发送请求至前端控制器DispatcherServlet。
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、Controller执行完成返回ModelAndView。
7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、ViewReslover解析后返回具体View.
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户。
七.tomcat服务器
1.概述
1.服务器:就是一台电脑
2.web服务器:就是一台电脑上装了一个软件,用户可以通过浏览器访问这台上的资源
3.Tomcat服务器:就是一个人软件,是一个轻量级的web应用服务器,如果你的程序想要被用户访问,name这个程序必须放入Tomcat中
八.Servlet
1.概述
1.代表了一个服务器端,主要作用是用来和浏览器动态的交换
2.接受浏览器发来的请求
3.服务器浏览器做出响应
2.创建Servlet程序
package cn.tedu.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ServletDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doPost()");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("doGet()");
}
}
2.配置Servlet web.xml类
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp/xml/ns/javaee"
xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp/xml/ns/javaee http://xmlns.jcp/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--配置Servlet类的访问信息-->
<servlet>
<!--给Servlet设置一个名字(一般是和类名相同)
细则:名字可以自定义,但是必须唯一,
不能和别的<servlet>的<servlet-name>相同
-->
<servlet-name>hello</servlet-name>
<!--指定Servlet类的全路径(包名.类名)-->
<servlet-class>cn.tedu.servlet.ServletDemo2</servlet-class>
</servlet>
<!--指定浏览器的访问规则-->
<servlet-mapping>
<!--即将根据指定的名字,去找到一个要被访问的Servlet类的全路径-->
<servlet-name>hello</servlet-name>
<!--指定了浏览器的访问方式,
细则:值可以自定义,但是浏览器必须是一样的写法才能访问Servlet
否则404:找不到你要访问的资源
-->
<url-pattern>/a/b/c</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>hello2</servlet-name>
<servlet-class>cn.tedu.servlet.ServletDemo3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello2</servlet-name>
<!--url-pattern的值不能和其他的url-pattern的值相同-->
<url-pattern>/ServletDemo3</url-pattern>
</servlet-mapping>
</web-app>
3.测试
http://localhost:8080/abc_war_exploded/123
写自己的项目名称和资源名称_war_exploded是配置tomcat是写
九.Servlet的生命周期
1.概述
分为三大阶段
1.初始化-由Servlet主动调用init()
2.提供服务-由Servlet主动调用service()/doGet()/doPost()
3.销毁-由Service主动调用destroy()
package cn.tedu.lifecycle;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//1,Servlet程序的注解开发方式,代替了web.xml文件中的8行配置代码
@WebServlet("/ServletDemo4")//注解的参数是指浏览器的访问方式
public class ServletDemo4 extends HttpServlet {
//2,Servlet的生命周期中会被调用的方法有:
//init() service()/doGet/doPost destroy()
//3,因为GenericServlet提供的以上方法中都是空实现,
// 重写这些方法并添加方法体来感受初始化的不同阶段
//4,重写的要求:有足够的权限 + 方法声明必须和父类一样
@Override
//当第一次访问Servlet程序时,Servlet自己调用init(),只会调用一次
public void init() throws ServletException {
System.out.println("init()被调用了,Servlet已被初始化!");
}
@Override
//每次访问Servlet程序时,Servlet自己调用service(),会调用多次
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("service()开始为您服务啦!");
}
@Override
//正常的关闭服务器时,Servlet自己调用destroy(),只会调用一次
public void destroy() {
System.out.println("destroy()被调用了,Servlet即将被销毁!");
}
}
整合前端页面访问
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>前后端 安排起来</title>
</head>
<body>
<!-- 点击超链接跳转到Servlet -->
<a href="http://localhost:8090/cgb2109javaweb03_war_exploded/ServletDemo3">点我,访问ServletDemo3</a>
<a href="http://localhost:8090/cgb2109javaweb03_war_exploded/ServletDemo4">点我,访问ServletDemo4</a>
</body>
</html>
测试
1.访问地址
2. 刷新 模拟调用业务
3.关闭服务器 销毁Servlet
十.Requset
1.概述
1.是指从前端浏览器 到后端的Servlet的程序的访问过程,交请求的过程
2.可以使用Servlet提供的Request对象,来及解析请求中的请求参数
2.常用方法
getParamter()--按照参数名获取参数值,但是只得到一个值
getParamterValues()--按照参数名获取参数值,但是得到多个值,存入数组
setCharacterEncoding()--如果请求参数中有中文,设置字符集为utf-8
setAttribute()--设置属性
getAttribute()--获取属性
一.请求转发
1.概述
1.作用是想让AServlet第哦啊用BServlet的功能
2.过程:浏览器访问AServlet,但是AServlet偷偷调用了BServlet,此时浏览器的地址栏没变全程只是一次请求
3.实现:Request.getRequestDispather(访问BServlet的方式).forward(request,response)
二.响应Response
1.概述
1.是指从java程序组织好的数据 发送给 前端浏览器的过程,叫作响应
2.常用方法
1.getwriter()---给浏览器响应数据
2.setContentType()---用来解决防止响应时的中文乱码
3.senRedirect()--重定向
三.重定向
1.概述
特点:
1.整个过程有 两个请求 两个响应
2.地址栏会发生变化
3.使用response.endRedirect(对方的访问方式)
3.此时,你想访问那个程序都可以
一.Maven
–1,概述
目前我们管理jar包的方式: 搜jar包 , 下载 , 存放jar包 , 导入jar包, 编译jar包…太复杂
用Maven来管理jar包,帮我们处理以上所有流程.
1.仓库
远程仓库/中央仓库: 本质上就是一个 国外的 网址
镜像仓库: 本质上就是一个 国内的 网址,网站上存了去中央仓库下载好的jar包,常用的是阿里云
本地仓库: 就是你在电脑里创建的一个文件夹,存放从镜像仓库中下载的jar包D:\Java\maven\resp
2,坐标: 能够快速定位jar包
groupId: 组id,通常值是公司域名
artifactId: 项目id,通常值是项目名称
version: 版本
3.依赖
项目的运行需要依赖jar包,jar包间也有依赖关系.
使用dependency来指定需要的jar包坐标
4.命令:
clean: 清除maven缓存
install: 安装
更多推荐
2022复习笔记
发布评论