1.使用缓存的目的:html
提升应用程序的性能,减小到数据库的访问次数,前端
举个简单应用场景,好比微信群聊,当服务器收到一条消息的时候,须要把消息插入数据库。
最原始的作法,就是每当有一条聊天记录到达服务器的时候,就进行一次数据库的插入操做。若是不考虑服务器带宽,这种状况下数据库的每秒io次数约等于每秒聊天记录插入的次数。
换一种实现思路,用redis作缓存,消息到达服务器的时候,并非马上插入数据库,而是存在redis里。当redis聊天记录到达60条的时候,再执行1次数据库插入操做。
这样子,粗略估计,服务器性能就提升了60倍java
2.缓存的介质(缓存的存储位置)node
内存:临时性存储空间 存取数据快 减小网络通讯量mysql
硬盘:永久性存储空间 存取速度慢jquery
3.缓存的分类linux
客户端缓存:浏览器 cookienginx
服务器缓存:oscache,redis,memcache,session程序员
4.缓存什么样的数据?web
常常访问,又不常常修改的数据
5.缓存的有效性
为了不脏数据的产生,要刷新缓存,这时就用到了事务为了不页面显示问题,须要更新缓存和数据库保证一致性
6.脏数据
若是缓存中的数据和数据库中的数据不一致,那么缓存中的数据就被称之为脏数据
脏读: 一个事务读到另外一个事务未提交的数据
7.刷新缓存的方式
手动刷新:写程序的时候调用指定的代码清除缓存数据
定时刷新:当到达缓存过时时间后,会自动刷新数据
8.缓存的层次(通常咱们将缓存加载service中)
jsp-->action-->service-->dao
缓存越靠前对性能的提升越大
9.缓存的清除策略:(缓存空间不足须要进行清理的时候使用)
LRU:最近最少使用原则.(理解:存储书)
FIFO:先进先出的缓存策略.(理解:排队)
10.何时使用缓存的清除策略?
当缓存中的数据已满,又有新的数据进来时,执行缓存的清除策略
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类充当持久层。Er4
@Resource:默认按照名字注入指定的bean。
@Autowired:默认按照类型进行注入能够结合@Qualifier("bean的的名字 名字")使使其按照名字进行注入。他是 其按照名字进行注入。他是Spring中的注解。
@RespsonceBody:将controller的方法返回的对象经过适当的转换器转换为指定个时候将其输出(一般适用于返回json/xml)
@RequestParam
做用:1.在文件上传时注解 @requestParam 后跟multilpartFile属性
2.接收指定参数名的参数并对方法中的参数赋值而且能够设置默认值
我对Spring MVC的理解和运用。
咱们一般使用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的理解和运用。
SSH整合的流程
在项目中首先是经过在web.xml中配置strtus2的前端控制器filterDispatcher加载struts.xml
配置文件并对指定的后缀名进行拦截,而且经过配置spring的监听器contextLoadListener
加载spring的相关配置文件如
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(Inversion of Control) 控制反转/依赖注入,又称DI(Dependency Injection) (依赖注入)
IOC的做用:产生对象实例,因此它是基于工厂设计模式的
Spring IOC的注入
经过属性进行注入,经过构造函数进行注入,
注入对象数组 注入List集合
注入Map集合 注入Properties类型
Spring IOC 自动绑定模式:
能够设置autowire按如下方式进行绑定
按byType只要类型一致会自动寻找,
按byName自动按属性名称进行自动查找匹配.
AOP 面向方面(切面)编程
AOP是OOP的延续,是Aspect Oriented Programming的缩写,
意思是面向方面(切面)编程。
注:OOP(Object-Oriented Programming ) 面向对象编程
AOP 主要应用于日志记录,性能统计,安全控制,事务处理(项目中使用的)等方面。
Spring中实现AOP技术:
在Spring中能够经过代理模式来实现AOP
代理模式分为
静态代理:一个接口,分别有一个真实实现和一个代理实现。
动态代理:经过代理类的代理,接口和实现类之间能够不直接发生联系,而 能够在运行期(Runtime)实现动态关联。
动态代理有两种实现方式,能够经过jdk的动态代理实现也能够经过cglib
来实现而AOP默认是经过jdk的动态代理来实现的。jdk的动态代理必需要有
接口的支持,而cglib不须要,它是基于类的。
Spring AOP事务的描述:
在spring-common.xml里经过<aop:config>里面先设定一个表达式,设定对service里那些方法 如:对add* ,delete*,update*等开头的方法进行事务拦截。咱们须要配置事务的传播(propagation="REQUIRED")特性,一般把增,删,改之外的操做须要配置成只读事务(read-only="true").只读事务能够提升性能。以后引入tx:advice,在tx:advice引用 transactionManager(事务管理),在事务管理里再引入sessionFactory,sessionFactory注入 dataSource,最后经过<aop:config>引入txAdvice。
Spring实现ioc控制反转描述:
原来须要咱们本身进行bean的建立以及注入,而如今交给
spring容器去完成bean的建立以及注入。
所谓的“控制反转”就是 对象控制权的转移,
从程序代码自己转移到了外部容器。
官方解释:
控制反转即IoC (Inversion of Control),
它把传统上由程序代码直接操控的对象的调用权交给容器,
经过容器来实现对象组件的装配和管理。
所谓的“控制反转”概念就是对组件对象控制权的转移,
从程序代码自己转移到了外部容器。
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【Java Development ToolKit】就是java开发工具箱, JDK是整个JAVA的核内心边包含了jre,它除了包含jre以外还包含了一些javac的工具类,把java源文件编译成class文件,java文件是用来运行这个程序的,除此以外,里边还包含了java源生的API,java.lang.integer在rt的jar包里边【能够在项目中看到】,经过rt这个jar包来调用咱们的这些io流写入写出等
JDK有如下三种版本:
J2SE,standard edition,标准版,是咱们一般用的一个版本
J2EE,enterpsise edtion,企业版,使用这种JDK开发J2EE应用程序
J2ME,micro edtion,主要用于移动设备、嵌入式设备上的java应用程序
Jre【Java Runtime Enviromental】是java运行时环境,那么所谓的java运行时环境,就是为了保证java程序可以运行时,所必备的一基础环境,也就是它只是保证java程序运行的,不能用来开发,而jdk才是用来开发的,全部的Java程序都要在JRE下才能运行。
包括JVM和JAVA核心类库和支持文件。与JDK相比,它不包含开发工具——编译器、调试器和其它工具。
Jre里边包含jvm
Jvm:【Java Virtual Mechinal】由于jre是java运行时环境,java运行靠什么运行,而底层就是依赖于jvm,即java虚拟机,java虚拟机用来加载类文件,java中之因此有跨平台的做用,就是由于咱们的jvm
关系:
J2se是基于jdk和jre,
JDK是整个JAVA的核内心边包含了jre,
Jre里边包含jvm
1.List和Set都是接口,他们都继承于接口Collection,List是一个有序的可重复的集合,而Set的无序的不可重复的集合。Collection是集合的顶层接口,Collections是一个封装了众多关于集合操做的静态方法的工具类,由于构造方法是私有的,因此不能实例化。
2.List接口实现类有ArrayList,LinkedList,Vector。ArrayList和Vector是基于数组实现的,因此查询的时候速度快,而在进行增长和删除的时候速度较慢LinkedList是基于链式存储结构,因此在进行查询的时候速度较慢但在进行增长和删除的时候速度较快。又由于Vector是线程安全的,因此他和ArrayList相比而言,查询效率要低。
我负责项目中的系统管理模块,其中包含用户管理,菜单管理以及给用户赋角色,给角色赋权限;涉及到的表有用户表,角色表,用户角色关联表,菜单表,角色菜单关联表。在菜单管理模块采用ztree进行菜单的增删改查操做,为了将权限控制到按钮级别咱们在进行菜单管理时会设置该菜单是属于按钮级别仍是普通菜单,经过在数据库中增长一个type类型的字段来实现,如type为1则是普通菜单,type为2则是按钮菜单。
这样用户在登陆的时候根据用户名和密码到用户表验证信息是否合法,若是合法则获取用户信息,以后根据用户id再到用户角色关联表中获得相关联的角色id集合,以后根据角色id集合再到角色权限关联表中获取该角色所拥有的权限id集合,而后再根据权限id集合到权限表(菜单表)中获取具体的菜单,展示给当前登陆用户,从而达到不一样用户看到不一样的菜单权限。
为了防止用户不登陆而直接访问后台资源我经过在项目中加入LoginInterceptor拦截器对未经认证的用户进行拦截,若是未经认证则跳转到登陆页面使用户再次登陆,除此以外还加入了PermissionInterceptor拦截器来对用户无权访问的资源进行拦截,若是无访问权限则跳转到没rr4有访问权限的页面。
再者考虑到性能将用户登陆后所拥有的资源权限经过OScache结合单例设计模式将数据存储到了缓存中,这样能够避免每次操做都须要从新进行查询的代价,减小和数据库的交互次数,提升系统性能。考虑到单例的设计模式在多线程中会出现线程安全的问题,因此就给单例加了双重判断锁,从而避免该问题的发生。
共同点:
不一样点
1.get是从服务器上获取数据,post是向服务器传送数据,
2.get传送的数据量较小,不能大于2KB。post传送的数据量较大,通常被默认为不受限制。
3.get安全性很是低,post安全性较高。可是执行效率却比Post方法好。
4.在进行文件上传时只能使用post而不能是get。
5.不明确是post请求的都是get请求
一、从数据共享上
Forword是一个请求的延续,能够共享request的数据
Redirect开启一个新的请求,不能够共享request的数据
二、从地址栏
Forword转发地址栏不发生变化
Redirect转发地址栏发生变化
HTTP是一个超文本传输协议,属于OSI七层模型的应用层,由请求和响应构成,
是一个标准的客户端服务器模型。HTTP是无状态的也就是说同一个客户端的此次请求和上次请求是没有对应关系。
http的工做流程:
当发送一个http请求时,首先客户机和服务器会创建链接,
以后发送请求到服务器,请求中包含了要访问的url地址,请求的方式(get/post),
以及要传递的参数和头信息,服务器接到请求后会进行响应,
包括状态行,状态码,响应头,以及要响应的主体内容。客户端接收
到请求后将其展现到浏览器上而后断开和服务器端的链接。
简单说就是:创建链接--》发送请求--》响应--》断开链接
在HTTP/1.0中,默认使用的是短链接。也就是说,浏览器和服务器每进行一次HTTP操做,就创建一次链接,
但任务结束就中断链接。
从 HTTP/1.1起,默认使用长链接,用以保持链接特性。使用长链接的HTTP协议,会在响应头有加入这行代码:
Connection:keep-alive
在使用长链接的状况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP链接不会关闭,
若是客户端再次访问这个服务器上的网页,会继续使用这一条已经创建的链接。
Keep-Alive不会永久保持链接,它有一个保持时间,能够在不一样的服务器软件(如Apache)中设定这个时间。
实现长链接要客户端和服务端都支持长链接。
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.大大加快数据的检索速度,这也是建立索引的最主要的缘由
建立索引默认排序 若是索引和主键 顺序相同 则不用排序
3.减小磁盘IO(向字典同样能够直接定位)
三、索引的缺点
1.建立索引和维护索引要耗费时间,这种时间随着数据量的增长而增长
2.索引须要占用额外的物理空间
3.当对表中的数据进行增长、删除和修改的时候,
索引也要动态的维护,下降了数据的维护速度
四、索引的分类
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.顺序索引,散列索引,位图索引
首先不考虑查询条件 先写分页语句 在写条件
1.例如:河北省不满18周岁的男的4,5,6条信息
select * from
(select t.* ,rownum rn from
(select id,name, age,sex from t_student where name="河北" and age<18 and sex="男") t
where rownum <= 6)
where rn >=4
2.女生年龄从高到低排序 每页3条 查询第3条
select * from
(select t.*,rownum rn from
(select id,name,age from t_student order by age desc) t
where rownum <= 9)
where rn>=7
第一范式(1NF):强调的是列的原子性,即列不可以再分红其余几列。
第二范式(2NF): 首先是知足第一范式,另外包含两部份内容,一是表必须有一个主键;二是没有包含在主键中的列必须彻底依赖于主键,而不是部分依赖。
第三范式(3NF): 首先知足第二范式,非主键列直接依赖于主键,消除传递依赖。
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查看执行计划
在作XX电商项目的时候,考虑到提升网站前台的性能,承受更大的并发,咱们将网站首页和不少文章页面都进行了静态化。当时采用的方式是经过freemarker模板引擎和spring定时器来结合完成的。前台美工经过网站管理后台用freemarker编写首页模板以及相关的样式,以后将模板信息存入模板表,我负责编写spring定时器在每晚的凌晨从数据库中的模板表中取出各类类型的模板并和相关的数据结合起来生成静态的html页面。而且考虑到减小前台美工编写freemarker标签的难度,我将常常用到的一些功能像分页,列表展现等经过#macro编写为freemarker的宏命令,方便前台美工直接使用。对于及时性要求比较高的特别热门的频道,则在用户点击发布时直接调用编写的接口经过freemarker和数据结合生成html静态页面。
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 次读出来的记录数不同。
mongodb是一个nosql数据库,咱们在项目中一般用它来存储评论信息,
【评论id,商品id,标题,评分,内容,评论人信息,评论的发布时间】
由于每一个商品都会有评论信息,并且某些热门商品的评论信息多是数千条,
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弹出框。
北京市海定区阜外亮甲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标准的安全验证(使用回调函数)。
(不必主动说)
webservice的三要素分别是:
wsdl(webservice description language)
用来描述发布的接口(服务)
soap(simple object access protocol)
是xml和http的结合,是webservice数据通讯的协议
uddi 用来管理,查询webService的服务 3.uddi(查询和管理webservice)
(不必主动说)
webservice的具体三种实现方式(框架)或者三种实现框架的区别
1. Axis2:能够用多种语言开发,
是一个重量级框架,功能很是强大,
可是它的性能比较低。
2. Xfire:它相比Axis2来讲是一个轻量级框架,
它的性能要比Axis2高。
3. cxf:是Xfire的升级版,就比如是,
struts2是webwork的升级,
而后cxf和spring集成起来很是方便,简易,
性能方面也要比Xfire高。
【注】jdk6 自带的webservice jws
(主动说)
业务场景
我在之前作项目的时候,其中遇到一个功能,
须要进行两个项目之间的数据的传输,
项目经理让我去完成这个任务,我根据以往的项目经验,
想到两种解决方案,第一种
就是开放另一个项目的数据库的权限给我,
而后我直接经过访问另一个项目的数据
库,来获得须要的信息,但后来我分析了下,觉的这种方式不安全,
并且由于当时
这个项目是另一家公司负责在作,因此数据库里面的表结构,
以及之后牵涉
到的责任问题都不少,因此我就采用了第二种方案,
即经过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地址?wsdl来验证服务是否发布成功。
(不必主动说)
webservice客户端的配置
首先经过wsdl2java根据发布的webservice服务端地址的wsdl
生成客户端调用的中间桥梁java类,
将生成的java类拷贝到客户端项目中,
配置spring-client.xml文件,
经过jaxws:client定义一个bean,
并经过address属性指明要访问的webservice的服务地址,
经过serviceClass指明充当中间桥梁的服务类,以后获取该bean,
就能够经过它来访问发布的webservice接口中的方法。
负载均衡:
(了解)
咱们在作这个项目时,考虑到服务器性能的问题,最开始想到使用纵向扩展,来增长硬件的配置提升其性能,但这样作比较耗费资金,并且服务器内存空间也是有限的;因此后来就使用横向扩展来达到这一目的.
(主动说)
当时咱们使用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.Linux下常见的分支:
CentOS:服务端【纯开源】
RedHat:服务器端【收费】
Ubantu:我的电脑
2.访问方式:经过SSH/Putty客户端链接服务器
3.如何使用:
1.虚拟机的好处?
能够在虚拟机中随意操做系统,不怕影响或损害电脑;
2.克隆(备份):快速建立当前系统的备份,快速建立另一个虚拟系统;
在manage 下的clone中
linked(连接克隆) 软克隆 优势:速度快,生成文件小;
full(完整克隆) 硬克隆 优势:文件大,速度比较慢;
选择桥接模式;
只查出四行 ping Ip -c 4
3.快照:能够将当前的虚拟系统快速还原到某一时刻;都是一个虚拟系统。
快照 Snapshot 下的 Take Snapshot
快照的好处:埋下几个点,方便还原
4.命令:
注意:
rpm是Linux下一种软件安转包的后缀名。如*。rpm ,等同于windows中的exe.rpm是一个命令,用来进行和软件安装相关的操做。(安转,卸载,查找)
linux下没有盘符的概念,它是经过相关的目录来管理资源的。咱们一般在/home中建立文件夹来存放须要安转的软件
tab键自动补全 *表明当前目录下的全部文件
JDK默认安装在 usr/java中
设置jdk的环境变量:
修改/etc/profile文件
用文本编辑器打开 /etc/profile
在profile文件末尾加入:
export JAVA_HOME = /usr/java/jdk.1.7.0_79
export PATH = $JAVA_HOME/binL$PATH
source /etc/profile 使修改当即生效
echo $PATH 查看PATH值
1.ifconfig:查看IP地址
2.java -version :查jdk的版本
3.rpm -qa | grep 软件的名称 :查找和指定名称相关的软件
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.service iptables stop 禁用防火墙
15.chmod +x *.sh :使全部的后缀名为sh的文件,拥有可执行的权限
16.在bin目录下 ./startup.sh 启动tomcat
17.在bin目录下经过tail -f ../logs/catalina.out 来查看启动日志 tail -n 300 ../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 更改防火墙的配置文件,开放新的端口号
重启防火墙 service iptables restart
查看当前防火墙的状态 service iptables status
export JAVA_HOME = /usr/java/jdk.1.7.0_79
export PATH = $JAVA_HOME/binL$PATH
source /etc/profile 使修改当即生效
echo $PATH 查看PATH值
咱们在项目中的关系型数据库采用的是MySQL,考虑到对事务的支持使用的是InnoDB引擎,为了保证数据库数据的安全,达到高可用性,以及分担服务器压力咱们对MySQL进行了主从复制的配置并结合MyCat这个数据库中间件进行读写分离。咱们项目 目前采用的是一主带2或者3从的架构。由于互联网项目通常都是读的多,写的少,因此经过这种一主多从的架构分担了单台数据库的压力而且在一台服务器宕机的状况下也能保证项目的基本运行。
主从复制的配置比较简单,最主要是开启主服务器的二进制日志并指明一个惟一的标识,从服务器也要指明一个惟一的标识,而且在主服务器上建立帐号,开启复制权限;在主服务器上运行show master status查看主服务器的状态,以后在从服务器上用刚才创建的帐号链接指定的的主服务器,并指明要复制的二进制文件以及起始位置,最后运行start slave就能够了,而后一般运行show slave status查看从服务器的状态,若是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.维护
62.httpClient
httpClient是一个支持http协议的客户端编程工具包,咱们在java中调用httpClient是经过url模拟了一个http请求,这样就能够经过java代码直接发送请求得到服务端响应数据,首先构建HttpClient,new DefaultHttpClient(); httpClient发送请求的方式也分红两种形式:一个 new httpGet(),一个是new httpPost() 把请求的url放进去,而后用excute发送请求,获取响应信息,里面包含状态码,成功为200,包含响应内容,将内容转换为字符串,最后关闭链接,其中post请求是模拟表单提交完成的、不能传递参数
63.多线程
1.java中实现线程的方式
在java中实现线程有两种方式:继承Thread类,实现Runable接口,一个java main程序默认会开启两个线程一个是主线程,一个垃圾回收线程。
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()方法,该线程结束生命周期
了解:
一、线程的实现有两种方式,一是继承Thread类,二是实现Runnable接口,但无论怎样,当咱们new了这个对象后,线程就进入了初始
状态;
二、当该对象调用了start()方法,就进入可运行状态;
三、进入可运行状态后,当该对象被操做系统选中,得到CPU时间片就会进入运行状态;
四、进入运行状态后状况就比较复杂了
4.一、run()方法或main()方法结束后,线程就进入终止状态;
4.二、当线程调用了自身的sleep()方法或其余线程的join()方法,就会进入阻塞状态(该状态既中止当前线程,但并不释放所占有的资
源)。当sleep()结束或join()结束后,该线程进入可运行状态,继续等待OS分配时间片;
4.三、线程调用了yield()方法,意思是放弃当前得到的CPU时间片,回到可运行状态,这时与其余进程处于同等竞争状态,O566S有可能会接
着又让这个进程进入运行状态;
4.四、当线程刚进入可运行状态(注意,还没运行),发现将要调用的资源被synchronized(同步),获取不到锁标记,将会当即进入锁
池状态,等待获取锁标记(这时的锁池里也许已经有了其余线程在等待获取锁标记,这时它们处于队列状态,既先到先得),一旦线程获
得锁标记后,就转入可运行状态,等待OS分配CPU时间片;
4.五、当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的全部资源,与阻塞状态不一样),进入这个状态后,是不能自
动唤醒的,必须依靠其余线程调用notify()或notifyAll()方法才能被唤醒(因为notify()只是唤醒一个线程,但咱们由不能肯定具体唤醒的
是哪个线程,也许咱们须要唤醒的线程不可以被唤醒,所以在实际使用时,通常都用notifyAll()方法,唤醒有所线程),线程被唤醒后
会进入锁池,等待获取锁标记。
补充:(wait和sleep的区别)
wait时会释放锁资源但sleep不会释放锁资源,wait一般和notify以及notifyAll结合使用,须要notify或者notifyAll对其进行唤醒,sleep一般在指定的时间内自动唤醒。
4.解决线程安全的问题的方案:
a.经过加锁(synchronized)的方式解决线程安全问题
1.synchronized 方法
2.synchronized 块(同步代码块)
b.避免使用全局变量
c.使用ThreadLocal(参考:http://blog.csdn.net/drifterj/article/details/7782706)
1. 为多线程并发的互斥控制提供了另外一种全新的解决思路
2. 经过ThreadLocal为其余模块的API传递参数
5.java线程池 (可参考:http://www.oschina.net/question/565065_86540)
1.减小了建立和销毁线程的次数,
每一个线程均可以被重复利用,
可执行多个任务。
2.能够根据系统的承受能力,
调整线程池中线程的数目,
防止由于消耗过多的内存,
而致使服务器宕机
(每一个线程须要大约1MB内存,线程开的越多,
消耗的内存也就越大,最后宕机)。
一般咱们使用的线程池是实现了ExecutorService的ThreadPoolExecutor。
6.死锁
死锁是由于多线程访问共享资源,因为访问的顺序不当所形成的,一般是一个线程锁定了一个资源A,而又想去锁定资源B;在另外一个线程
中,锁定了资源B,而又想去锁定资源A以完成自身的操做,两个线程都想获得对方的资源,而不肯释放本身的资源,形成两个线程都在等
待,而没法执行的状况。
死锁产生的缘由:是由访问共享资源顺序不当所形成的.
简单的说:所谓死锁,是指两个或两个以上的线程在执行过程当中,因争夺资源而形成的一种互相等待的现象,若无外力做用,它们都将没法推动下去。
7.守护线程
在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)
java建立的线程对象.
用个比较通俗的好比,任何一个守护线程都是整个JVM中全部非守护线程的保姆:
只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就所有工做;只有当最后一个非守护线程结束时,守护线程随着JVM
一同结束工做。
Daemon的做用是为其余线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器),它就是一个很称职的守护者。
User和Daemon二者几乎没有区别,惟一的不一样之处就在于虚拟机的离开:若是 User Thread已经所有退出运行了,只剩下Daemon
Thread存在了,虚拟机也就退出了。 由于没有了被守护者,Daemon也就没有工做可作了,也就没有继续运行程序的必要了。
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)的通知,如方法调用。这是最强大的一种通知类型。
环绕通知能够在方法调用先后完成自定义的行为。它也会选择是否继续执行链接点或直接返回它们本身的返回值或抛出异常来结束执行
文件一般是由一连串的字节或字符构成,组成文件的字节序列称为字节流,组成文件的字符序列称为字符流。Java中根据流的方向能够分为输入流和输出流。输入流是将文件或其它输入设备的数据加载到内存的过程;输出流偏偏相反,是将内存中的数据保存到文件或其余输出设备,详见下图:
文件是由字符或字节构成,那么将文件加载到内存或再将文件输出到文件,须要有输入和输出流的支持,那么在Java语言中又把输入和输出流分为了两个,字节输入和输出流,字符输入和输出流,见下表:
InputStream是字节输入流,InputStream是一个抽象类,全部继承了InputStream的类都是字节输入流,主要了解如下子类便可:
主要方法介绍:
void |
close() |
abstract int |
read() |
int |
read(byte[] b) |
int |
read(byte[] b, int off, int len) |
全部继承了Reader都是字符输如流
主要方法介绍
abstract void |
close() |
int |
read() |
int |
read(char[] cbuf) |
abstract int |
read(char[] cbuf, int off, int len) |
全部继承了OutputStream都是字节输出流
主要方法介绍
void |
close() |
void |
flush() |
void |
write(byte[] b) |
void |
write(byte[] b, int off, int len) |
abstract void |
write(int b) |
示例代码:
全部继承了Writer都是字符输出流
主要方法介绍
Writer |
append(char c) |
abstract void |
close() |
abstract void |
flush() |
void |
write(char[] cbuf) |
abstract void |
write(char[] cbuf, int off, int len) |
void |
write(int c) |
void |
write(String str) |
void |
write(String str, int off, int len) |
缓冲流主要是为了提升效率而存在的,减小物理读取次数,缓冲流主要有: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.
JVM -- java virtual machine
JVM就是咱们常说的java虚拟机,它是整个java实现跨平台的 最核心的部分,全部的java程序会首先被编译为.class的类文件,这种类文件可 以在虚拟机上执行,也就是说class并不直接与机器的操做系统相对应,而是通过虚拟机间接与操做系统交互,由虚拟机将程序解 释给本地系统执行。
JVM 是 Java 平台的基础,和实际的机器同样,它也有本身的指令集,而且在运行 时操做不一样的内存区域。 JVM 经过抽象操做系统和 CPU 结构,提供了一种与平台无关的代码执行方法,即与特殊的实现方 法、主机硬件、主机操做系统无关。可是在一些小的方面, JVM 的实现也是互不相同的,好比垃圾回收 算法,线程调度算法(可能不一样 OS 有不一样的实现)。
JVM 的主要工做是解释本身的指令集(即字节码)到 CPU 的指令集或 OS 的系统调用,保护用户免被恶意程序骚扰。 JVM 对上层的 Java 源文件是不关心的,它关注的只是由源文件生成的类文件( class file )。类文件的 组成包括 JVM 指令集,符号表以及一些补助信息。
JRE -- java runtime environment
JRE是指java运行环境。光有JVM还不能成class的 执行,由于在解释class的时候JVM须要调用解释所须要的类库lib。 在JDK的安装目 录里你能够找到jre目录,里面有两个文件夹bin和lib,在 这里能够认为bin里的就是jvm,lib中则是jvm工 做所须要的类库,而jvm和 lib和起来就称为jre。因此,在你写完java程序编译成.class以后,你能够把这个.class文件 和jre一块儿打包发给朋友,这样你的朋友就 能够运行你写程序了。(jre里有运行.class的java.exe)
JRE 是 Sun 公司发布的一个更大的系统,它里面就有一个 JVM 。 JRE 就与具体的 CPU 结构和操做系统有关,咱们从 Sun 下载 JRE 的时候就看到了不一样的各类版本。同 JVM 一块儿组成 JRE 的还有一些 API (如 awt , swing 等)。 JRE 是运行 Java 程序必不可少的。
JRE ( Java Runtime Environment ),是运行 Java 程序必不可少的(除非用其余一些编译环境编译成.exe可执行文件……),JRE的 地位就象一台PC机同样,咱们写好的Win32应用程序须要操做系统帮 咱们运行,一样的,咱们编写的Java程序也必需要JRE才能运行。
JRE里面有一个 JVM , JRE 与具体的 CPU 结构和操做系统有关,咱们从 Sun 下载 JRE 的时候就看到了不一样的各类版本,,同 JVM 一块儿组成 JRE 的还有 一些 API (如 awt , swing 等), JRE 是 运行 Java 程序必不可少的.
JDK -- java development kit
JDK是java开发工具包,基本上每一个学java的人都会先在机器 上装一个JDK,那他都包含哪几部分呢?让咱们看一下JDK的安装目录。在目录下面有 六个文件夹、一个src类库源码压缩包、和其余几个声明文件。其中,真正在运行java时起做用的 是如下四个文件夹:bin、include、lib、 jre。如今咱们能够看出这样一个关系,JDK包含JRE,而JRE包 含JVM。
bin:最主要的是编译器(javac.exe)
include:java和JVM交互用的头文件
lib:类库
jre:java运行环境
(注意:这里的bin、lib文件夹和jre里的bin、lib是 不一样的)总的来讲JDK是用于java程序的开发,而jre则 是只能运行class而没有编译的功能。
eclipse、idea等 其余IDE有本身的编译器而不是用JDK bin目录中自带的,因此在安装时你会发现他们只要求你 选中jre路径就ok了。
三者联系
Java 喊出的带有标志性的口号“ Write Once , Run Anywhere (一次编写,处处运行)”,正是创建在 JRE 的基础之上。何以实现?就是在 Java 应用程序和操做系统之间增长了一虚拟层—— JRE 。
程序源代码不是直 接编译、连接成机器代码,而是先转化到字节码( bytecode ) 这种特殊的中间形式,字节码再转换成机器码或系统调用。前者是传统的编译方法,生成的机器代码就不可避免地跟特殊的操做系统和特殊的机器结构相关。
而 Java 程序的字节码文件能够放到任意装有 JRE 的计算机运行,再由不一样 JRE 的将它们转化成相应的机器代码,这就实现了 Java 程序的可移植性。这样程序员也不用去 关心程序运行的具体环境,而能够专心编写软件。这种分层抽象、隐藏细节的思想在计算机科学中到处可见,好比机器组织结构的设计、网络协议的实现等。 Pascal 语言的发明者 Niklaus Wirth ,就富有预见性地指出应该有这样一种可移植的语言,其生成的中间代码能够在一台假想的机器( a hypothetical machine )上运行。
而 Java 虚拟机( Java virtual machine 或 JVM )就是这样的一台机器,它模拟实际处理器的结构,解释字节码。 怎么一会说是 JRE ,一下子又成了 JVM ,二者是否同物不一样名? 回答是否认的。
JRE的地位就象一台PC机同样,咱们写好的Win32应用程序须要操做系统帮 咱们运行,一样的,咱们编写的Java程序也必需要JRE才能运行。
要运行Applet,在客户端必须安装有 JRE,即“运行时”,容易一点理解,就象所谓的“插件”,要开发JAVA应用程序\Web应用,就必须在服务器端安装相应的 JVM+JDK 了(开发应用 Java web应用 时,客户端不须要安装任何的JVM)
若是你使用JAVA开发应用,就须要安装 JRE+JDK,就是 J2SE.
若是在客户端运行Applet,客户端浏览器必须嵌有JAVA JVM,若是没有,就须要安装,即: 在客户端建立JRE(运行时,包含JVM),而客户端是不须要作开发的,因此,JDK就没有必要安装 了。
不一样版本的Applet在不一样的JVM下可能没法正常运行,而Microsoft JVM只是Sun JVM的“低版本”,微软在windows xp/2003中干脆将JVM去掉了.
StringBuilder和StringBuffer都是可变字符串,前者线程不安全,后者线程安全。
StringBuilder和StringBuffer的大部分方法均调用父类AbstractStringBuilder的实现。其扩容机制首先是把容量变为原来容量的2倍加2。最大容量是Integer.MAX_VALUE,也就是0x7fffffff。Rr54
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(就是拦截器须要拦截的路径),而后就是引入我们的定义的拦截器类,这也就简单实现e4我们拦截器这样一个功能。
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