标签:run 虚拟机 轮询 src uniq 文件中 rop cell xhr
二、74--
三、
四、Java内存泄露引起原因
首先,什么是内存泄露?。内存泄露是指不再使用的对象持续占有内存,对象的内存得不到及时释放,从而造成的内存空间的浪费称为内存泄露。内存泄露有时不严重且不易察觉,这样开发者就不知道存在内存泄露,但有时也会很严重,会提示你Out of memory。
1. System.gc(); Runtime.getRuntime().gc() 这两种方法用于显示通知JVM可以进行一次垃圾回收,但垃圾回收机制具体在什么时间运行是无法预知的。
2.finalize() 方法 释放对象所占用的相关资源。
当垃圾回收器将要释放无用对象的内存时,先调用该对象的finalize()方法。如果在程序终止之前垃圾回收器始终没有执行垃圾回收操作,那么垃圾回收器将始终不会调用无用对象的finalize()方法。因为finalize()只有在垃圾回收器工作的时候才会被调用,也就是说,通过它进行资源释放并不能确保马上被释放,甚至可能根本不会被释放(因为垃圾回收器可能不会工作)。程序即使显式调用System.gc()或Runtime.gc()方法,也不能保证垃圾回收操作一定执行,因此不能保证无用对象的finalize()方法一定被调用。
经过以上的描述,我们可以知道字节流与字符流之间主要的区别体现在以下几个方面:
答:不对,有相同的 hash code
这是java语言的定义:
1) 对象相等则hashCode一定相等;
2) hashCode相等对象未必相等
***Set集合中的元素是不能重复的 那用==还是equal判断 他们之间的区别
set中每个对象都是按hashcode存放的,当再次加入一个对象时,先算出该对象的hashcode,再到对应的存放区域寻找是否有相同的hashcode,如果有相同的,再比较equals方法,如果还相同,则不能再次加入该对象。
****list,,set,,map接口的特点
List,Set,Map是否继承自Collection接口?
答:List,Set是,Map不是。
List特点:元素有放入顺序,元素可重复
Map特点:元素按键值对存储,无放入顺序
Set特点:元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的)
hashmap |
线程不安全 |
允许有null的键和值 |
效率高一点、 |
方法不是Synchronize的要提供外同步 |
有containsvalue和containsKey方法 |
HashMap 是Java1.2 引进的Map interface 的一个实现 |
HashMap是Hashtable的轻量级实现 |
hashtable |
线程安全 |
不允许有null的键和值 |
效率稍低、 |
方法是是Synchronize的 |
有contains方法方法 |
、Hashtable 继承于Dictionary 类 |
Hashtable 比HashMap 要旧 |
HTTP是一个超文本传输协议,属于OSI七层模型的应用层,由请求和响应构成,
是一个标准的客户端服务器模型。HTTP是无状态的也就是说同一个客户端的这次请求和上次请求是没有对应关系。
http的工作流程:
当发送一个http请求时,首先客户机和服务器会建立连接,
之后发送请求到服务器,请求中包含了要访问的url地址,请求的方式(get/post),
以及要传递的参数和头信息,服务器接到请求后会进行响应,
包括状态行,状态码,响应头,以及要响应的主体内容。客户端接收
到请求后将其展示到浏览器上然后断开和服务器端的连接。
在数据库中,所谓事务是指一组逻辑操作单元即一组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、索引的缺点
1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加
2.索引需要占用额外的物理空间
3.当对表中的数据进行增加、删除和修改的时候,
索引也要动态的维护,降低了数据的维护速度
4、索引的分类
1.普通索引和唯一性索引
普通索引:CREATE INDEX mycolumn_index ON mytable (myclumn)
唯一性索引:保证在索引列中的全部数据是唯一的
CREATE unique INDEX mycolumn_index ON mytable (myclumn)
2. 单个索引和复合索引
单个索引:对单个字段建立索引
复合索引:又叫组合索引,在索引建立语句中同时包含多个字段名,
最多16个字段
CREATE INDEX name_index ON userInfo(firstname,lastname)
3.顺序索引,散列索引,位图索引
rowid物理位置的唯一标识。
而id是逻辑上的唯一标识,所以rowid查找速度要快于id,是目前最快的
定位一条记录的方式
rowid和rownum都是"伪数列"
所谓“伪数列”也就是默认隐藏的一个数列。
rownum用于标记结果集中结果顺序的一个字段,
它的特点是按顺序标记,而且是连续的,
换句话说就是只有有rownum=1的记录,才可能有rownum=2的记录。
rownum关键字只能和<或者<=直接关联
如果是>或者=则需要给他0起个别名
单例就是该类只能返回一个实例(实例只会创建一次)
单例所具备的特点:
1.私有的构造函数
2.私有的静态的全局变量
3.公共的静态的方法
双重锁定式
public class Singleton {
private Singleton(){};
private static Singleton single;
public static Singleton getInstance(){
if(null ==single){
Synchronized(single){
if(null == single){
single = new Singleton();
}
}
}
return single;
}
}
在创建主键的同时会生成对应的唯一索引,主键在保证数据唯一性的同时不允许为 空,而唯一可以有一个为空数据项,一个表中只能有一个主键,但是一个主键可以 有多个字段,一个表中可以有多个唯一索引。
数据库连接池的优点运行原理:
在我们不使用数据库连接池的时候,每次访问数据库都需要创建连接,
使用完成之后需要释放关闭连接,而这样是很耗费资源的。当我们使用
数据库连接池的时候,在tomcat启动的时候就创建了指定数量的连接,
之后当我们程序使用的时候就直接从连接池里面取,而不需要创建,同理,
当我们使用完的时候也不需要关闭连接,而是将连接返回到连接池中,供
其他请求继续使用。
DBCP:比较稳定。
C3P0: 性能比较高。
Hibernate属于全自动, Ibatis属于半自动,Jdbc属于手动,从开发效率上讲hibernate较高,ibatis居中,jdbc较低,从执行效率上讲hibernate较低,ibatis居中,jdbc较高,因为jdbc是手工写sql语句,程序员对sql的控制能力更大,可以根据业务需要进行优化,而ibatis虽然也可以对sql进行优化,但是他里面将resultset封装为实体的过程中采用了反射机制所以一定程度上影响了性能,而hibernate因为高度封装所以开发效率相对较高,但正因为这个原因,所以程序员在对sql语句的控制和优化方面相对比较弱,而且在将resultset封装成实体的过程中也采用了反射机制,所以在性能方面较低
外键必须加索引。
避免在 where 子句中对有索引的字段进行运算,这会导致索引失效,从而进行全表扫描。
在 where 及 order by 涉及的列上建立索引,要尽量避免全表扫描。
在设计表时要避免表中字段出现null的情况,通常要为其设置默认值。
避免在查找时放弃使用索引而进行全表扫描。
SELECT语句中避免使用‘*’,只查询需要返回的字段 ,这样可以减少oracle解析sql语句的时间。
用NOT EXISTS 替换 NOT IN 操作符,用 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进行优化。
Batch Size是设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小,Batch Size越大和数据库交互的次数就越少,速度就越快, 但也不要无限的大下去,通常选择一个合适的值,如100条;其次我们在进行大批量数据的导入操作时,可以结合batchsize进行分段批量提交,从而达到最优效果。
29.数据库优化?(被动说)
数据库优化:作为开发人员最主要是从sql语句的优化方面考虑的,对于数据库底层的优化,是由DBA完成的。
在我们公司里面做项目的时候,在开发过程中最主要是由程序员对java代码以及sql语句这方面进行优化,至于数据库 底层的优化,则由DBA在项目基本结尾进行压力测试的时候参与进来,通过对数据库的分析,确定影响性能的sql语句以及相关的表,通过和我们进行交流然后对其进行适当的改进。
慢日志就是在我们设置的时间内执行慢的语句可以在慢日志看到!
2.分表:
时间划分 地区划分
水平划分 垂直划分(把平常经常使用的提取出来加上索引)
3.在mysql中通过explain查看执行计划
redis是一个基于key,value的支持多种数据类型(String,List,Set,zSet,Hash)的可进行持久化的内存数据库。我们在项目中通常使用redis来充当缓存服务器来缓存分类列表,品牌列表,热销商品,推荐商品以及该商品的关联商品等等。以前做项目的时候,我们是把商品的信息存放在redis里面,redis支持多种数据类型,有两种方法存储对象:1,可以把对象序列化进行存储,然后反序列化取出。2.用hash结构存储,最后发现,还是用hash存取比较快
当时我们就是在redis中设置maxmemory【最大内存】,把maxmemory-policy【数据清除策略】设置为allkeys-lru。为了保证redis不会因为占用内存过大而导致系统宕机,也会设置最大内存和数据清除策略。使用了jedis作为客户端,并考虑到性能问题使用了jedis连接池。考虑到redis服务器的高可用性,我们做了redis的主从复制,刚开始配置redis的时候,我是关闭它的保护模式,虽然实现了功能,但是不安全,最后是在redis.conf配置文件中绑定具体的ip地址,这样只有该ip地址才能访问redis服务器,并且设置长度为20位左右的密码,从而保证只有进行了密码授权才能进行相关的操作,为了信息安全,我们配置了redis的主从复制,在从服务器的配置文件中通过配置slaveof绑定主服务器的ip地址和端口号,
当设置好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 服务器发送 SUBSCRIBE SENTINEL_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 的 auto discover 的全貌了。
在哨兵的定时程序中,哨兵会向所有的服务器,包括哨兵服务器,发送 PING 心跳,而哨兵收到来自 Redis 服务器的回应后,也会更新相应的时间点或者执行其他操作,哨兵不仅仅凭借自己的信息,还依据其他哨兵提供的信息判断 Redis 服务器是否下线的方法称为客观方法,即通过所有其他哨兵报告的主机在线状态来判定某主机是否下线。
一个 Redis 集群难免遇到主机宕机断电的时候,哨兵如果检测主机被大多数的哨兵判定为下线,就很可能会执行故障修复,重新选出一个主机。一般在 Redis 服务器集群中,只有主机同时肩负读请求和写请求的两个功能,而从机只负责读请求,从机的数据更新都是由之前所提到的主从复制上获取的。因此,当出现意外情况的时候,很有必要新选出一个新的主机。
优选选择优先级高的从机
优先选择主从复制偏移量高的从机,即从机从主机复制的数据越多
优先选择有 runid 的从机
如果上面条件都一样,那么将 runid 按字典顺序排序
并且通过加入哨兵来使redis主服务器宕机时,从服务器自动转换为主服务器继续提供服务。
①加载数据库驱动程序(Class.forName("数据库驱动类");)
②连接数据库(Connection con = DriverManager.getConnection();)
③操作数据库(PreparedStatement stat = con.prepareStatement(sql);stat.executeQuery();)
④关闭数据库,释放连接(con.close();)
悲观锁/乐观锁:
悲观锁(Pessimistic Lock), 每次去查询数据的时候都认为别人会修改,
所以每次在查询数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。
传统的关系型数据库里边就用到了这种锁机制,比如通过select ....for update进行数据锁定。
乐观锁(Optimistic Lock), 每次去查询数据的时候都认为别人不会修改,
所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,
可以使用版本号,时间戳等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。
spring中事务的传播特性好像有5个左右,
我做项目的时候使用最多的就是PROPAGATION_REQUIRED,
它所代表的意思支持当前事务,如果当前没有事务,就新建一个事务。
spring中事务的隔离级别有5个,默认使用的是ISOLATION_DEFAULT,
它代表使用数据库默认的事务隔离级别,也是我们项目中最常使用的。
除此之外还有
读未提交:
它充许另外一个事务可以看到这个事务未提交的数据,
这种隔离级别会产生脏读,不可重复读和幻像读。
读提交:
保证一个事务修改的数据提交后才能被另外一个事务读取,
也是大多数数据库的默认值。可以避免脏读,但会产生不可重复读和幻像读。
重复读:
在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
串行化:
顺序执行事务。除了防止脏读,不可重复读外,还避免了幻像读。
并发性也最低,但最安全。
不可重复读的重点是修改 :
同样的条件 , 你读取过的数据 , 再次读取出来发现值不一样了 。
幻读的重点在于新增或者删除 :
同样的条件 , 第 1 次和第 2 次读出来的记录数不一样
我们在项目中通常用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页,我们的做法是当点击事件发生时,先判断当前
选中的菜单所对应的tab页是否已经存在,如果存在就将其激活选中,否则
再添加新的。多个tab页出现的另一个问题就是不同tab页间的数据可能不
同步,所以我们会在每个tab页上面都增加一个刷新按钮,可以通过点击
该按钮给该tab页所对应的iframe的src属性重新赋值,来起到刷新的作用。
datagrid也是我们在项目中经常使用到的,在使用datagrid时应该注意的是
在拼装好的json数据中,需要有total和rows这两个属性,其中total用来
指明数据的总条数,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弹出框。
北京市海定区阜外亮甲1号中关注联网创意产业园27号楼 (丰台区)
海淀区蓝靛厂 晨月园小区 远大路公交站上车 355/79/118线都能到 坐六站(定慧北桥下车)走大概5分钟就到了
公司附近 在那边有一个丰台科技原生态主题公园
晨月园附近有个巨人学校
从育新坐606路公交到成府路南口下车然后在步行到公司
15K 14K 13K 1000
郑州理工专修学院 计算机科学与技术 刘信古
有,还有,酒店服务管理 建筑工程 行政管理 轨道交通运营 等等。。。
计算机原理 计算机网络 高级语言 编程语言 操作系统 数据结构
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中有一个timeout这个属性设置它的时间是根据秒来设置
Ajax 异步是跳转页面加载一部分数据当点击按钮的时候加载另一部分数据这样的使用于大数据量的加载
Ajax同步 是跳转页面一下子执行了说有的ajax请求加载了所有的数据这样的如果在大量数据中页面会卡
Ajax中有async属性 async =”true”是同步flase是异步 默认的是异步
原生的ajax是xmlhttprequest
(主动说)
webservice是SOA(面向服务编程)的一种实现,
主要是用来实现异构平台通信也就
是不同平台不同项目之间的数据传输,从而避免了信息孤岛的问题,
它之所以能够
进行异构平台通信是因为它是完全基于xml的,
所以说,webService是跨平台,
跨语言,跨框架的,在java中通常有三种技术框架分别是xfire,cxf,axis2。
我们为了保证
webservice的安全性,采用了基于
WS-Security标准的安全验证(使用回调函数)。
负载均衡:
(了解)
我们在做这个项目时,考虑到服务器性能的问题,最开始想到使用纵向扩展,来增加硬件的配置提高其性能,但这样做比较耗费资金,而且服务器内存空间也是有限的;所以后来就使用横向扩展来达到这一目的.
(主动说)
当时我们使用nginx(n g 个 s)+3个tomcat进行负载均衡,在我们不进行负载均衡之前,那所有的请求都由一台tomcat进行处理,这样会使我们的tomcat所承受的压力增大,而我们进行负载均衡之后,同样数量的请求经过nginx将其分发到多台tomcat进行处理,从而降低每台tomcat所承受的压力,而且当其中一台机器宕机时,其他机器还可以继续提供服务,保证服务不间断。
当时项目在部署完成后,遇到这么个问题,用户登录输入验证码的时候,明明验证码输入的正确,但总是提醒说验证码不正确从而不能正常登录,经过分析后发现有可能第一次
请求被发送到t1上,那么放在session中的验证码就被放到了t1上,当用户输入验证码点击登录时,新发送的请求有可能被发送到t2上面,这样在进行对比时就肯定会不一致从
而提示验证码输入错误,后来我就考虑使用ip_hash这种负载均衡策略来代替默认的轮询策略,虽然解决了验证码错误问题,但是在后续的测试中发现如果用户在使用过程中
突然一台服务器宕机了,那么因为session在这台服务器上存储着,所以就会提示用户重新登录,这样使用户的体验度非常不好,最后就通过将session信息保存到redis服务器中从而在
多台web服务器中实现session共享,这样就解决了上面所说的那些问题。
怎么避免nginx产生单点故障(被动说)
同时我们为了避免nginx的单点故障,达到高可用性,就在nginx的前面又加了一个F5,从而将请求分配给多个nginx,再通过nginx分配给多个不同的Tomcat。这样大大的提高了服务的有效性,并且进一步提高了性能。
1.AOP是OOP(面向对象编程)的延续,是Aspect Oriented Programming的缩写,意思是面向方面编程或者面向切面编程。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>.前置通知(Before advice):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异
常)。
<2>.返回后通知(After returning advice):在某连接点(join point)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
<3>.抛出异常后通知(After throwing advice):在方法抛出异常退出时执行的通知。
<4>后置通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
<5>环绕通知(Around Advice):包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。
环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行
StringBuilder和StringBuffer都是可变字符串,前者线程不安全,后者线程安全。
StringBuilder和StringBuffer的大部分方法均调用父类AbstractStringBuilder的实现。其扩容机制首先是把容量变为原来容量的2倍加2。最大容量是Integer.MAX_VALUE,也就是0x7fffffff。
StringBuilder和StringBuffer的默认容量都是16,最好预先估计好字符串的大小避免扩容带来的时间消耗。
因为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.send redrecte这个方法让它重定向到登陆页面,还需在配置文件里面配置相应的标签,标签里面有两个属性:1,path(就是拦截器需要拦截的路径),然后就是引入咱们的定义的拦截器类,这也就简单实现咱们拦截器这样一个功能。
mybatis 是持久层它是ORM的一个实现,它是半自动化的框架,相比hibernate它的执行效率更高,它可以直接通过写sql这种方式来操作数据库,并且对sql的优化也比较方便,hibernate呢它是对jdbc的高度封装,所以对sql优化方面比较欠缺,在使用的时候呢,在它的配置文件里面的namespacse与咱们的接口进行匹配,像里面的resultMap(返回值集合)resultType(返回对象) parameterType(参数类型对象)parameterMap(参数集合)
服务端:
1.提供json视图/xml视图
2.提供jsonp方式的数据
3.webservice[服务端]
客户端:
1.ajax【jsonp】
2.httpclient
3.webservice[客户端]
webservice用于传统的企业[非互联网企业]【CXF】
SOA[面向服务编程][思想/理念]
webservice[实现方式]
xfire[技术框架]
cxf
axis2【很多公司】【掌握】
解决了 信息孤岛 的问题
跨语言,跨平台。
webService的三要素
1.wsdl(webservie描述语言):描述发布接口的信息
2.soap(简单对象访问协议)(webservice使用的协议):http+xml
3.uddi(查询和管理webservice)
cxf:
服务端的配置:
1.在web.xml中通过cxfServlet这个核心类对指定的url进行拦截
2.通过在接口上加入@webservice的注解
3.通过配置spring-cxf-server.xml这个配置文件进行接口的发布
4.在地址栏输入http://ip地址:端口号/项目名/web.xml中配置的servlet的url-pattern/spring-cxf-
server.xml中发布的接口的address?wsdl。【验证】
客户端的配置:【多种实现方式】【wsdl2java来生成客户端】【导入jar包】
1.配置环境变量 path=D:\java\apache-cxf-2.7.18\bin
2.wsdl2java -p 包名 -d 目标路径 服务器生成的接口路径
3.通过spring-cxf-client.xml来配置客户端
4.验证客户端代码以及服务端【单元测试】
简介
之前jsp-->controller-->service-->dao
webservice改变:
服务端:service-->dao
客户端:jsp-->controller-->远程service
httpclient/json视图 改变:
服务端:controller-->service-->dao
客户端:jsp-->controller-->service-->通过httpclient调用远程的json视图
ajax jsonp 改变:
服务端:controller-->service-->dao
客户端:jsp-->ajax jsonp
Maven两个重点:根据Maven的约定由于配置了四个文件的文件名必须是固定的,还有一个loge日志的名字也是固定的,这样不需要去加载这些文件直接通过Maven的约定由于配置自动加载好
还有根据maven的依赖管理在pom.xml中配置jar与这个jar包相关的jar包自动配置好
我当时是怎么配置maven的通过在服务端中setting 中配置这个mirror镜像配置访问nexus的访问路径
这样我们就可以通过pom.xml先到我们的本地去找,如果本地仓库找不到在去maven私服去找如果私服找不到在去外网下载使用maven这样可以提高我们的开发效率与节省了下载带宽,以及jar包的重用性。
@Controller:使其普通的java类充当控制层的作用。
@RequestMapping:有两个参数 url 代表要访问的路径 method请求方式
@Service::使其java类充当service层。
@Repository::使其java类充当持久层。
@Resource:默认按照名字注入指定的bean。
@Autowired:默认按照类型进行注入可以结合@Qualifier("bean的的名字 名字")使使其按照名字进行注入。他是 其按照名字进行注入。他是Spring中的注解。
@RespsonceBody:将controller的方法返回的对象通过适当的转换器转换为指定个时候将其输出(通常适用于返回json/xml)
@RequestParam
作用:1.在文件上传时注解 @requestParam 后跟multilpartFile属性
2.接收指定参数名的参数并对方法中的参数赋值并且可以设置默认值
我们通常使用Spring MVC来充当我们项目中的控制层,我们控制层的作用就是接受前台传递的参数,调用业务逻辑层进行业务处理以及将返回的结果集返回前台进行展示,首先我们要在web.xml中配置Spring MVC的前端总控制器DispatcherServlet并加载Spring MVC的配置文件,我们在Controller层上加上@Controller注解,使其充当控制层,并且要在Spring mvc的配置文件中通过component-scan对Controller层进行扫描从而使类中的@Controller注解生效,Spring mvc用方法来接收参数,所以我们说Spring mvc是基于方法的设计,我们也可以通过@PathVariable从路径中获取信息,我们通常通过@Resource这个注解来进行Bean注入,他是java中的注解,而不是Spring中的,默认是按照属性名进行注入,我们也可以通过设置name属性的值,让其只能按照属性名进行注入,我们也可以用@Autowired注解来进行Bean的注入,他默认是按照类型进行注入,如果要按属性名进行注入我们需要结合@Qualifier注解使其按照名字进行注入,我们可以将返回值的类型改为ModelAndView并在配置文件中配置视图解析器的前缀和后缀,以此来给我们前台页面传递数据,也可以在方法中通过ModelMap进行返回数据。也可以通过@ResponseBody将返回的实体类或者实体类的集合转换为指定的格式进行前台页面交互。并且要在配置文件中进行相关的配置。@RequestMapping是将Url映射到具体的方法上。文件上传时我们通过@RequestParam来接收前台上传的文件。以上就是我对Spring MVC的理解和运用。
过滤器的主要作用
1.任何系统或网站都要判断用户是否登录。
2.网络聊天系统或论坛,功能是过滤非法文字
3.统一解决编码
怎么创建一个过滤器:
1.生成一个普通的class类,实现Filter接口(javax.servlet.Filter;)。
2.重写接口里面的三个方法:init,doFilter,destroy。
3.然后在web.xml配置过滤器。
一、Servlet过滤器的概念:
◆Servlet过滤器是在Java Servlet规范2.3中定义的,它能够对Servlet容器的请求和响应对象进行检查和修改。
◆Servlet过滤器本身并不产生请求和响应对象,它只能提供过滤作用。Servlet过滤器能够在Servlet被调用之前检查Request对象,修改Request Header和Request内容;在Servlet被调用之后检查Response对象,修改Response Header和Response内容。
◆Servlet过滤器负责过滤的Web组件可以是Servlet、JSP或者HTML文件。
二、Servlet过滤器的特点:
◆Servlet过滤器可以检查和修改ServletRequest和ServletResponse对象
◆Servlet过滤器可以被指定和特定的URL关联,只有当客户请求访问该URL时,才会触发过滤器
◆Servlet过滤器可以被串联在一起,形成管道效应,协同修改请求和响应对象
三、Servlet过滤器的作用:
◆查询请求并作出相应的行动。
◆阻塞请求-响应对,使其不能进一步传递。
◆修改请求的头部和数据。用户可以提供自定义的请求。
◆修改响应的头部和数据。用户可以通过提供定制的响应版本实现。
◆与外部资源进行交互。
四、Servlet过滤器的适用场合:
◆认证过滤
◆登录和审核过滤
◆图像转换过滤
◆数据压缩过滤
◆加密过滤
◆令牌过滤
◆资源访问触发事件过滤
◆XSL/T过滤
◆Mime-type过滤
五、Servlet过滤器接口的构成:
所有的Servlet过滤器类都必须实现javax.servlet.Filter接口。这个接口含有3个过滤器类必须实现的方法:
◆init(FilterConfig):
这是Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例后将调用这个方法。在这个方法中可以读取web.xml文件中Servlet过滤器的初始化参数
◆doFilter(ServletRequest,ServletResponse,FilterChain):
这个方法完成实际的过滤操作,当客户请求访问于过滤器关联的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain参数用于访问后续过滤器
◆destroy():
Servlet容器在销毁过滤器实例前调用该方法,这个方法中可以释放Servlet过滤器占用的资源
六、Servlet过滤器的创建步骤:
◆实现javax.servlet.Filter接口
◆实现init方法,读取过滤器的初始化函数
◆实现doFilter方法,完成对请求或过滤的响应
◆调用FilterChain接口对象的doFilter方法,向后续的过滤器传递请求或响应
◆销毁过滤器
七、Servlet过滤器对请求的过滤:
◆Servlet容器创建一个过滤器实例
◆过滤器实例调用init方法,读取过滤器的初始化参数
◆过滤器实例调用doFilter方法,根据初始化参数的值判断该请求是否合法
◆如果该请求不合法则阻塞该请求
◆如果该请求合法则调用chain.doFilter方法将该请求向后续传递
八、Servlet过滤器对响应的过滤:
◆过滤器截获客户端的请求
◆重新封装ServletResponse,在封装后的ServletResponse中提供用户自定义的输出流
◆将请求向后续传递
◆Web组件产生响应
◆从封装后的ServletResponse中获取用户自定义的输出流
◆将响应内容通过用户自定义的输出流写入到缓冲流中
◆在缓冲流中修改响应的内容后清空缓冲流,输出响应内容
九、Servlet过滤器的发布:
◆发布Servlet过滤器时,必须在web.xml文件中加入﹤filter﹥元素和﹤filter-mapping﹥元素。
◆filter元素用来定义一个过滤器:
filter-name 指定过滤器的名字
filter-class 指定过滤器的类名
init-param 为过滤器实例提供初始化参数,可以有多个
◆filter-mapping元素用于将过滤器和URL关联:
十一、Servlet过滤器使用的注意事项
◆由于Filter、FilterConfig、FilterChain都是位于javax.servlet包下,并非HTTP包所特有的,所以其中所用到的请求、响应对象ServletRequest、ServletResponse在使用前都必须先转换成HttpServletRequest、HttpServletResponse再进行下一步操作
过滤器编写完成之后,要在Web工程的web.xml进行配置,格式如下:
<filter>
<filter-name>过滤器名称</filter-name>
<filter-class>过滤器对应的类</filter-class>
<!--初始化参数-->
<init-param>
<param-name>参数名称1</param-name>
<param-value>参数值1</param-value>
</init-param>
<init-param>
<param-name>参数名称2</param-name>
<param-value>参数值2</param-value>
</init-param>
</filter>
优点如下:
缺点如下:
Maven是做什么的,谁能给通俗的介绍一下
在maven的下载网站中应该下载哪个,分别都代表什么
从初学者使用者的角度你可以把他看成可以告别set classpath, javac 这些刀耕火种命令的利器。
作为理解,不太准确的可以说maven主要是用来解决导入java类依赖的jar,编译java项目主要问题。(最早手动导入jar,使用Ant之类的编译java项目)
以pom.xml文件中dependency属性管理依赖的jar包,而jar包包含class文件和一些必要的资源文件。
当然它可以构建项目,管理依赖,生成一些简单的单元测试报告,像现在公司的持续集成都广泛的使用maven,
当你接触一些项目以后你就会有更深的体会。
解决方案二:
比如之前项目导入jar。是通过copy方式导入项目中,而且还会存在jar之间的依赖和冲突。而maven解决了这些问题,只是网速不好的时候有点麻烦。只需要下载-bin.zip就可以了。md5是加密,src是包含了源文件。其他我也不是很清楚=。=
解决方案三:
jar 包管理,防止jar之间依赖起冲突 。小组之间建立个私服务,大家都用通用 的maven配置文件,不用自己手动去下载jar ,pom文件会自动管理下载好的
jar包。
解决方案四:
Maven是基于项目对象模型,可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具。Maven能够很方便的帮你管理项目报告,生成站点,管理JAR文件,等等。例如:项目开发中第三方jar引用的问题,开发过程中合作成员引用的jar版本可能不同,还有可能重复引用相同jar的不同版本,使用maven关联jar就可以配置引用jar的版本,避免冲突。
你给出的图片中binary是二进制文件,source是源码,开发中我们需要下载的是binary文件,后缀标识压缩的算法. 一般来说,windows系统用zip较多,linux系统用tar.gz较多。source是maven项目的源码,探究原理时可以下载源码进行研究。
封装:
首先,属性可用来描述同一类事物的特征, 行为可描述一类事物可做的操作,封装就是要把属于同一类事物的共性(包括属性与行为)归到一个类中,以方便使用.比如人这个东东,可用下面的方式封装:
人{
年龄(属性一)
身高(属性二)
性别(属性三)
做事(行为之一)
走路(行为之二)
说话(行为之三)
}
继承:
由于封装,使得有共同特征的一类事物的所有描述信息都被归于一类之中,但我们知道,这并不是万能的,有些事物有共性,但还存在区别,比如教师,简单封装起来如下:
教师{
年龄(属性一)
身高(属性二)
性别(属性三)
做事(行为之一)
走路(行为之二)
说话(行为之三)
教书(行为之四)
}
上面对"教师"的封装,与对"人"的封装基本上差不多,只是多了一个特征行为:教书,
教师有与人一样的共性, 但我们不能说"人教书",也就是不能把教书封装到"人"之中去,教书是教师的特征行为之一. 为了省事地封装教师(代码的复用,这只是继承存在的原因之一), 可以让教师去继承人,如:
教师 extends 人{
教书(行为之三)
}
这样,我们就不用重新定义那些已经被"人"这一个类所封装的那些属性与行为了,而只需要使用继承的方式,在人的基础上拓展教师专有的行为,即"教书"即可把教师描述出来;这样的结果, 即是教师也同时拥有"人"之中所封装的一切属性与行为, 还拥有自己的特征行为"教书".
多态:
多态的概念发展出来,是以封装和继承为基础的(其实我觉得抽象也应该算是面向对象的大特征之一,要封装,抽象是必须的)
简单的理解一下多态,比如:
人这个类,封装了很多人类共有的特性,
教师是人的子类,继承了人的属性与行为,当然教师有自己的特征行为,比如教书授课;
学生是人的子类,继承了人的属性与行为,当然学生有自己的特征行为,比如学习做作业;
现在,当我们需要去描述教师与学生各自的行为的时候, 我们可以分开来说"教师在授课", "学生做作业", 但如果我们要站在抽象的角度, 也就是从教师与学生的父类"人"的角度, 来同时描述他们各自的行为时,我们怎么描述?"人在授课"?"人在做作业"?这是不是怪怪的很不合适?不合适的问题就在于, 对于行为主体,我们使用了抽象层次的东东"人",而对于行为本身, 我们却使用了具体的东东"授课"与"教书". 怎么解决呢? 那就需要解决抽象与具体的矛盾问题.
既然是站在抽象在角度来描述,那我们把行为抽象一下,不就能同时描述了吗?比如"人在做事"(教师授课与学生做作业都可以说成人在做事),这样就解决了抽象层次与具体层次之间的矛盾.
到了这一步, 我们可以把两个描述: "教师在做事", "学生在做事" 两者统一为"人在做事",
然后, 我们可以在"教师"的"做事"行为中去调用教师自己的特征行为"授课",
在"学生"的"做事"行为中去调用学生自己的特征行为"做作业",
所以,当调用"人"去"做事"的时候,如果这个人是教师,那他所做的事实际上就是"教书",
如果这个人是学生,那他所做的事实际上就是"做作业".
也就是说在这里"人"是多态的, 在不同的形态时,特征行为是不一样的, 这里的"人", 同时有两种形态,一种是教师形态,一种是学生形态,所对应的特征行为分别是"授课"与"做作业".
完成上述的描述过程, 其实就是多态机制的体现.
多态, 就是站在抽象的层面上去实施一个统一的行为,到个体(具体)的层面上时, 这个统一的行为会因为个体(具体)的形态特征而实施自己的特征行为.
多态比起封装与继承来说要复杂很多, 上面的描述很简单, 不用去死抠多态两个字,
其实只要明白:
能站在抽象的角度去描述一件事,
而针对这件抽象的事, 对于每个个体(具体)又能找到其自身的行为去执行, 这就是多态.
那么什么是Java的反射呢?
大家都知道,要让Java程序能够运行,那么就得让Java类要被Java虚拟机加载。Java类如果不被Java虚拟机加载,是不能正常运行的。现在我们运行的所有的程序都是在编译期的时候就已经知道了你所需要的那个类的已经被加载了。
Java的反射机制是在编译并不确定是哪个类被加载了,而是在程序运行的时候才加载、探知、自审。使用在编译期并不知道的类。这样的特点就是反射。
那么Java反射有什么作用呢?
假如我们有两个程序员,一个程序员在写程序的时候,需要使用第二个程序员所写的类,但第二个程序员并没完成他所写的类。那么第一个程序员的代码能否通过编译呢?这是不能通过编译的。利用Java反射的机制,就可以让第一个程序员在没有得到第二个程序员所写的类的时候,来完成自身代码的编译。
Java的反射机制它知道类的基本结构,这种对Java类结构探知的能力,我们称为Java类的“自审”。大家都用过Jcreator和eclipse。当我们构建出一个对象的时候,去调用该对象的方法和属性的时候。一按点,编译工具就会自动的把该对象能够使用的所有的方法和属性全部都列出来,供用户进行选择。这就是利用了Java反射的原理,是对我们创建对象的探知、自审。
Class类
要正确使用Java反射机制就得使用java.lang.Class这个类。它是Java反射机制的起源。当一个类被加载以后,Java虚拟机就会自动产生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方法、成员以及构造方法的声明和定义等信息。
反射API
u反射API用于反应在当前Java虚拟机中的类、接口或者对象信息
u功能
—获取一个对象的类信息.
—获取一个类的访问修饰符、成员、方法、构造方法以及超类的信息.
—检获属于一个接口的常量和方法声明.
—创建一个直到程序运行期间才知道名字的类的实例.
—获取并设置一个对象的成员,甚至这个成员的名字是
在程序运行期间才知道.
—检测一个在运行期间才知道名字的对象的方法
利用Java反射机制我们可以很灵活的对已经加载到Java虚拟机当中的类信息进行检测。当然这种检测在对运行的性能上会有些减弱,所以什么时候使用反射,就要靠业务的需求、大小,以及经验的积累来决定。
反射技术大量用于Java设计模式和框架技术,最常见的设计模式就是工厂模式(Factory)和单例模式(Singleton)。
单例模式(Singleton)
这个模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。在很多操作中,比如建立目录 数据库连接都需要这样的单线程操作。这样做就是为了节省内存空间,保证我们所访问到的都是同一个对象。
使用反射机制的步骤:
u导入java.lang.relfect 包
u遵循三个步骤
第一步是获得你想操作的类的 java.lang.Class 对象
第二步是调用诸如 getDeclaredMethods 的方法
第三步使用 反射API 来操作这些信息
标签:run 虚拟机 轮询 src uniq 文件中 rop cell xhr
原文地址:https://www.cnblogs.com/shan1393/p/9251946.html