提高应用程序的性能,减少到数据库的访问次数,
2.缓存的介质(缓存的存储位置)
内存:临时性存储空间存取数据快减少网络通信量
硬盘:永久性存储空间存取速度慢
3.缓存的分类
客户端缓存:浏览器cookie
服务器缓存:oscache,redis,memcache,session
4.缓存什么样的数据?
经常访问,又不经常修改的数据
5.缓存的有效性
为了避免脏数据的产生,要刷新缓存,这时就用到了事务为了避免页面显示问题,需要更新缓存和数据库保证一致性
6.脏数据
如果缓存中的数据和数据库中的数据不一致,那么缓存中的数据就被称之为脏数据
脏读:一个事务读到另一个事务未提交的数据
7.刷新缓存的方式
手动刷新:写程序的时候调用指定的代码清除缓存数据
8.缓存的层次(一般我们将缓存加载service中)
jsp-->action-->service-->dao
缓存越靠前对性能的提高越大
9.缓存的清除策略:(缓存空间不足需要进行清理的时候使用)
LRU:最近最少使用原则.(理解:存储书)
FIFO:先进先出的缓存策略.(理解:排队)
10.什么时候使用缓存的清除策略?
当缓存中的数据已满,又有新的数据进来时,执行缓存的清除策略
Maven两个重点:根据Maven的约定由于配置了四个文件的文件名必须是固定的,还有一个loge日志的名字也是固定的,这样不需要去加载这些文件直接通过Maven的约定由于配置自动加载好
我当时是怎么配置maven的通过在服务端中setting中配置这个mirror镜像配置访问nexus的访问路径
这样我们就可以通过pom.xml先到我们的本地去找,如果本地仓库找不到在去maven私服去找如果私服找不到在去外网下载使用maven这样可以提高我们的开发效率与节省了下载带宽,以及jar包的重用性。
@Controller:使其普通的java类充当控制层的作用。
@RequestMapping:有两个参数url代表要访问的路径method请求方式
@Service::使其java类充当service层。
@Repository::使其java类充当持久层。Er4
@Resource:默认按照名字注入指定的bean。
@Autowired:默认按照类型进行注入可以结合@Qualifier("bean的的名字名字")使使其按照名字进行注入。他是其按照名字进行注入。他是Spring中的注解。
@RespsonceBody:将controller的方法返回的对象通过适当的转换器转换为指定个时候将其输出(通常适用于返回json/xml)
@RequestParam
作用:1.在文件上传时注解@requestParam后跟multilpartFile属性
2.接收指定参数名的参数并对方法中的参数赋值并且可以设置默认值
我对SpringMVC的理解和运用。
SSH整合的流程
在项目中首先是通过在web.xml中配置strtus2的前端控制器filterDispatcher加载struts.xml
配置文件并对指定的后缀名进行拦截,并且通过配置spring的监听器contextLoadListener
spring-service.xml,spring-dao.xml,spring-common.xml,
之后新建控制层的类继承于BaseAction,而BaseAction继承于ActionSupport,
在BaseAction中封装了常用的方法如getRealPath(),outJson()等,
之后控制层注入service层,service层注入dao,dao层继承于HibernateDaoSupport
并注入spring-common.xml中配置的sessionFactory,sessionFactory注入dataSource连接数据库,
注入hibernate.cfg.xml从而加载hbm.xml文件,
除此之外还通过Spring中的Aop配置了事务并且通过切点表达式对Servcie层代码进行控制。
======================================================================SSM整合的流程
在项目中通过在web.xml配置springMVC的核心控制器DispatcherServlet
并加载Spring-mvc-controller.xml,并且通过配置Spring的监听器contextLoaderListener
加载spring-common.xml,之后新建控制层并在类上加入@Controller和@RequestMapping注解,
并通过@Resouce注入service层,在
service的实现类上加入@Service注解并通过@Autowired注入dao层,
dao层只有接口并没有实现类,
是通过在mybatis中对应的含有sql语句的xml文件中来通过namespace指明要实现的dao层的接口,
并使sql语句的id和dao层接口中的方法名一致从而明确调用指定dao层接口时要执行的sql语句。
并且在spring-mvc-controller.xml中配置了component-scan对controller
进行扫描从而使控制层的注解生效还配置了内部视图解析器从而在控制层进行页面跳转时加上指定的前缀和后缀,
在spring-common.xml中配置了dbcp数据库连接池以及sqlSession来加载mapper下所有的xml
并对所有的mapper层进行扫描也就是对dao层的扫描,
还通过Aop中的切点表达式对service层进行事务控制,并且对service层进行扫描使其注解生效。
Spring是完全面向接口的设计,降低程序耦合性,主要是事务控制并创建bean实例对象。在ssh整合时,充当黏合剂的作用。IOC(InversionofControl)控制反转/依赖注入,又称DI(DependencyInjection)(依赖注入)
IOC的作用:产生对象实例,所以它是基于工厂设计模式的
SpringIOC的注入
通过属性进行注入,通过构造函数进行注入,
注入对象数组注入List集合
注入Map集合注入Properties类型
SpringIOC自动绑定模式:
可以设置autowire按以下方式进行绑定
按byType只要类型一致会自动寻找,
按byName自动按属性名称进行自动查找匹配.
AOP面向方面(切面)编程
AOP是OOP的延续,是AspectOrientedProgramming的缩写,
意思是面向方面(切面)编程。
注:OOP(Object-OrientedProgramming)面向对象编程
AOP主要应用于日志记录,性能统计,安全控制,事务处理(项目中使用的)等方面。
Spring中实现AOP技术:
在Spring中可以通过代理模式来实现AOP
代理模式分为
静态代理:一个接口,分别有一个真实实现和一个代理实现。
动态代理:通过代理类的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联。
动态代理有两种实现方式,可以通过jdk的动态代理实现也可以通过cglib
来实现而AOP默认是通过jdk的动态代理来实现的。jdk的动态代理必须要有
接口的支持,而cglib不需要,它是基于类的。
SpringAOP事务的描述:
在spring-common.xml里通过
Spring实现ioc控制反转描述:
原来需要我们自己进行bean的创建以及注入,而现在交给
spring容器去完成bean的创建以及注入。
所谓的“控制反转”就是对象控制权的转移,
从程序代码本身转移到了外部容器。
官方解释:
控制反转即IoC(InversionofControl),
它把传统上由程序代码直接操控的对象的调用权交给容器,
通过容器来实现对象组件的装配和管理。
所谓的“控制反转”概念就是对组件对象控制权的转移,
1.Map是一个以键值对存储的接口。Map下有两个具体的实现,分别是HashMap和HashTable.
2.HashMap是线程非安全的,HashTable是线程安全的,所以HashMap的效率高于HashTable.
3.HashMap允许键或值为空,而HashTable不允许键或值为空.
HashMap底层就是一个数组结构,数组中的每一项又是一个链表。
当新建一个HashMap的时候,就会初始化一个数组。
Entry就是数组中的元素,每个Entry其实就是一个key-value对,
它持有一个指向下一个元素的引用,这就构成了链表。
HashMap在底层将key-value当成一个整体进行处理,这个整体就是一个Entry对象。
HashMap底层采用一个Entry[]数组来保存所有的key-value对,
当需要存储一个Entry对象时,会根据hash算法来决定其在数组中的存储位置,
再根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,
也会根据hash算法找到其在数组中的存储位置,
再根据equals方法从该位置上的链表中取出该Entry。
Jdk【JavaDevelopmentToolKit】就是java开发工具箱,JDK是整个JAVA的核心里边包含了jre,它除了包含jre之外还包含了一些javac的工具类,把java源文件编译成class文件,java文件是用来运行这个程序的,除此之外,里边还包含了java源生的API,java.lang.integer在rt的jar包里边【可以在项目中看到】,通过rt这个jar包来调用我们的这些io流写入写出等
JDK有以下三种版本:
J2SE,standardedition,标准版,是我们通常用的一个版本
J2EE,enterpsiseedtion,企业版,使用这种JDK开发J2EE应用程序
J2ME,microedtion,主要用于移动设备、嵌入式设备上的java应用程序
Jre【JavaRuntimeEnviromental】是java运行时环境,那么所谓的java运行时环境,就是为了保证java程序能够运行时,所必备的一基础环境,也就是它只是保证java程序运行的,不能用来开发,而jdk才是用来开发的,所有的Java程序都要在JRE下才能运行。
包括JVM和JAVA核心类库和支持文件。与JDK相比,它不包含开发工具——编译器、调试器和其它工具。
Jre里边包含jvm
Jvm:【JavaVirtualMechinal】因为jre是java运行时环境,java运行靠什么运行,而底层就是依赖于jvm,即java虚拟机,java虚拟机用来加载类文件,java中之所以有跨平台的作用,就是因为我们的jvm
关系:
J2se是基于jdk和jre,
JDK是整个JAVA的核心里边包含了jre,
1.List和Set都是接口,他们都继承于接口Collection,List是一个有序的可重复的集合,而Set的无序的不可重复的集合。Collection是集合的顶层接口,Collections是一个封装了众多关于集合操作的静态方法的工具类,因为构造方法是私有的,所以不能实例化。
2.List接口实现类有ArrayList,LinkedList,Vector。ArrayList和Vector是基于数组实现的,所以查询的时候速度快,而在进行增加和删除的时候速度较慢LinkedList是基于链式存储结构,所以在进行查询的时候速度较慢但在进行增加和删除的时候速度较快。又因为Vector是线程安全的,所以他和ArrayList相比而言,查询效率要低。
我负责项目中的系统管理模块,其中包含用户管理,菜单管理以及给用户赋角色,给角色赋权限;涉及到的表有用户表,角色表,用户角色关联表,菜单表,角色菜单关联表。在菜单管理模块采用ztree进行菜单的增删改查操作,为了将权限控制到按钮级别我们在进行菜单管理时会设置该菜单是属于按钮级别还是普通菜单,通过在数据库中增加一个type类型的字段来实现,如type为1则是普通菜单,type为2则是按钮菜单。
共同点:
不同点
1.get是从服务器上获取数据,post是向服务器传送数据,
2.get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。
3.get安全性非常低,post安全性较高。但是执行效率却比Post方法好。
4.在进行文件上传时只能使用post而不能是get。
5.不明确是post请求的都是get请求
1、从数据共享上
Forword是一个请求的延续,可以共享request的数据
Redirect开启一个新的请求,不可以共享request的数据
2、从地址栏
Forword转发地址栏不发生变化
Redirect转发地址栏发生变化
HTTP是一个超文本传输协议,属于OSI七层模型的应用层,由请求和响应构成,
是一个标准的客户端服务器模型。HTTP是无状态的也就是说同一个客户端的这次请求和上次请求是没有对应关系。
之后发送请求到服务器,请求中包含了要访问的url地址,请求的方式(get/post),
以及要传递的参数和头信息,服务器接到请求后会进行响应,
包括状态行,状态码,响应头,以及要响应的主体内容。客户端接收
到请求后将其展示到浏览器上然后断开和服务器端的连接。
简单说就是:建立连接--》发送请求--》响应--》断开连接
在HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,
但任务结束就中断连接。
从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有加入这行代码:
Connection:keep-alive
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,
如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。
实现长连接要客户端和服务端都支持长连接。
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
jquery是一个轻量级的js框架,具有跨浏览器的特性,兼容性好,
并且封装了很多工具,方便使用。
常用的有:选择器,dom操作,ajax(ajax不能跨域),特效,工具类
在数据库中,所谓事务是指一组逻辑操作单元即一组sql语句。当这个单元中的一部分操作失败,整个事务回滚,只有全部正确才完成提交。
判断事务是否配置成功的关键点在于出现异常时事务是否会回滚
事务的ACID属性
1.原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,
要么都不发生。
2.一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(数据不被破坏)
3.隔离性(Isolation)
事务的隔离性是指一个事务的执行不能被其他事务干扰.
4.持久性(Durability)
持久性是指一个事务一旦被提交,
它对数据库中数据的改变就是永久性的.即使系统重启也不会丢失.
在JDBC中,
事务默认是自动提交的,
每次执行一个SQL语句时,如果执行成功,
就会向数据库自动提交,而不能回滚
为了让多个SQL语句作为一个事务执行:
(1)执行语句前调用Connection对象的setAutoCommit(false);
以取消自动提交事务
(2)在所有的SQL语句都成功执行后,调用commit();方法提交事务
(3)在出现异常时,调用rollback();方法回滚事务。
1、索引的概念
索引就是为了提高数据的检索速度。
数据库的索引类似于书籍的索引。
在书籍中,索引允许用户不必翻阅完整个书就能迅速地找到所需要的信息。
在数据库中,索引也允许数据库程序迅速地找到表中的数据,
而不必扫描整个数据库.
2、索引的优点
1.创建唯一性索引,保证数据库表中每一行数据的唯一性
2.大大加快数据的检索速度,这也是创建索引的最主要的原因
创建索引默认排序如果索引和主键顺序相同则不用排序
3.减少磁盘IO(向字典一样可以直接定位)
3、索引的缺点
2.索引需要占用额外的物理空间
3.当对表中的数据进行增加、删除和修改的时候,
索引也要动态的维护,降低了数据的维护速度
4、索引的分类
1.普通索引和唯一性索引
普通索引:CREATEINDEXmycolumn_indexONmytable(myclumn)
唯一性索引:保证在索引列中的全部数据是唯一的
CREATEuniqueINDEXmycolumn_indexONmytable(myclumn)
2.单个索引和复合索引
单个索引:对单个字段建立索引
复合索引:又叫组合索引,在索引建立语句中同时包含多个字段名,
最多16个字段
CREATEINDEXname_indexONuserInfo(firstname,lastname)
3.顺序索引,散列索引,位图索引
首先不考虑查询条件先写分页语句在写条件
1.例如:河北省不满18周岁的男的4,5,6条信息
select*from
(selectt.*,rownumrnfrom
(selectid,name,age,sexfromt_studentwherename="河北"andage<18andsex="男")t
whererownum<=6)
wherern>=4
2.女生年龄从高到低排序每页3条查询第3条
(selectid,name,agefromt_studentorderbyagedesc)t
whererownum<=9)
wherern>=7
第一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列。
第二范式(2NF):首先是满足第一范式,另外包含两部分内容,一是表必须有一个主键;二是没有包含在主键中的列必须完全依赖于主键,而不是部分依赖。
第三范式(3NF):首先满足第二范式,非主键列直接依赖于主键,消除传递依赖。
rowid物理位置的唯一标识。
而id是逻辑上的唯一标识,所以rowid查找速度要快于id,是目前最快的
定位一条记录的方式
rowid和rownum都是"伪数列"
所谓“伪数列”也就是默认隐藏的一个数列。
rownum用于标记结果集中结果顺序的一个字段,
它的特点是按顺序标记,而且是连续的,
换句话说就是只有有rownum=1的记录,才可能有rownum=2的记录。
rownum关键字只能和<或者<=直接关联
如果是>或者=则需要给他0起个别名
单例就是该类只能返回一个实例(实例只会创建一次)
单例所具备的特点:
1.私有的构造函数
2.私有的静态的全局变量
3.公共的静态的方法
双重锁定式
publicclassSingleton{
privateSingleton(){};
privatestaticSingletonsingle;
publicstaticSingletongetInstance(){
if(null==single){
Synchronized(single){
single=newSingleton();
}
returnsingle;
在创建主键的同时会生成对应的唯一索引,主键在保证数据唯一性的同时不允许为空,而唯一可以有一个为空数据项,一个表中只能有一个主键,但是一个主键可以有多个字段,一个表中可以有多个唯一索引。
数据库连接池的优点运行原理:
在我们不使用数据库连接池的时候,每次访问数据库都需要创建连接,
使用完成之后需要释放关闭连接,而这样是很耗费资源的。当我们使用
数据库连接池的时候,在tomcat启动的时候就创建了指定数量的连接,
之后当我们程序使用的时候就直接从连接池里面取,而不需要创建,同理,
当我们使用完的时候也不需要关闭连接,而是将连接返回到连接池中,供
其他请求继续使用。
DBCP:比较稳定。
C3P0:性能比较高。
Hibernate属于全自动,Ibatis属于半自动,Jdbc属于手动,从开发效率上讲hibernate较高,ibatis居中,jdbc较低,从执行效率上讲hibernate较低,ibatis居中,jdbc较高,因为jdbc是手工写sql语句,程序员对sql的控制能力更大,可以根据业务需要进行优化,而ibatis虽然也可以对sql进行优化,但是他里面将resultset封装为实体的过程中采用了反射机制所以一定程度上影响了性能,而hibernate因为高度封装所以开发效率相对较高,但正因为这个原因,所以程序员在对sql语句的控制和优化方面相对比较弱,而且在将resultset封装成实体的过程中也采用了反射机制,所以在性能方面较低
外键必须加索引。
避免在where子句中对有索引的字段进行运算,这会导致索引失效,从而进行全表扫描。
在where及orderby涉及的列上建立索引,要尽量避免全表扫描。
在设计表时要避免表中字段出现null的情况,通常要为其设置默认值。
避免在查找时放弃使用索引而进行全表扫描。
用NOTEXISTS替换NOTIN操作符,用EXISTS替换IN
解析大文件的xml
数据使用sax替代dom4j,使用分段批量提交来完成大数据量的插入。
对于大批量字符串的拼接使用stringbuffer或者stringbuilder代替string进行+拼接。
根据业务情况使用缓存减少对数据库的访问。
单线程应尽量使用HashMap,ArrayList,因为HashTable,Vector使用了同步机制,降低了性能。
在finally块中关闭流,断开连接,释放资源。
避免在循环条件中使用复杂表达式。
3.Hibernate优化:
在处理大数据量时,会有大量的数据缓冲保存在Session的一级缓存中,这缓存大太时会严重显示性能,所以在使用Hibernate处理大数据量的,可以使用session.clear()或者session.evict(Object),在处理过程中,清除全部的缓存或者清除某个对象。
通过使用Hibernate的一级缓存,二级缓存,查询缓存等来提高性能(必须)
Hibernate可以通过设置hibernate.jdbc.fetch_size,hibernate.jdbc.batch_size等属性,对Hibernate进行优化。
BatchSize是设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小,BatchSize越大和数据库交互的次数就越少,速度就越快,但也不要无限的大下去,通常选择一个合适的值,如100条;其次我们在进行大批量数据的导入操作时,可以结合batchsize进行分段批量提交,从而达到最优效果。
29.数据库优化?(被动说)
数据库优化:作为开发人员最主要是从sql语句的优化方面考虑的,对于数据库底层的优化,是由DBA完成的。
2.分表:
水平划分垂直划分(把平常经常使用的提取出来加上索引)
3.在mysql中通过explain查看执行计划
redis是一个基于key,value的支持多种数据类型(String,List,Set,zSet,Hash)的可进行持久化的内存数据库。我们在项目中通常使用redis来充当缓存服务器来缓存分类列表,品牌列表,热销商品,推荐商品以及该商品的关联商品等等。以前做项目的时候,我们是把商品的信息存放在redis里面,redis支持多种数据类型,有两种方法存储对象:1,可以把对象序列化进行存储,然后反序列化取出。2.用hash结构存储,最后发现,还是用hash存取比较快
当设置好slave服务器后,slave会建立和master的连接,然后发送sync命令。无论是第一次同步建立的连接还是连接断开后的重新连接,master都会启动一个后台进程,将数据库
快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来。后台进程完成写文件后master就发送文件给slave,slave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上。接着master就会把缓存的命令转发给slave。而且后续master收到的写命令都会通过开始建立的连接发送给slave。从master到slave的同步数据的命令和从client发送的命令使用相同的协议格式。当master和slave的连接断开时slave可以自动重新建立连接。如果master同时收到多个slave发来的同步连接命令,只会使用启动一个进程来写数据库镜像,然后发送给所有slave。
哨兵要监视Redis服务器,就必须连接Redis服务器。启动哨兵的时候需要指定一个配置文件,程序初始化的时候会读取这个配置文件,获取被监视Redis服务器的IP地址和端口等信息。
哨兵连接redis服务器发送两个连接一个是普通连接,另一个是订阅发布专用连接。哨兵在初始化订阅发布连接的时候,做了两个工作:一是,向Redis服务器发送SUBSCRIBESENTINEL_HELLO_CHANNEL命令;二是,注册了回调函数sentinelReceiveHelloMessages()。
哨兵会向hello频道发送包括:哨兵自己的IP地址和端口,runid,当前的配置版本;其所监视主机的IP地址,端口,当前的配置版本。【这里要说清楚,什么是runid和配置版本】虽然未知的信息很多,但我们可以得知,当一个哨兵新加入到一个Redis集群中时,就能通过hello频道,发现其他更多的哨兵,而它自己也能够被其他的哨兵发现,哨兵向与Redis服务器的命令连接通道上,发送了一个INFO命令(字符串);并注册了回调函数sentinelInfoReplyCallback()。Redis服务器需要对INFO命令作出相应,能在redis.c主文件中找到INFO命令的处理函数:当Redis服务器收到INFO命令时候,会向该哨兵回传数据,包括:
关于该Redis服务器的细节信息,rRedis软件版本,与其所连接的客户端信息,内存占用情况,数据落地(持久化)情况,各种各样的状态,主从复制信息,所有从机的信息,CPU使用情况,存储的键值对数量等。
Redis服务器收集了这些信息回传给了哨兵,刚才所说哨兵的回调函数sentinelInfoReplyCallback()会被调用,它的主要工作就是着手监视未被监视的从机;完成一些故障修复(failover)的工作。连同上面的一节,就是Redis的autodiscover的全貌了。
一个Redis集群难免遇到主机宕机断电的时候,哨兵如果检测主机被大多数的哨兵判定为下线,就很可能会执行故障修复,重新选出一个主机。一般在Redis服务器集群中,只有主机同时肩负读请求和写请求的两个功能,而从机只负责读请求,从机的数据更新都是由之前所提到的主从复制上获取的。因此,当出现意外情况的时候,很有必要新选出一个新的主机。
优选选择优先级高的从机
优先选择主从复制偏移量高的从机,即从机从主机复制的数据越多
优先选择有runid的从机
如果上面条件都一样,那么将runid按字典顺序排序
并且通过加入哨兵来使redis主服务器宕机时,从服务器自动转换为主服务器继续提供服务。
①加载数据库驱动程序(Class.forName("数据库驱动类");)②连接数据库(Connectioncon=DriverManager.getConnection();)③操作数据库(PreparedStatementstat=con.prepareStatement(sql);stat.executeQuery();)④关闭数据库,释放连接(con.close();)
悲观锁/乐观锁:
悲观锁(PessimisticLock),每次去查询数据的时候都认为别人会修改,
所以每次在查询数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。
传统的关系型数据库里边就用到了这种锁机制,比如通过select....forupdate进行数据锁定。
乐观锁(OptimisticLock),每次去查询数据的时候都认为别人不会修改,
所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,
spring中事务的传播特性好像有5个左右,
我做项目的时候使用最多的就是PROPAGATION_REQUIRED,
它所代表的意思支持当前事务,如果当前没有事务,就新建一个事务。
spring中事务的隔离级别有5个,默认使用的是ISOLATION_DEFAULT,
它代表使用数据库默认的事务隔离级别,也是我们项目中最常使用的。
除此之外还有
读未提交:
它充许另外一个事务可以看到这个事务未提交的数据,
这种隔离级别会产生脏读,不可重复读和幻像读。
读提交:
保证一个事务修改的数据提交后才能被另外一个事务读取,
也是大多数数据库的默认值。可以避免脏读,但会产生不可重复读和幻像读。
重复读:
在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
串行化:
顺序执行事务。除了防止脏读,不可重复读外,还避免了幻像读。
并发性也最低,但最安全。
不可重复读的重点是修改:
同样的条件,你读取过的数据,再次读取出来发现值不一样了。
幻读的重点在于新增或者删除:
同样的条件,第1次和第2次读出来的记录数不一样。
mongodb正好适用于这种大数据量、高并发、弱事务的互联网应用。考虑
到mongodb的高可用性我们搭建了3台mongodb数据库来实现副本集,这样
不仅可以达到故障自动转移的特性而且也可以通过读写分离提高性能,即便
主服务器宕机了,还会通过投票选举出下一个主服务器继续提供服务。
再者考虑到我们的项目最后要部署到多台tomcat通过nginx来实现负载均衡,
为了对项目中的文件以及图片进行统一的管理,我们就用mongodb来充当文件服务器。
对于大部分的单张图片和单个文件来说小于16M,所以我们就以常规的方式来将
文件转换为二进制的字节数组进行保存。考虑到高可用性以及为了应对后期随着文件数量的不断
增加而能够方便进行扩容,我们建立了3个分片并将分片和副本集做了整合,每个分片都是一个副本集,这样
不仅满足了大数据量的存储也避免了分片中单台机器导致的单点故障问题。考虑到可能要处理
大于16M的文件,所以又增加了支持大文件存储的gridfs,这样即便再大的文件也会被gridfs分解为多个
chunk进行存储。
我们在项目中通常用EasyUI来充当展示层,因为它是一个RIA富客户端框架,
自身提供了很多功能强大的插件,可以提高用户的体验度而且也有助于我们
开发人员直接使用,提高开发效率。我们在项目中使用到的EasyUI插件有Layout布局,
EasyUI的tree,Tab页面,datagrid,form表单,Dialog对话框,Messager提示信息还有
Accordion手风琴效果,progress进度条等。
EasyUI的tree的生成方式有两种,一种是通过一条sql语句查询所有的菜单信息,
然后在java中通过递归的方式将其拼装成符合指定json格式的数据,这种适用
于数据量比较小的情况,通过减少数据库的访问次数提高性能,另一种是通过
ajax异步加载的方式,每点击一下树节点就向后台发送一次请求,从而来获取
该节点下的子节点,这种适用于数据量比较大的情况。这时候如果采用取出全
部数据递归拼装的话就有可能出现内存溢出。
我们当时在项目中是通过Easyui的tree来生成菜单,考虑到菜单的
数据量也不是特别的大,所以就采用了第一种取出所有数据并递归将其
拼装成指定Json的方式来提高性能,再者考虑到每个用户的菜单信息并
不是经常改变,所以又结合oscache缓存以及带有双重判定锁的单例模式
将其缓存到内存中,从而再次提高了性能。
在点击树形菜单,动态添加tab页的时候一定要注意,为了避免每次点击
都添加一个新的tab页,我们的做法是当点击事件发生时,先判断当前
选中的菜单通过exist方法判断所对应的tab页是否已经存在,如果存在就select方法将其激活选中,否则
再添加新的。多个tab页出现的另一个问题就是不同tab页间的数据可能不
同步,所以我们会在每个tab页上面都增加一个刷新按钮,可以通过点击
该按钮给该tab页所对应的iframe的src属性重新赋值,来起到刷新的作用。
datagrid也是我们在项目中经常使用到的,在使用datagrid时应该注意的是分页
在拼装好的json数据中,需要响应有total和rows这两个属性,其中total用来
指明数据的总条数,rows用来指明当前页的数据列表;要从页面获取参数page和rows在前台页面中要保证
columns中的field和rows中的属性名相对应,否则数据就展现不出来,而且
对于图片等制定格式数据的展示需要结合formatter对其进行格式化才能进行
正确的显示。最后就是在datagrid和form表单结合进行数据查询时调用的是
load方法,进行增删改后刷新datagrid调用的是reload方法。
Bootstrap是一个支持响应式的Css框架它提供了很多组件,
如导航条,面板,菜单,form表单,还有栅格,
而且他们这些都是支持响应式的,可以在各种
设备上进行完美的展现。这里面我感觉最有价值的就是
bootstrap提供的栅格系统,这个栅格系统将
整个页面分为12列,而且可以根据屏幕的宽窄进行自动
调节,这也是响应式的关键所在。在使用栅格系统的时候
要注意最外层样式是Container,里面是row,row里面包含
的是列,列里面可以用来填充各种各样的组件。
我在项目中使用bootstrap完成的情况大概是这个样子,
首先我使用了bootstrap的导航条,并将其固定在顶部,
使其在拖拉滚动条的时候不至于看不到,
之后在导航条的下面采用了bootstrap的栅格系统将其分为左右两部分,
左边使用bootstrap的Treeview组件,将菜单展现出来,当点击treeview
上的菜单节点时结合一个第三方的tab组件,将需要展示的内容放到tab页内,
并进行上下切分,上面使用了bootstrap的form组件,
下面使用了它的响应式表格以及分页组件,在进行增加修改时,
使用了第三方的bootbox弹出框。
海淀区蓝靛厂晨月园小区远大路公交站上车355/79/118线都能到坐六站(定慧北桥下车)走大概5分钟就到了
公司附近在那边有一个丰台科技原生态主题公园
晨月园附近有个巨人学校
从育新坐606路公交到成府路南口下车然后在步行到公司
15K14K13K1000
郑州理工专修学院计算机科学与技术刘信古
有,还有,酒店服务管理建筑工程行政管理轨道交通运营等等。。。
计算机原理计算机网络高级语言编程语言操作系统数据结构
26马
合同到期,想换一个新的环境,公司这边也挽留我,但是在公司也呆了,2.3年了,
想换一个新的平台,来不断提升充实自己。
在上家公司的时候,人事说咱们公司的五险一金如果要上的话都是从自己工资里面扣的,
当时感觉没啥必要也就没上。
这几年做程序,因为要不断的对代码进行验证确认,所有感觉自己现在有点强迫症。
前2,3年继续加强自己的技术功底,然后朝着项目经理(技术经理,产品经理)方面发展
2008年9月2012年6月下了火车打个车10来块钱
(吹牛逼的活)有一些卖衣服的卖吃的小超市酒店什么的....
养老保险,医疗保险,失业保险,工伤保险,生育险住房公积金
60人左右技术部销售部行政部人力资源部财务部
ajax全称是异步JavaScript及xml;
ajax的核心JavaScript中的xmlHttpRequest(XHR);
使用ajax可以提高用户的体验度,进行异步数据传输从而提高性能。ajax不能跨域,所谓不能跨域就是不能跨多个网站(多个域名),不能跨多个项目可以通过jsonp来解决ajax跨域的问题,而jsonp的实质就是通过动态添加script标签来实现的
Ajax异步是跳转页面加载一部分数据当点击按钮的时候加载另一部分数据这样的使用于大数据量的加载
Ajax同步是跳转页面一下子执行了说有的ajax请求加载了所有的数据这样的如果在大量数据中页面会卡
Ajax中有async属性async=”true”是同步flase是异步默认的是异步
(主动说)
webservice是SOA(面向服务编程)的一种实现,
主要是用来实现异构平台通信也就
是不同平台不同项目之间的数据传输,从而避免了信息孤岛的问题,
它之所以能够
进行异构平台通信是因为它是完全基于xml的,
所以说,webService是跨平台,
跨语言,跨框架的,在java中通常有三种技术框架分别是xfire,cxf,axis2。
我们为了保证
webservice的安全性,采用了基于
WS-Security标准的安全验证(使用回调函数)。
(没必要主动说)
webservice的三要素分别是:
wsdl(webservicedescriptionlanguage)
用来描述发布的接口(服务)
soap(simpleobjectaccessprotocol)
uddi用来管理,查询webService的服务3.uddi(查询和管理webservice)
webservice的具体三种实现方式(框架)或者三种实现框架的区别
1.Axis2:可以用多种语言开发,
是一个重量级框架,功能非常强大,
但是它的性能比较低。
2.Xfire:它相比Axis2来说是一个轻量级框架,
它的性能要比Axis2高。
3.cxf:是Xfire的升级版,就好比是,
struts2是webwork的升级,
然后cxf和spring集成起来非常方便,简易,
性能方面也要比Xfire高。
【注】jdk6自带的webservicejws
业务场景
我在以前做项目的时候,其中遇到一个功能,
需要进行两个项目之间的数据的传输,
项目经理让我去完成这个任务,我根据以往的项目经验,
想到两种解决方案,第一种
就是开放另外一个项目的数据库的权限给我,
然后我直接通过访问另外一个项目的数据
库,来得到需要的信息,但后来我分析了下,觉的这种方式不安全,
而且因为当时
这个项目是另外一家公司负责在做,所以数据库里面的表结构,
以及以后牵涉
到的责任问题都很多,所以我就采用了第二种方案,
即通过webservices的方式,进行
异构系统之间数据信息的传递,webservices的具体实现,
有xfire,cxf,axis2,
我根据以往的项目经验,了解到cxf是xfire的升级版本,适用于java语言,
xfire/cxf性能比axis2要高,并且和spring整合起来也比较方便,
而axis2支持更多的语言,
性能相对于cxf要低,通过上面分析,
结合我们目前的两个项目都是基于java
语言的,所以我采用cxf这种方式实现了两个项目之间数据的传递,
webservice的安全性我们采用了基于
WS-Security标准的安全验证(使用CXF回调函数)。
webservice服务端配置流程
首先在web.xml中引入cxfServlet核心类,
指定对以/cxf开头的url路径提供webservice服务,
之后我们在要发布成webservice接口上添加@Webservice注解,
而且还要在实现类上添加同样的webservice注解并且要说明实现了哪个接口,
之后在spring-webservice.xml中发布webservice服务,
需要通过@Test测试此接口方法
通过jaxws:endpoint这个标签,
并且在标签配置implementor和address来表明实现服务的类,
以及发布的地址,
webservice客户端的配置
首先通过wsdl2java根据发布的webservice服务端地址的wsdl
生成客户端调用的中间桥梁java类,
将生成的java类拷贝到客户端项目中,
配置spring-client.xml文件,
通过jaxws:client定义一个bean,
并通过address属性指明要访问的webservice的服务地址,
通过serviceClass指明充当中间桥梁的服务类,之后获取该bean,
就可以通过它来访问发布的webservice接口中的方法。
负载均衡:
(了解)
我们在做这个项目时,考虑到服务器性能的问题,最开始想到使用纵向扩展,来增加硬件的配置提高其性能,但这样做比较耗费资金,而且服务器内存空间也是有限的;所以后来就使用横向扩展来达到这一目的.
(主动说)
当时我们使用nginx(ng个s)+3个tomcat进行负载均衡,在我们不进行负载均衡之前,那所有的请求都由一台tomcat进行处理,这样会使我们的tomcat所承受的压力增大,而我们进行负载均衡之后,同样数量的请求经过nginx将其分发到多台tomcat进行处理,从而降低每台tomcat所承受的压力,而且当其中一台机器宕机时,其他机器还可以继续提供服务,保证服务不间断。
而提示验证码输入错误,后来我就考虑使用ip_hash这种负载均衡策略来代替默认的轮询策略,虽然解决了验证码错误问题,但是在后续的测试中发现如果用户在使用过程中
多台web服务器中实现session共享,这样就解决了上面所说的那些问题。
怎么避免nginx产生单点故障(被动说)
同时我们为了避免nginx的单点故障,达到高可用性,就在nginx的前面又加了一个F5,从而将请求分配给多个nginx,再通过nginx分配给多个不同的Tomcat。这样大大的提高了服务的有效性,并且进一步提高了性能。
1.Linux下常见的分支:
CentOS:服务端【纯开源】
RedHat:服务器端【收费】
Ubantu:个人电脑
2.访问方式:通过SSH/Putty客户端连接服务器
3.如何使用:
1.虚拟机的好处?
可以在虚拟机中随意操作系统,不怕影响或损害电脑;
2.克隆(备份):快速创建当前系统的备份,快速创建另外一个虚拟系统;
在manage下的clone中
linked(链接克隆)软克隆优点:速度快,生成文件小;
full(完整克隆)硬克隆优点:文件大,速度比较慢;
选择桥接模式;
只查出四行pingIp-c4
3.快照:可以将当前的虚拟系统快速还原到某一时刻;都是一个虚拟系统。
快照Snapshot下的TakeSnapshot
快照的好处:埋下几个点,方便还原
4.命令:
注意:
tab键自动补全*代表当前目录下的所有文件
JDK默认安装在usr/java中
设置jdk的环境变量:
修改/etc/profile文件
用文本编辑器打开/etc/profile
在profile文件末尾加入:
exportJAVA_HOME=/usr/java/jdk.1.7.0_79
exportPATH=$JAVA_HOME/binL$PATH
source/etc/profile使修改立即生效
echo$PATH查看PATH值
1.ifconfig:查看IP地址
2.java-version:查jdk的版本
4.rpm-e--nodeps软件的名称:卸载指定的软件
5.rpm-ivh软件名称:安装指定的软件
6.uname-a查看Linux系统的基本信息(计算机名,操作位数,版本号)
7.LL查看文件夹下的文件
8.mkdir创建文件夹
9.vi文件名:对指定的文件名进行编译。
按i进入编辑模式,
按ESC键进入命令模式
:wq!强制保存并退出
:q!强制退出(!是强制的意思)
10.pwd:查看当前目录的完整路径
11.unzip文件名.zip:解压后缀名为zip的压缩文件
zip文件名.zip要压缩的文件
12.mv源文件目标文件名(mv可以移动/重命名)
13.rm-rf文件夹名:递归强制删除文件夹及其下的文件
14.serviceiptablesstop禁用防火墙
15.chmod+x*.sh:使所有的后缀名为sh的文件,拥有可执行的权限
16.在bin目录下./startup.sh启动tomcat
17.在bin目录下通过tail-f../logs/catalina.out来查看启动日志tail-n300../logs/catalina.out查看最后三百行的信息
18.cat文件名:查看整个文件内容
19.ps-ef|grep进程名:查看指定进程是否启动
20.kill-9进程号:强制杀死进程
killall-9进程名
21.find/-name文件名-print:查看指定文件的路径
vi在命令模式下yy复制当前光标所在行
p粘贴
dd删除当前行
vi/etc/sysconfig/iptables更改防火墙的配置文件,开放新的端口号
重启防火墙serviceiptablesrestart
查看当前防火墙的状态serviceiptablesstatus
我们在项目中的关系型数据库采用的是MySQL,考虑到对事务的支持使用的是InnoDB引擎,为了保证数据库数据的安全,达到高可用性,以及分担服务器压力我们对MySQL进行了主从复制的配置并结合MyCat这个数据库中间件进行读写分离。我们项目目前采用的是一主带2或者3从的架构。因为互联网项目一般都是读的多,写的少,所以通过这种一主多从的架构分担了单台数据库的压力并且在一台服务器宕机的情况下也能保证项目的基本运行。
主从复制的配置比较简单,最主要是开启主服务器的二进制日志并指明一个唯一的标识,从服务器也要指明一个唯一的标识,并且在主服务器上创建账号,开启复制权限;在主服务器上运行showmasterstatus查看主服务器的状态,之后在从服务器上用刚才建立的账号连接指定的的主服务器,并指明要复制的二进制文件以及起始位置,最后运行startslave就可以了,然后通常运行showslavestatus查看从服务器的状态,如果slave_io和slave_sql为yes,就证明配置成功了。
最主要就是主服务器上的二进制日志以及从服务器上的IO线程,SQL线程,以及中继日志。主服务器将其自身的改变存入到二进制日志中去,从服务器连接主服务器并通过IO线程读取主服务器上的二进制日志,将读取的内容存入自身的中继日志,之后SQL线程会读取中继日志中的sql语句对其进行执行,这样就保证了从服务和主服务器的一致性。MySQL的主从复制默认是基于sql语句进行的。
60.MyCat概述?
1.需求分析
2.概要设计
3.详细设计(用例图,流程图,类图)
4.数据库设计(powerdesigner)
5.代码开发(编写)
6.单元测试(junit白盒测试)(开发人员)
svn版本管理工具(提交,更新代码,文档)
7.集成测试(黑盒测试,loadrunner(编写测试脚本)(高级测试))
8.上线试运行(用户自己体验)
9.压力测试(loadrunner)
10.正式上线
11.维护
63.多线程
1.java中实现线程的方式
在java中实现线程有两种方式:继承Thread类,实现Runable接口,一个javamain程序默认会开启两个线程一个是主线程,一个垃圾回收线程。
2.线程不安全与安全:
多个线程访问同一个资源,导致结果和期望值不同,我们就说它是非线程安全的(线程不安全),反之我们就说它是线程安全的。
了解:
a.多个线程访问同一个资源(这里的资源通常指的是全局变量或者静态变量),如果每次运行结果和单线程运行的结果是一样的,就是线程安
全的。
b.线程安全问题都是由全局变量及静态变量引起的。
c.若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;
若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
3.线程的状态
1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期
1、线程的实现有两种方式,一是继承Thread类,二是实现Runnable接口,但不管怎样,当我们new了这个对象后,线程就进入了初始
状态;
2、当该对象调用了start()方法,就进入可运行状态;
4、进入运行状态后情况就比较复杂了
4.1、run()方法或main()方法结束后,线程就进入终止状态;
4.2、当线程调用了自身的sleep()方法或其他线程的join()方法,就会进入阻塞状态(该状态既停止当前线程,但并不释放所占有的资
着又让这个进程进入运行状态;
4.4、当线程刚进入可运行状态(注意,还没运行),发现将要调用的资源被synchronized(同步),获取不到锁标记,将会立即进入锁
池状态,等待获取锁标记(这时的锁池里也许已经有了其他线程在等待获取锁标记,这时它们处于队列状态,既先到先得),一旦线程获
4.5、当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的所有资源,与阻塞状态不同),进入这个状态后,是不能自
动唤醒的,必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒(由于notify()只是唤醒一个线程,但我们由不能确定具体唤醒的
是哪一个线程,也许我们需要唤醒的线程不能够被唤醒,因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程),线程被唤醒后
会进入锁池,等待获取锁标记。
补充:(wait和sleep的区别)
4.解决线程安全的问题的方案:
a.通过加锁(synchronized)的方式解决线程安全问题
1.synchronized方法
2.synchronized块(同步代码块)
b.避免使用全局变量
1.为多线程并发的互斥控制提供了另一种全新的解决思路
2.通过ThreadLocal为其他模块的API传递参数
1.减少了创建和销毁线程的次数,
每个线程都可以被重复利用,
可执行多个任务。
2.可以根据系统的承受能力,
调整线程池中线程的数目,
防止因为消耗过多的内存,
而导致服务器宕机
(每个线程需要大约1MB内存,线程开的越多,
消耗的内存也就越大,最后宕机)。
通常我们使用的线程池是实现了ExecutorService的ThreadPoolExecutor。
6.死锁
死锁是因为多线程访问共享资源,由于访问的顺序不当所造成的,通常是一个线程锁定了一个资源A,而又想去锁定资源B;在另一个线程
中,锁定了资源B,而又想去锁定资源A以完成自身的操作,两个线程都想得到对方的资源,而不愿释放自己的资源,造成两个线程都在等
待,而无法执行的情况。
死锁产生的原因:是由访问共享资源顺序不当所造成的.
简单的说:所谓死锁,是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。
7.守护线程
在Java中有两类线程:UserThread(用户线程)、DaemonThread(守护线程)
java创建的线程对象.
用个比较通俗的比如,任何一个守护线程都是整个JVM中所有非守护线程的保姆:
只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM
一同结束工作。
Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是GC(垃圾回收器),它就是一个很称职的守护者。
User和Daemon两者几乎没有区别,唯一的不同之处就在于虚拟机的离开:如果UserThread已经全部退出运行了,只剩下Daemon
Thread存在了,虚拟机也就退出了。因为没有了被守护者,Daemon也就没有工作可做了,也就没有继续运行程序的必要了。
1.AOP是OOP(面向对象编程)的延续,是AspectOrientedProgramming的缩写,意思是面向方面编程或者面向切面编程。AOP是基于代理模式来实现的。(23种设计模式:工厂模式、代理模式、单例模式、适配器模式、责任链模式、装饰模式,模式的应用场景不是很明确,什么场景用什么模式都是可以理解或解释的。一个项目并不是运用的模式越多,则代表项目更强大,反而显得臃肿,复杂度提高了,从而影响代码的效率、开发人员的开发效率,项目的维护成等)
2.AOP主要应用于日志记录,性能统计,安全控制,事务处理等方面。它的主要意图就要将日志记录,性能统计,安全控制等等代码从
核心代码中清楚的划分出来。
3.AOP代理可以通过jdk动态代理实现,也可以通过cglib实现,默认是通过jdk动态代理实现的。jdk动态代理需要接口的支持,如果没有接口只有类,则使用cglib来实现。
jdk基于接口,cglib基于类
所谓代理设计模式:在代理模式中有个接口,接口中有个代理实现和一个真实实现,要用代理实现去代表真实实现。
一个接口,分别有一个真实实现和一个代理实现。静态代理中,真实实现和代理实现都是实现了同一个接口,并且把真实实现作为参数传递给代理实现去调用。
缺点:这种模式的代理类只能为一个接口的对象进行代理,这即是静态代理。要解决这样的问题,可以采用动态代理。
使用一个代理类便可以代理所有接口动态代理,通过代理类的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联,代理实现都需要实现InvocationHandler接口,这个时候我们需要用到Proxy里面的newProxyInstance需要有三个参数1.实现类,2.接口3.当前对象
1.切面(Aspect):由切点(PointCut)和通知(Advice)组成,它既包括横切逻辑的定义,也包括了连接点的定义。
2.切点(Pointcut):一个切点定位多个类中的多个方法。(定义类或者方法的)
3.通知也叫增强(Advice):由方位和横切逻辑构成,所谓的方位指的是前置通知,后置通知,返回后通知,环绕通知,抛出异常后通知
4.连接点(JoinPoint):由切点和方位构成,用来描述在在哪些类的指定方法之前或之后执行
方位:
<1>.前置通知(Beforeadvice):在某连接点(joinpoint)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异
常)。
<2>.返回后通知(Afterreturningadvice):在某连接点(joinpoint)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
<3>.抛出异常后通知(Afterthrowingadvice):在方法抛出异常退出时执行的通知。
<4>后置通知(After(finally)advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
<5>环绕通知(AroundAdvice):包围一个连接点(joinpoint)的通知,如方法调用。这是最强大的一种通知类型。
环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行
文件通常是由一连串的字节或字符构成,组成文件的字节序列称为字节流,组成文件的字符序列称为字符流。Java中根据流的方向可以分为输入流和输出流。输入流是将文件或其它输入设备的数据加载到内存的过程;输出流恰恰相反,是将内存中的数据保存到文件或其他输出设备,详见下图:
文件是由字符或字节构成,那么将文件加载到内存或再将文件输出到文件,需要有输入和输出流的支持,那么在Java语言中又把输入和输出流分为了两个,字节输入和输出流,字符输入和输出流,见下表:
InputStream是字节输入流,InputStream是一个抽象类,所有继承了InputStream的类都是字节输入流,主要了解以下子类即可:
主要方法介绍:
void
abstractint
int
所有继承了Reader都是字符输如流
主要方法介绍
abstractvoid
所有继承了OutputStream都是字节输出流
示例代码:
所有继承了Writer都是字符输出流
Writer
缓冲流主要是为了提高效率而存在的,减少物理读取次数,缓冲流主要有:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter,并且BufferedReader提供了实用方法readLine(),可以直接读取一行,BuffereWriter提供了newLine()可以写换行符。
67.从数组中获取到最大的数据?
方式有很多
(递归)
通过先取出数组中的第一个值然后用for依次循环是数组中的值是否大于第一个值如果大于第一个值取出在用for循环循环以后的值按照这种方式找到数组中最大的值
工作流2.0的定义是:实现工作过程管理的自动化、智能化和整合化。工作流2.0最主要的特征就是可以灵便的实现数据整合和数据统计,消除信息孤岛,既能实现OA办公系统内部工作流之间的数据整合,如借款与报销、预算与决算等,又能实现OA办公系统工作流与其他业务系统之间的数据整合,如HR、ERP、CRM等。工作流2.0能彻底的弥补工作流1.0的不足,它不但实现OA办公系统内部的数据整合,也实现OA办公系统和第三方应用系统之间的数据整合。
如果给工作流1.0打上标签的话,那就是“无纸化、重复工作、流程孤岛、系统孤岛、数据孤岛”;工作流2.0对应的便是“智能化、效率质量提升、外部数据整合、消除信息孤岛、内部数据整合”。毫无疑问,工作流2.0更加智能,更加整合,能够实现数据的同步交换和共享的特征更受用户欢迎,能有效帮助企业简化多余流程,是未来工作流技术发展的方向。
69.
StringBuilder和StringBuffer都是可变字符串,前者线程不安全,后者线程安全。
StringBuilder和StringBuffer的大部分方法均调用父类AbstractStringBuilder的实现。其扩容机制首先是把容量变为原来容量的2倍加2。最大容量是Integer.MAX_VALUE,也就是0x7fffffff。Rr54
因为string是不可变的,所以绝对安全。StringBuilder实际上自身维护一个char[]数组,append是没有synchronized。StringBuffer的append等很多操作都是带有synchronized的,所以同样线程安全。
所以单线程字符串拼接一般采用StringBuilder,效率高。多线程环境则采用Stringbuffer,虽然安全,但是相对效率会低些。
StringBuffer类被final修饰所以不能继承没有子类
2、StringBuffer对象是可变对象,因为父类的value[]char没有被final修饰所以可以进行引用的改变,而且还提供了方法可以修改被引用对象的内容即修改了数组内容。
3、在使用StringBuffer对象的时候尽量指定大小这样会减少扩容的次数,也就是会减少创建字符数组对象的次数和数据复制的次数,当然效率也会提升。存储过程
拦截器:需要门写一个普通类,继承interceptorAdapter,里面定义一个Adapter方法,我们那会儿怎么实现的呢,就是说当用户登陆成功以后,我都会把它登陆后的信息放到session里面,然后我们取的时候可以直接用看session里面有没有信息,如果有证明用户已经登陆了,就让他继续执行,如果没有信息springMVC里面的response.sendredrecte这个方法让它重定向到登陆页面,还需在配置文件里面配置相应的标签,标签里面有两个属性:1,path(就是拦截器需要拦截的路径),然后就是引入咱们的定义的拦截器类,这也就简单实现e4咱们拦截器这样一个功能。
mybatis是持久层它是ORM的一个实现,它是半自动化的框架,相比hibernate它的执行效率更高,它可以直接通过写sql这种方式来操作数据库,并且对sql的优化也比较方便,hibernate呢它是对jdbc的高度封装,所以对sql优化方面比较欠缺,在使用的时候呢,在它的配置文件里面的namespacse与咱们的接口进行匹配,像里面的resultMap(返回值集合)resultType(返回对象)parameterType(参数类型对象)parameterMap(参数集合)
服务端:
1.提供json视图/xml视图
2.提供jsonp方式的数据
3.webservice[服务端]
客户端:
1.ajax【jsonp】
3.webservice[客户端]
webservice用于传统的企业[非互联网企业]【CXF】
SOA[面向服务编程][思想/理念]
webservice[实现方式]
xfire[技术框架]
cxf
axis2【很多公司】【掌握】
解决了信息孤岛的问题
跨语言,跨平台。
webService的三要素
1.wsdl(webservie描述语言):描述发布接口的信息
3.uddi(查询和管理webservice)
cxf:
服务端的配置:
1.在web.xml中通过cxfServlet这个核心类对指定的url进行拦截
2.通过在接口上加入@webservice的注解
3.通过配置spring-cxf-server.xml这个配置文件进行接口的发布
server.xml中发布的接口的addresswsdl。【验证】
客户端的配置:【多种实现方式】【wsdl2java来生成客户端】【导入jar包】