我们在访问web应用时,在web应用内部会有一个拦截器,这个拦截器会对请求的url进行拦截,拦截到请求以后,读取sentinel 控制台推送到web应用的流控规则,基于流控规则对流量进行限流操作。
基于Feign可以更加友好的实现服务调用,简化服务消费方对服务提供方方法的调用)。
@FeignClient注解的作用是什么?(告诉Feign Starter,在项目启动时,为此注解描述的接口创建实现类-代理类)
Feign方式的调用,底层负载均衡是如何实现的?(Ribbon)
@EnableFeignCleints 注解的作用是什么?(描述配置类,例如启动类)
打印日志的工厂设计模式,门面设计模式
可以修饰成员变量与成员方法
随着类的加载而加载,优先于对象加载
只加载一次,就会一直存在,不再开辟新空间, 直到类消失才一起消失
静态资源也叫做类资源,全局唯一,被全局所有对象共享
可以直接被类名调用
静态只能调用静态,非静态可以随意调用
static不能和this或者super共用,因为有static时可能还没有对象
Final修饰的是常量,而不是变量 定义常量的时候必须与其赋值
1.在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
2.在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
在JAVA中,继承是一个重要的特征,通过extends关键字,子类可以复用父类的功能,如果父类不能满足当前子类的需求,则子类可以重写父类中的方法来加以扩展。
在应用中就存在着两种转型方式,分别是:向上转型和向下转型。
比如:父类Parent,子类Child
向上转型:父类的引用指向子类对象Parent p=new Child();
说明:向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类的方法就根据这个引用指向调用子类重写方法。
向下转型(较少):子类的引用的指向子类对象,过程中必须要采取到强制转型。
Parent p = new Child();//向上转型,此时,p是Parent类型
Child c = (Child)p;//此时,把Parent类型的p转成小类型Child
//其实,相当于创建了一个子类对象一样,可以用父类的,也可以用自己的
说明:向下转型时,是为了方便使用子类的特殊方法,也就是说当子类方法做了功能拓展,就可以直接使用子类功能。
集合的英文名字就是Collection ,是用来存放对象的数据结构
而且长度可变
通常用来跟集合的对象一起使用..程序的增强器(可读性),,,,,,,想通过泛型来约束集合中元素的类型
在支持正则表达式操作的方法,包括:matches(),replaceAll(),replaceFirst(),split().此外,Java可以用Pattern类表达正则表达式对象,他提供了丰富的API进行各种正则表达式操作
动态初始化:int[] a =new int[5];
静态初始化:int[]b =new int{1,2,3,4,5}
Int[] c ={1,2,3,4,5}
char类型的数组底层中做了处理,可以直接打印数组
除了char 类型以外的数组想要查看数组中的具体数组,需要使用具体元素,需要使用数组的工具类Arrays
具体方式: Arrays.toString(数组名)
数组名保存的是数组的地址值,是一个引用类型变量
扩容Arrays.copyof( , )
缩容Arrays.copyof( , )
截取 Arrays.copyofRange( , , )截取数组含头不含尾,不包含结束数组的下标
Byte short int long 默认值为0
Float double 默认的值是0.0
Char 默认值\u0000,打印出来的空格
Boolean 默认值为false
What?
面向对象OOP是一种编程思想
Why?
相较于之前的面向过程而言,面向过程强调的是过程,凡是亲力亲为
而面向对象强调的是结果,我们由之前每件事的执行者转变为指挥者
要做事情,先创建对象出来,通过对象完成具体的业务,提高效率
Java是一门面向对象的语言
一个类中定义多个同名的方法,但是每个方法的参数列表不同(也就是指参数的个数和类型不同),
1.Error:错误,程序无法处理
2.Exception:我们可以编码修复的错误(RunTimeException 和 IOException )
捕获(catch)和向上抛出(throws)
抽象类是否有构造方法?有 * 既然抽象类不能实例化,为什么要有构造方法呢? * 不是为了自己使用,而是为了子类创建对象时使用super();
是的,可以通过接口类名直接调用
继承的关系,只支持单继承
实现关系,可以单实现,也可以多实现
class A implements B,C{}
是继承关系,可以单继承,也可以多继承
interface A extends B,C{}
抽象类是一个特殊的类,特殊在,抽象类中可以包含没有方法体的方法(抽象方法)
接口可以理解成一个特殊的抽象类,特殊在,接口里的都是抽象方法,没有普通方法
接口会为方法自动拼接public abstract,还会为变量自动拼接public final static
抽象类可以有成员变量成员常量
接口只能有静态常量
抽象类可以有构造方法–用来给子类创建对象
接口中没有构造方法
抽象类和接口都不能实例化(创建对象)
接口可继承接口,并可多继承接口,但类只能单继承
抽象方法只能声明,不能实现,接口是设计的结果 ,抽象类是重构的结果
API是一种预先定义的函数,目的是提供应用程序与开发人员基于某软件可以访问的一些功能集
1.toString()
本方法用于返回对应对象的字符串表示
2.hashCode()
本方法用于返回对应对象的哈希码值
小贴士:哈希码值的得出是通过一种算法,意在让不同的对象具有不同的哈希码值,用于区分不同的对象.
但是有时候也存在不同对象哈希码值相同的特殊情况,我们称之为”哈希碰撞”现象
本方法用于指示其他某个对象是否与当前对象”相等”
添加重写的equals与hashCode()
/*equals()与hashCode()逻辑要保持一致,要重写都重写,要不重写都不重写
* 如果不重写:hashCode()的哈希码根据地址值生成
* equals()底层使用==比较两个对象的地址值
* 如果重写了:hashCode()的哈希码根据重写传入的属性值生成
* equals()比较的是重写后类型 + 所有属性与属性值*/
System.out.println(String.valueOf(10));//10,将int类型的参数10转为String类型
byte[] bs = s7.getBytes();//将指定字符串转为byte[]
System.out.println(s1.charAt(0));//a,根据下标获取本字符串中对应的元素
封装了char[]数组
Append()来进行字符串的链接
区别: StringBuffer和StringBuilder的区别?
StringBuffer是jdk1.5后,线程不安全(不加锁)
StringBuilder是jdk1.0后.线程安全(加锁)
1.当使用= =比较时,如果相比较的两个变量是引用类型,那么比较的是两者的物理地值(内存地址)(地址值)
2.当使用equals()方法进行比较时,比较的结果实际上取决于equals()方法的具体实现
任何类都继承自Object类,因此所有的类均具有Object类的特性,比如String、integer等,他们在自己的类中重写了equals()方法,此时他们进行的是数值的比较,而在Object类的默认实现中,equals()方法的底层是通过==来实现的。
常用来用户输入的内容是否符合格式的要求,需注意严格区分大小写
Matches(正则):能否匹配正则表达式
ReplaceAll(正则,子串):替换子串
Split(正则):拆分字符串
1.Break直接结束当前的循环,跳出当前的这一层循环体,简单粗暴
2.Continue:跳出本轮循环,继续下一轮的循环
本循环体的后面的代码不会被执行了(启到高效的作用)
包装类的功能更加的完善
Integer : 创建Integer的对象
new Integer(5)
Integer.valueOf(5) (-128-127)的范围
Static int parseInt(String s) 将字符串参数作为有符号的十进制整数进行解析
自动装箱: 基本类型转化为包装类型(Integer a=5)(Integer a=Integer.valueOf(5))
自动拆箱: 包装类型转化为基本类型(int i=a)(int i =a.intValue())
BigDecimal(String val)
ROUND_HALF_UP 四舍五入,五入 如:4.4结果是4; 4.5结果是5
字节流继承inputSteam, OutputStream
字符流继承Reader和Writer
字节流:针对二进制文件
字符流:针对文本文件
序列化是指利用ObjectOutputStream把对象的信息,按照固定的格式转成一串字节值输出并持久保存到磁盘中
反序列化是指利用ObjectInputStream指读取此盘中之前序列化好的数据..重新恢复出对象
SerialVersionUID的作用:是验证版本号启到能否成功反序列化
1.Collection,为集合层级的根接口,
Set,是一个不能包含重复元素的集合接口
List是一个有序集合可以包含重复的元素
2.Map接口.是一个key映射到value的对象.key不能重复
尽管 Map 接口和它的实现也是集合框架的一部分,但 Map 不是集合,集合也不是 Map。因此,Map 继承 Collection 毫无意义,反之亦然。
如果 Map 继承 Collection 接口,那么元素去哪儿?Map 包含 key-value 对,它提供抽取 key 或 value 列表集合( Collection )的方法,但是它不适合“一组对象”规范。
内部数组默认的初始容量是10,如果不够会以1.5倍的容量增长
查询快,增删数据效率会低
LinkedList(): 底层是链表结构,查询慢,增删快
核心思想:就是把原数组用一个更大容量的新数组来代替,然后将原数组的数据拷贝到新的数组中来
elementData对象数组 ensureCapacityInternal方法会判断
进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。
线程池就是事先将多个线程对象放到一个容器中,当使用的时候就不用new线程而是直接去池中拿线程即可,节省了开辟子线程的时间,提高的代码执行效率。在JDK的java.util.concurrent.Executors中提供了生成多种线程池的静态方法。
2 线程创建的其他方式
2.1 ExecutorService/Executors
ExecutorService:用来存储线程的池子,把新建线程/启动线程/关闭线程的任务都交给池来管理
execute(Runnable任务对象) 把任务丢到线程池
Executors 辅助创建线程池的工具类
newFixedThreadPool(int nThreads) 最多n个线程的线程池
newCachedThreadPool() 足够多的线程,使任务不必等待
newSingleThreadExecutor() 只有一个线程的线程池
悲观锁: 像不管三七二一 ,直接加synchronized 锁
乐观锁: 竞争不是总是发生的,作为原子操作尝试去修改内存的变量
synchronized 互斥锁(悲观锁,有罪假设)
采用synchronized修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁。
每个对象都有一个monitor(锁标记),当线程拥有这个锁标记时才能访问这个资源,没有锁标记便进入锁池。任何一个对象系统都会为其创建一个互斥锁,这个锁是为了分配给线程的,防止打断原子操作。每个对象的锁只能分配给一个线程,因此叫做互斥锁。
ReentrantLock 排他锁(悲观锁,有罪假设)
ReentrantLock是排他锁,排他锁在同一时刻仅有一个线程可以进行访问,实际上独占锁是一种相对比较保守的锁策略,在这种情况下任何“读/读”、“读/写”、“写/写”操作都不能同时发生,这在一定程度上降低了吞吐量。然而读操作之间不存在数据竞争问题,如果”读/读”操作能够以共享锁的方式进行,那会进一步提升性能。
ReentrantReadWriteLock 读写锁(乐观锁,无罪假设)
因此引入了ReentrantReadWriteLock,顾名思义,ReentrantReadWriteLock是Reentrant(可重入)Read(读)Write(写)Lock(锁),我们下面称它为读写锁。
读写锁内部又分为读锁和写锁,读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的。
读锁和写锁分离从而提升程序性能,读写锁主要应用于读多写少的场景。
需要注意的是,用sychronized修饰的方法或者语句块在代码执行完之后锁会自动释放,而是用Lock需要我们手动释放锁,所以为了保证锁最终被释放(发生异常情况),要把互斥区放在try内,释放锁放在finally内!
与互斥锁相比,读-写锁允许对共享数据进行更高级别的并发访问。虽然一次只有一个线程(writer 线程)可以修改共享数据,但在许多情况下,任何数量的线程可以同时读取共享数据(reader 线程)从理论上讲,与互斥锁定相比,使用读-写锁允许的并发性增强将带来更大的性能提高
回顾之前的学过的知识
Java代码操作数据库时,那些是元数据信息?
区分jdk8之前,ArrayList 默认的存储数组的长度我是10,
当
1.什么是聚合函数?
包含MAX MIN AVG count(1) 这些都是聚合函数
2.什么是分组?
使用group by实现分组,使用having在分组后的结果上继续添加过滤条件
3什么是事务?
执行多条sql语句要么全部 成功,,要么全部失败 原子性,,一致性 隔离性 持久性
#Mysql默认就开启了事务,但是每条SQL一个事务
begin;#开启事务
insert into dept values(null,'java开发部','北京');
insert into dept values(null,'php开发部','上海');
commit;#提交事务--会对数据库产生持久影响
#rollback;#回滚事务--不会对数据库产生持久影响
4.什么是字段约束
外键约束 默认约束 检查约束
5.什么是索引
好处:给加完索引的列,提高查询效率 坏处:索引本质上就是一张表,如果表的体积太大,比较占内存 主键本身就有索引、
单值索引 复合索引 唯一索引
6什么是视图
#视图:把一个查询语句的结果缓存起来存入视图中
#好处:提高查询效率
#坏处:占用了内存,无法进行SQL优化,当更新了数据时视图也需要时间更新
#1. 创建视图 create view 视图名 as SQL语句
create view empView as
select * from emp where ename like '%a%' #把SQL执行的结果存入视图
#2. 使用视图,就当做一张表来用
select * from empView
1、Spring
Spring是一个开源容器框架,可以接管web层,业务层,dao层,持久层的组件,并且可以配置各种bean,和维护bean与bean之间的关系。其核心就是控制反转(IOC),和面向切面(AOP),简单的说就是一个分层的轻量级开源框架。
2、SpringMVC
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。SpringMVC是一种web层mvc框架,用于替代servlet(处理|响应请求,获取表单参数,表单校验等。SpringMVC是一个MVC的开源框架,SpringMVC=struts2+spring,springMVC就相当于是Struts2加上Spring的整合。
3、SpringBoot
Springboot是一个微服务框架,延续了spring框架的核心思想IOC和AOP,简化了应用的开发和部署。Spring Boot是为了简化Spring应用的创建、运行、调试、部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置。提供了一堆依赖打包,并已经按照使用习惯解决了依赖问题—>习惯大于约定。
主要作用是为了提高查询效率,它的执行也是有一定条件的,不是加了索引就一定能够加快查询的效率,由于索引的创建是需要占据内存空间的.以下不适合加索引:
坏处:索引需要单独的一张表
1:如果每次都需要取到所有表记录,无论如何都必须进行全表扫描了,那么是否加索引也没有意义了
2、对非唯一的字段,例如“性别”这种大量重复值的字段,增加索引也没有什么意义
3、对于记录比较少的表,增加索引不会带来速度的优化反而浪费了存储空间,因为索引是需要存储空间的,而且有个致命缺点是对于update/insert/delete的每次执行,字段的索引都必须重新计算更新
4、mysql中通过Explain来查看索引的扫描次数
事物就是为了保证原有事物的完整性和一致性,通过一定的条件规定该事物的可靠性和安全性(如数据库中的事物),同时具有4大特性:
A:原子性:一个事物是不可再分的工作单位,该事物要么成功要么失败
B:一致性:事物必须是使数据库从另外一个一致性状态到另一个一致性状态,与原子性密切相关
C:持久性:指一个事物一旦提交后对数据库中数据的改变应该是永久不变的
D:隔离性:一个事物的执行不能够被其他事物所干扰
JSON 是存储和交换文本信息的语法。当数据在浏览器与服务器之间进行交换时,这些数据只能是文本。JSON 属于文本,并且我们能够把任何 JavaScript 对象转换为 JSON,然后将 JSON 发送到服务器。我们也能把从服务器接收到的任何 JSON 转换为 JavaScript 对象。以这样的方式,我们能够把数据作为 JavaScript 对象来处理,无需复杂的解析和转译。
主键约束:实现实体的完整性(PK:主键),值唯一,不能为空,且使用主键的自增策略
外键约束:用于多表之间的查询该表组建作为另外张表的外键建立标语标志就的关系(FK)
非空约束:(NOT NULL)保证该字段的内容不能为空null
唯一约束:(UNIQUE)字段的值必须唯一的约束
检查约束:(CHECK)检查列的值是否满足一个boolean表达式
默认约束:(default)给指定的字段可以设置默认值,不设置值时使用默认值而不是null
(1)查询时,能不用* 就不用,尽量写全字段名
(2)索引不是越多越好,每个表控制在5个索引以内
(3)大部分情况连接效率远大于子查询,但是有例外
(4)多用explain 和 profile分析查询语句
(5)连接查询的性能上尽量使用小表驱动大表的原则
(6)查看慢查询日志,找出执行时间长的SQL进行优化
(7)尽量避免使用order by
(8)因为where子句后面的条件是执行顺序是从右到左,所以尽量把能过滤掉大部分数据的条件放在最后
把一个类放入到spring容器中,对象的创建、初始化、销毁等工作交给spring容器来做。由spring容器控制对象的生命周期
AOP把系统分为两部分,核心关注点和横切关注点。核心主要处理业务逻辑,横切主要是权限验证,日志,事物处理等,涉及到众多概念。
AOP主要由:方面(Aspect)一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的 Advisor或拦截器实现
连接点(Joinpoint):程序执行过程中明确的点,如方法的调用或特定的异常被抛出。
通知(Advice):Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice
切入点(Pointcut): Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上
引入(Introduction)Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通
目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。
AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
Spring AOP有三要素:
Aspect定义切面;
通过通知(Advice)来指定具体做什么事情。如方法执行前做什么,方法执行后做什么,抛出异常做什么,从而实现对象行为(方法)的增强;
具体通过切点(PointCut)配置切点表达式(expression)来指定在哪些类的哪些方法上织入(ware)横切逻辑;被切的地方叫连接点(JoinPoint);
SpringMVC严格上来说是一种设计思想而不是设计模式,其底层采用反射的机制构建工程,适配器,代理模式构建。
我们POJO就是Model层,我们的JSP就是视图层,Controller控制层
(1)用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获
(2)DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain(执行链)对象的形式返回
(3)DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法)
(4)提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
(5)Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象
(6)根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet
(7)ViewResolver 结合Model和View,来渲染视图
(8)将渲染结果返回给客户端
#能够有效防止SQL的注入攻击,并且是预编译的SQL
#还能够把传入的数值当成一个字符串,会对自动拼接字符串
如:where name=#{name} 如果传入的值是jack,那么解析成的SQL是:where name=“jack”
$会将传入的值直接显示在sql中,会发送sql的攻击的风险,且相对低效,不会拼接字符串
本质上是封装了JDBC,简化了jdbc的操作并且是一个非常优秀的ORM框架.
1, mybatis应用程序通过SqlSessionFactoryBuilder(创建会话工厂)从mybatis-config.xml配置文件
(也可以用Java文件配置的方式,需要添加@Configuration)中构建出SqlSessionFactory(SqlSessionFactory是线程安全的)
2, SqlSessionFactory的实例直接开启一个SqlSession
3, 再通过SqlSession实例获得Mapper对象
4, 执行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交
5, 关闭SqlSession
说明:SqlSession是单线程对象,因为它是非线程安全的,是持久化操作的独享对象,类似jdbc中的Connection,底层就封装了jdbc连接。
MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的(对应着我们的model对象中的实体),而resultMap则是对外部ResultMap的引用(提前定义了db和model之间的隐射key:value关系),但是resultType跟resultMap不能同时存在。
在MyBatis进行查询映射时,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值。
(1)当提供的返回类型属性是resultType时,MyBatis会将Map里面的键值对取出赋给resultType所指定的对象对应的属性。所以其实MyBatis的每一个查询映射的返回类型都是ResultMap,只是当提供的返回类型属性是resultType的时候,MyBatis对自动的给把对应的值赋给resultType所指定对象的属性。
(2)当提供的返回类型是resultMap时,因为Map不能很好表示领域模型,就需要自己再进一步的把它转化为对应的对象,这常常在复杂查询中很有作用。
LRU也就是“最近最少使用”,LRU缓存就是使用这种原理实现的,就是缓存一定数量的数据,当超过该数据的阈值时就把相关的数据删除掉,例如我们缓存10000条数据,当小于该数据时可以随意的增加,超过时就将过期的数据删除掉。
好比java中实现LRU就有两种方式:一是LinkedHashMap,一种是自己设计的数据结构,使用链表+HashMap。
get请求用来从服务器上获得资源,而post是用来向服务器提交数据;
get将表单中数据按照name=value的形式,添加到action 所指向的URL 后面,并且两者使用"?“连接,而各个变量之间使用”&"连接;post是将表单中的数据放在HTTP协议的请求头或消息体中,传递到action所指向URL;
get传输的数据要受到URL长度限制(1024字节);而post可以传输大量的数据, POST数据是没有限制的,上传文件通常要使用post方式;
使用get时参数会显示在地址栏上,如果这些数据不是敏感数据,那么可以使用get;对于敏感数据还是应用使用post;
get使用MIME类型application/x-www-form-urlencoded的URL编码(也叫百分号编码)文本的格式传递参数,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是"%20"。
SQL注入:就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
防止的方法:
1.永远不要信任用户的输入,要对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引号和双"-"进行转换等。
2.永远不要使用动态拼装SQL,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取。
3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
4.不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息。
应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装,把异常信息存放在独立的表中
在网页中,一个元素占有空间的大小由几个部分构成,其中包括元素的内容(content),元素的内边距(padding),元素的边框(border),元素的外边距(margin)四个部分。这四个部分占有的空间中,有的部分可以显示相应的内容,而有的部分只用来分隔相邻的区域或区域。4个部分一起构成了css中元素的盒模型。
href 是指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接,用于超链接。
src是指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置;在请求src资源时会将其指向的资源下载并应用到文档内,例如js脚本,img图片和frame等元素。当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等元素也如此,类似于将所指向资源嵌入当前标签内。这也是为什么将js脚本放在底部而不是头部。
id选择器( # myid)
类选择器(.myclassname)
标签选择器(div, h1, p)
相邻选择器(h1 + p)
子选择器(ul > li)
后代选择器(li a)
通配符选择器( * )
属性选择器(a[rel = “external”])
伪类选择器(a:hover, li:nth-child)
JDBC 是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。java 提供了jdbc的接口规范,对应数据库厂商依照规范进行驱动类库开发,提供给开发者。应用程序与数据以jdbc桥接的方式进行交互,任何基于JDBC 的 ORM 框架都是对JDBC 操作的封装。
SQL 攻击发生的现象是:用户输入了一些SQL中的特殊字符,#表示注释
Statement工具:无法避免SQL注入问题,而且SQL复杂需要自己拼接参数,低效
PreparedStatement工具:避免了SQL攻击的问题,SQL简单,高效
–SQL简单,先把SQL骨架发给数据库,再把参数发给数据库。用?代替参数的位置叫占位符
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
维护一定数量的连接,减少创建连接的时间
更快的响应时间
统一的管理
优点
1、容易理解:二维表结构是非常贴近逻辑世界一个概念,关系模型相对网状、层次等其他模型来说更容易理解;
2、使用方便:通用的SQL语言使得操作关系型数据库非常方便;
3、易于维护:丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了数据冗余和数据不一致的概率;
4、支持SQL,可用于复杂的查询。
5, 支持事务
缺点
1、为了维护一致性所付出的巨大代价就是其读写性能比较差;
2、固定的表结构;
3、不支持高并发读写需求;
4、不支持海量数据的高效率读写
非关系型数据库
1、使用键值对存储数据;
2、分布式;
优点
无需经过sql层的解析,读写性能很高
基于键值对,数据没有耦合性,容易扩展
存储数据的格式:nosql的存储格式是key,value形式
缺点
不提供sql支持
自动装配
利用注解方式,我们只需要写@Autowired注解,底层就会去容器中找对应的对象,如果有获取到,反射调用其对应的set方法,设置。而这个调用过程都是自动,我们没有手工去写set方法。所以这个过程也称为自动装配`。
1.区别一,定长和变长
char 表示定长,长度固定,varchar表示变长,即长度可变。char如果插入的长度小于定义长度时,则用空格填充;varchar小于定义长度时,还是按实际长度存储,插入多长就存多长。
因为其长度固定,char的存取速度还是要比varchar要快得多,方便程序的存储与查找;但是char也为此付出的是空间的代价,因为其长度固定,所以会占据多余的空间,可谓是以空间换取时间效率。varchar则刚好相反,以时间换空间。
2.区别之二,存储的容量不同
对 char 来说,最多能存放的字符个数 255,和编码无关。
而 varchar 呢,最多能存放 65532 个字符。varchar的最大有效长度由最大行大小和使用的字符集确定。整体最大长度是 65,532字节。
1, 读未提交: 性能最好,但是安全性最差
2, 读已提交: 性能较差,安全性较高,Oracle数据库的默认隔离级别
3, 可重复读: 性能较差,安全性较高,MySQL数据库的默认隔离级别
4, 串行化: 性能太差
和索引一样,都是对数据库优化的有效方案.
特点: 1, 可以把视图当做表来使用
2,视图里存的数据是 SQL查询到的结果
3,SQL无法优化,要合理的使用视图
一对一:Association+JavaType
一对多:collection+ofType
当数据库的字段名 和 对象的属性名 一致时,可以用简单属性resultType。
但是当 数据库中的字段名称 和 对象中的属性名称 不 一致时,就需要resultMap属性。
多表联查的使用的时候resultMap
Resulttype是resultMap的k键
JDBC是java提供了一套专门用于和数据库对接的api,java.sql.*,其规范了如何和数据库进行对接,实现由各数据库厂商进行各自的实现和扩展。学习JDBC重点在学习如何使用其api。
MyBatis框架是轻量级封装了JDBC,我们已经看不到这些api,连接connection、语句preparedstatement、结果集ResultSet,而关注的是mybatis框架体系如何去使用,一旦写好,我们关注的是java对象。
SqlSession的getMapper方法找到类,通过反射可以获取到类的全路径(包名.类名),相加后就定位到某个xml的命名空间namespace,在根据调用的方法去找到xml中某个标签的id属性。从而实现价值接口,调用接口的方法而间接找到xml中的标签,通过解析xml获取这个标签的内容,从而获取到sql语句。
MyBatis提供了两种操作数据库的方式,一种是通过xml映射文件,一种是通过java的接口类。按面向对象方式更加推荐接口方式,但如果复杂的多表映射,仍然需要使用xml映射文件的ResultMap方式实现。
接口只是假象,其底层仍然是通过xml实现,好不容易实现了一套方式,怎忍丢掉呢?可以做个测试就知道它底层怎么实现的?把xml中的sql删除,它就玩不转了。
mybatis是什么?有什么特点?
它是一款半自动的ORM持久层框架,具有较高的SQL灵活性,支持高级映射(一对一,一对多),动态SQL,延迟加载和缓存等特性,但它的数据库无关性较低
什么是ORM?
Object Relation Mapping,对象关系映射。对象指的是Java对象,关系指的是数据库中的关系模型,对象关系映射,指的就是在Java对象和数据库的关系模型之间建立一种对应关系,比如用一个Java的Student类,去对应数据库中的一张student表,类中的属性和表中的列一一对应。Student类就对应student表,一个Student对象就对应student表中的一行数据
为什么mybatis是半自动的ORM框架?
用mybatis进行开发,需要手动编写SQL语句。而全自动的ORM框架,如hibernate,则不需要编写SQL语句。用hibernate开发,只需要定义好ORM映射关系,就可以直接进行CRUD操作了。由于mybatis需要手写SQL语句,所以它有较高的灵活性,可以根据需要,自由地对SQL进行定制,也因为要手写SQL,当要切换数据库时,SQL语句可能就要重写,因为不同的数据库有不同的方言(Dialect),所以mybatis的数据库无关性低。虽然mybatis需要手写SQL,但相比JDBC,它提供了输入映射和输出映射,可以很方便地进行SQL参数设置,以及结果集封装。并且还提供了关联查询和动态SQL等功能,极大地提升了开发的效率。并且它的学习成本也比hibernate低很多
在web服务器端,转变成java文件: Login_jsp.java(继承了HttpJspBase)--->又继承了HttpServlet
Jsp本质是一个java类,属于动态资源数据,在访问jsp时,经过jsp-->java-->class文件,比较
耗时