java面试复习目录,要面试的小伙伴看过来

Java (4) 2024-09-03 20:23

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
java面试复习目录,要面试的小伙伴看过来,希望能够帮助你!!!。

说项目的时候要联系到技术上来,说技术的时候要联系到项目上来

java面试复习目录,要面试的小伙伴看过来_https://bianchenghao6.com/blog_Java_第1张

更多精彩内容请关注微信“柠檬学园”

第一章:JSP/Servlet

1、Servlet生命周期

当客户端第一次访问一个servlet的时候,服务器判断该servlet对象是否已经创建,如果没有创建,则创建该servlet对象,创建时执行init方法,对servlet执行一些初始化工作,然后准备好ServletRequest和ServletResponse的对象,将其作为参数传给service方法,处理业务后,将结果交给response对象,response对象将信息交给http协议发送到客户端进行解析,当容器停掉或者重启服务器的时候,执行destory方法。

2、JSP的9个内置对象:

request

response

session

application

config

page

exception

out

pageContext

3、四大域对象

PageContext:页面范围。用的较少,范围太小。

ServletRequest:请求范围。用的较多,数据仅存在一次请求中。(需要注意:转发是一次请求)比如:查询记录的结果集

HttpSession:会话范围。用的较多,数据存在一次会话中。比如:购物车、用户登录信息等。

ServletContext:应用范围。用的较少,范围太大,有线程安全问题。注意同步。

4、EL11大隐士对象

pageContext

pageScope

requestScope

sessoinScope

applicationScope

param

paramValues

header

headerValues

cookie

initParam

5、自定义标签的开发步骤

1>、写一个类,继承SimpleTagSupport类;

2>、写一个tld文件,配置标签

3>、在页面上引入标签

6、自定义函数的开发步骤

1>、写一个类,写一个自定义方法,这个方法必须是静态的

2>、在WEB-INF下写配置一个tld文件,对其进行配置

3>、在jsp页面上使用

第二章、Struts2

1、说一说Struts2的优点

Struts2是一个MVC框架,它的作用就是替代我们传统的JSP、Servlet开发,对我们以往开发中出现的重复代码进行了一系列的重构,要说Struts2,首先需要说一下我们以往的开发是怎么个现状,这样才能知道为什么要有Struts2的出现。

以往我们开发web项目的时候,业务层和DAO层我就不说了,WEB层我们用的是MVC框架,这叫做model1,javabean作为数据传输的对象,Servlet作为控制器,jsp负责显示数据。以往的程序运行和处理流程如下:

1>、当客户端访问我们web应用的时候,服务器根据客户端访问的路径到web.xml中去找到url映射,看客户端请求的是哪个servlet,找到这个servlet对象后,进行判断,如果没有初始化则对这个servlet进行初始化,然后判断客户端的请求方式,到底是get还是post,如果是get就调用doGet方法,如果是post方式就调用doPost方式,一个请求我们一般要写一个servlet,如果想要多个请求共用一个servlet,可以在客户端的请求后面带参数,在servlet的doGet或doPost方法中进行判断,然后调用对应的方法。

2>、在对应的处理方法中,我们先通过request对象设置编码格式,然后获取客户端提交过来的参数,对需要转换类型的数据,比如说日期类型,我们需要手工转化这个类型。

3>、处理业务,对处理业务中产生的异常,我们采用trycatch进行捕获,出现异常的时候,我们通过request转发或response重定向到某个错误页面去。

4>、处理完业务后,我们将我们的结果存储到request域中,或者如果是json格式的数据,我们要进行非常复杂的数据转化,然后通过response.getOutputStream.write()方法,将数据输出到浏览器。

以上是我们以往采用jsp/servlet开发系统时的现状,我们可以发现有很大的问题;

第一:一个servlet要处理多个请求非常麻烦,不但要在web.xml文件中进行一堆配置,还需要在servlet的doGet或doPost方法中进行判断请求的是哪个方法;

第二:获取前台页面的参数非常麻烦;

第三:所有的类型转换需要我们程序员来手动转换;

第四:所有的异常都要一一处理,代码重复度很高;

第五:结果集的处理非常麻烦;

这时候,struts2就出来了,它解决了我们上面出现的所有问题,甚至更优秀,struts2有一个核心过滤器,StrutsPreparedAndExecuteFilter,在容器启动的时候,执行该过滤器中的init方法,在该方法中,加载系统的一些配置,包括struts.xml配置文件,在该方法中,它会解析这个配置文件,将文件中action节点的name作为key,class指定的类的对象作为实例存储到一个Map中,当你客户端发送一个请求的时候,它会从这个map里面去找与你请求匹配的key,这样就解决了我们上面说的servlet请求映射的问题。在初始化方法中,还进行了一些常量的初始化,比如字符集统一设置为UTF-8等,常量是支持自定义的,我们可以在struts.xml配置文件中进行配置。包括请求后缀、struts2的模版等。当客户端发送一个请求的时候,首先会经过struts2核心过滤器,核心过滤器根据你的请求,从一个map集合中取出你要访问的对象,生成一个代理对象,紧接着,调用一系列的拦截器,这些拦截器的调用方式采用的是职责链的方式,拦截器是struts2的一个核心功能,struts2默认提供了一堆拦截器,采用拦截器栈的方式进行了配置,主要作用是

1>、对请求参数进行拦截,采用反射技术,将参数的值注入到VO对象中,如果实现了ModelDriven,则会将值注入到ModelDriven的泛型类的对象的属性中去。

2>、对文件上传进行进行统一处理,简化了文件上传功能

3>、对国际化提供支持

4>、对前台的Checkbox数据进行处理

5>、如果配置了声明式验证,则对请求的数据进行校验

等等。

经过一系列的拦截器后,调用客户端请求的action中的方法,在方法中,我们不需要再用request对象去设置编码和获取参数了,struts2框架已经帮我们将值注入了属性中,我们直接拿来用即可。处理完业务流程后,我们将我们的结果交给struts2的结果集来处理,默认struts2提供了10个结果集,比如dispatcher、chain、redirectAction、stream等。

对于异常的处理,在struts2中,可以使用自定义拦截器来实现。对比struts2和我们传统的servlet、jsp的开发,我们可以发现struts2的很多有点和好处,框架的作用就是帮我们简化开发、优化开发流程。

2、Struts2中的值栈

Struts2中的值栈的作用是简化我们获取数据的方式,采用ValueStack+OGNL表达式,实现数据的存取。ValueStack是一个接口,这个接口有一个默认的实现类OgnlValueStack,这个类在运行的时候,有两个很重要的属性,一个是CompondRoot,叫根对象,一个是OgnlContext,Ognl上下文环境,这个OgnlContext里面又包含两个东西,一个是Map集合,一个是CompoundRoot,Map集合里存储了所有Session的集合、request对象的集合等数据,CompoundRoot里存储的东西跟OgnlValueStack里的CompoundRoot存储的是一样的,这个我觉得Struts2设计的有点多余,搞两个一样的东西,不过人家可能觉得为我们提供了方便,但是另一方面,也增加了我们学习时的难度。细节太多了。

通过ActionContext.getContext().getValueStack().push()方法,我们可以将一个对象数据压入栈顶,CompoundRoot继承了ArrayList这个类,对里面的几个方法进行了扩展,所谓栈顶,就是这个集合的第一个元素,通过把数据放到栈顶,在页面或struts2配置文件中,我们可以非常方便的直接获取出来,不需要再用对象.属性的方式来获取了,这是struts2做的很好的一个地方。

3、Struts上传下载

上传

1、页面表单设置enctype=”multipart/form-data”,method=”post”

2、在action中定义三个属性,一个Filephoto,上传文件的文件流;一个StringphotoContentType,这是上传文件的MIME类型;一个是photoFileName,这是上传文件的文件名。

3、在struts.xml中指定上传处理方法即可。

下载

1、在action中定义两个属性,一个InputStream类型的inputStream用于接收下载文件的输入流;一个String类型的fileName属性,存储下载文件时的名称。这个文件名如果是中文名会出现乱码问题,需要先获取iso8859-1的二进制数据再转化成utf-8的编码,然后将文件名存储到request域中

2、获取下载文件的输入流,赋值给inputStream属性

3、定义stream类型的结果集,设置三个参数,第一个参数contentType的值为application/octet-stream;第二个参数inputName的值为inputStream;第三个参数contentDisposition的值为attachment;filename=${#request.fileName};

4、struts2漏洞

在2013年6月底发布的Struts2.3.15版本被曝出存在重要的安全漏洞

1>、可远程执行服务器脚本代码:可以破坏系统让系统无法运行;

2>、重定向漏洞:可以利用其盗取用户密码。

应对方法:升级版本到2.3.15.1即可。

第三章、hibernate

1、实体对象的状态

瞬态:对象刚创建,还没有和session关联

持久化状态:对象跟session关联了

脱管状态:session关闭了

2、检索策略(抓取策略)

hibernate的检索策略分为类级别的检索、关联级别的检索、批量检索三种

类级别的检索:session.load(),默认这个是懒加载一个对象,只有在用的时候才会真正的去加载这个对象。

关联级别的检索:从一的一方检索多的一方,从多的一方检索一的一方,双向检索

3、hibernate处理并发

hibernate中,如果不考虑事务的级别,可能出现脏读、不可重复度,幻读(虚读)和丢失更新的现象。所谓丢失更新,就是后操作的事务覆盖了前面提交的事务的结果。在hibernate中,为了解决丢失更新的现象,可以使用悲观锁和乐观锁,所谓悲观锁,就是认为丢失更新一定会发生,在查询一条数据的时候就对它进行锁定,只有操作完了,别人才能操作,在操作期间,别人哪怕是想查询都不行,在查询对象的时候设置LockOptions.UPGRADE参数即可。所谓乐观锁,通过在数据库添加一个版本号字段,就是我在查询的时候拿到一个版本号,另外一个事务查询的时候也拿到一个版本号,当我进行修改的时候,数据库中的版本号会更改,另外一个事务提交的时候,数据库发现版本号不一致就会报错。在hibernate映射文件中配置一个版本号字段即可。

以上现象如果考虑事务隔离级别的话是不会有问题的,hibernate中默认的事务隔离级别是READCOMMITED,不会造成以上问题。如果需要修改,配置一下即可。

4、hibernate二级缓存

hibernate中的二级缓存是基于sessionFactory级别的缓存,二级缓存分为更新时间戳区、类级别的缓存区、集合级别的缓存区、查询缓存区。

1>.对于类级别的缓存,存放的是对象中散列数据,比如id=1,name=”张三”这样的形式存储。如果配置了hibernate的类级别的缓存,第一次查询出一个对象后,下次就不会到数据库里去查了,直接从二级缓存中取出来用。

2>.对于集合级别的缓存:比如说部门员工的关系,部门的PO对象中引用了员工的Set集合数据,当第一次查询出部门对象的时候,假如说员工都查询出来了,当下次再查询的时候就不需要去数据库里查了,hibernate会直接从二级缓存中取出来。对于集合级别缓存,集合中存储的都是对象的oid,具体的数据都存储在类级别的缓存区中,要用的时候再重新组装数据。当我集合缓存了2条数据,下次我要查3条的时候,hibernate会根据oid判断,如果前面2条数据的oid已经存在集合缓存区里了,就不再去数据库查了,只会去数据库中查询那条没有存在缓存中的数据。

3>.查询缓存区:查询缓存区的原理是以查询的sql语句作为key,查询的结果作为value,存储在一个map集合中,value中存的都是oid,具体的值也存放在类级别的缓存区中。当下次再查询的时候,会从这个map中去查找这个sql语句,如果又是相同的sql语句,则直接从用sql语句作为key从map集合中取出来。否则就去数据库查询。

4>.更新时间戳区:更新时间戳区的作用是更新二级缓存中的数据,当你数据库中的数据发生变化的时候,hibernate会更新二级缓存中的数据。如果是直接从库里改的,是不会更新二级缓存的,只有从前台更改的数据hibernate才会去更新。

第四章、Spring

谈谈你对spring的理解

spring类似于一个大的容器,具有非常强大的整合作用,可以整合市面上绝大部分的j2ee

框架,spring的核心是依赖注入(DI)、控制反转(IOC)和面向切面编程(AOP)。

1>.所谓依赖注入,就是把对象之间的依赖关系交给spring容器来管理,比如说A对象中用到了B对象,那么在初始化A对象的时候,spring容器会将B对象进行实例化同时将B对象注入A对象中的B属性。

2>.所谓控制反转就是将单例对象的创建、初始化和销毁工作交给spring来处理,让spring容器来管理对象的生命周期。

3>.所谓AOP编程就是将业务逻辑代码和非业务逻辑代码分离,每一类非业务逻辑代码(比如事务、日志、权限等)封装成一个独立的切面,当需要对一个目标类中的方法进行事务控制的时候,我们可以通过spring的切面配置和表达式给某些指定的目标类加上事务控制的功能,不需要事务控制的时候,我们卸载事务控制功能,这种AOP的方式做到了非业务逻辑代码的可插拔式编程,不仅有利于团队开发还有利于后期的维护工作。

3>.另外,spring在对数据库的操作方面提供了一整套的JDBC编程模版,利用这套模版,程序员可以非常方便和简单的实现数据库的访问

第五章、mybatis和hibernate的比较

相同点:

资源

hibernate

mybatis

配置文件

hibernate.cfg.xml

sqlMapConfig.xml

实体类

User.java

User.java

实体类映射文件

User.hbm.xml

UserMapper.xml

CRUD操作步骤

1、加载配置文件

2、构建session工厂

3、获取session对象

4、操作数据库获取结果集

5、关闭Session

跟hibernate是一样的

当实体类中的属性和数据库中的字段不对应的时候

可以通过在hbm.xml文件中设置字段和属性的映射关系来解决

可以通过在写sql语句的时候给字段取别名的方式来解决

不同点:

1、hibernate是面向对象的ORM框架,而mybatis是面向结果集的;

2、hibernate的学习难度相对mybatis来说要难一点。

3、性能方面,hibernate每次都是查询所有的字段,虽然可以通过投影查询来查询指定属性,或者通过抓取策略和二级缓存来提高性能,但是想对来说,性能还是差一点,而mybatis都是通过原生态的sql语句来获取结果集的,所以性能肯定要优于hibernate。

4、对于使用hibernate开发,开发人员甚至都不需要非常熟悉sql语言就可以以面向对象的思维去开发程序,但是mybatis需要对sql较为熟练才行。

5、可扩展性:由于hibernate的HQL语句是与数据库无关的,所以在不同数据库之前的迁移是非常方便的,但是mybatis开发的项目一旦需要做数据库迁移,那将是非常大的工作量。

6、两者都有一级缓存和二级缓存,但是mybatis的二级缓存配置想读较为简单。

7、hibernate的dao层开发比mybatis的dao层的开发要快、更简单。

第六章、SpringMVC

浏览器输入请求地址首先经过DispatcherServlet该转发的servlet类的作用是:首先获取响应的请求然后初始化WebApplicationContext上下文,初始化SpringMvc的各个主键然后封装到DispatcherServlet中,DispatcherServlet在根据配置的处理器映射HadlerMapping,HadlerMapping的实现类通过配置文件,把一个URL映射到Controller

类上,再根据注解或配置找到对应的Controller,执行业务逻辑,返回响应所需数据和url等信息,接下来根据配置的ViewResolver找到对应的View,然后构造Response呈递给浏览器。

第七章:前台技术(ajax、jquery)

1、同步和异步的区别

同步:需要等到一个操作完了,才能做另外一个操作

异步:你做一件事情的时候,我可以做另外一件事情

异步的好处:使web开发的项目页面性能提高了,因为不需要像以前一样,如果要更新页面的部分信息需要整个页面提交,再从服务器端下载整个页面;现在有了ajax异步交互,我可以局部刷新,这样不仅减少了带宽、还增加了web应用的反应速度。

类似的异步技术还有iframe框架、flash和javaapplet。

2、ajax的核心对象是javascript的XmlHttpRequest

3、ajax不是一项新技术,而是多种技术的综合,ajax=javascript+xhtml+css+dom+xml+XMLHttpRequest

4、ajax开发的步骤:(以下xhr代表XMLHttpRequest对象)

1>.创建XMLHttpRequest对象:不同的浏览器创建对象的方式不一样

//创建XMLHttpRequest对象是固定写法:背下来

functionajaxFunction(){

varxmlHttp;

try{//Firefox,Opera8.0+,Safari

xmlHttp=newXMLHttpRequest();

}

catch(e){

try{//InternetExplorer

xmlHttp=newActiveXObject("Msxml2.XMLHTTP");

}

catch(e){

try{

xmlHttp=newActiveXObject("Microsoft.XMLHTTP");

}

catch(e){}

}

}

returnxmlHttp;

}

2>.监听服务器状态:xhr.onreadystatechange=function(){}

3>.客户端与服务端建立连接:xhr.open(“get”,”abc.do”)

4>.客户端向服务端发送请求:xhr.send()

不过,现在都用jQuery了,上面这种方式很少用了,用jQuery,写个$.ajax();就可以了。

5、jQuery十个选择器

如果想在面试jQuery的时候没问题,这十大选择器还是必须会的,如果觉得太多了,最少要把属性选择器熟透了。

5.1基本选择器:$(“#mydiv”)、$(“div”)、$(“.myClass”)

5.2.层次选择器:$(“forminput”)表示form表单下的input标签、$(“form>input”)表示form表单下的所有input标签、$(“label+input”)匹配紧接在label标签后的input元素、$(“label~input”)匹配label标签后的所有同辈的input元素

5.3.过滤选择器:该选择器除了属性选择器以外,都以“:”开头。

5.3.1>、基础过滤选择器:$(“tr:first”)查找第一个tr标签、$(“tr:last”)查找最后一个tr标签、$(“input:not(checked)”)匹配没有选中的input框、$(“tr:even”)匹配所有索引为偶数的tr标签、$(“tr:odd”)匹配所有索引为奇数的tr标签、$(“tr:eq(0)”)获取第一个tr标签、$(“tr:gt(3)”)获取索引大于3的所有tr标签、$(“tr:lt(3)”)获取所有索引小于3的tr标签、$(“:header”)匹配所有h1,h2,h3这样的标签、$(“:animated”)匹配所有正在执行动画效果的元素;

5.3.2>、内容过滤选择器:$(“div:contains(‘zengping)”)匹配内容中包含了zengping的所有div元素、$(“div:empty”)匹配所有不包含子元素或者是文本的空元素、$(“div:has(p)”)匹配所有包含了p标签的div元素、$(“div:parent”)匹配所有含有子元素或者文本的元素

5.3.3>、可见度过滤选择器:$(“div:hidden”)获取所有隐藏的div标签、$(“div:visible”)获取所有可见的div标签。

5.3.4>、属性过滤选择器:

$(“div[id]”)匹配所有带id属性的div标签、$(“input[name=’username’]”)匹配所有name属性”username”的input标签、$(“input[name!=’username’]”)匹配所有name属性不为”username”的input标签、$(“input[name^=’us’]”)匹配所有name属性的值以”us”开头的input标签、$(“input[name$=’me’]”)匹配所有name属性的值以”me”结尾的input标签、$(“input[name*=’us’]”)匹配所有name属性的值包含”us”的input标签、$(“input[id]input[name^=’us’]”)匹配所有包含id属性,且name属性的值以”us”开头的input标签;

在过滤器中,属性过滤选择器是重点,只要问jQuery,这里面的东西都是必问的。

5.3.5>、子元素过滤选择器:这个太麻烦,用的也少,就不写了

5.3.6>、表单对象属性过滤器:$(“input:enable”)匹配所有可用的input元素、$(“input:disable”)匹配所有不可用的input元素、$(“input:checked”)匹配所有选中了的单选框或复选框但不包含select标签中选中的option、$(“selectoption:selected”)匹配所有select标签下选中了的option

5.3.7>、表单选择器:$(“:input”)匹配所有的input元素、$(“:text”)匹配所有的text元素、$(“:password”)匹配所有的password元素、$(“:radio”)匹配所有的radio元素、$(“:checkbox”)匹配所有的checkbox元素、$(“:file”)匹配所有file元素。

第八章:数据库

1、oracle数据库

分页语句:

select*

from(selectrownumr,e1.*

from(select*fromemporderbysal)e1

whererownum<=8

)

wherer>=5;

2、mysql数据库

2.1>、explain命令:sql语句的执行查询计划,通过此命令我们可以知道mysql优化器是如何执行sql语句的。命令不给调整建议,但可以帮助我们去做调优决策。

2.2>、当数据库中数据量过大时,有什么方案进行优化?

a、在数据库端,可以进行分库、分表、分区操作。

所谓分库,就是将数据分别存储在多个数据库上,搞几台服务器,每台服务器上的数据库都是一样的表结构,假如A服务器上的A表里存100W条用户数据,超过100W的数据我就存储到B服务器上的B表里,在查询用户数据的时候进行逻辑判断,如果要查询前100W的数据则连接A服务器,要查询后面的数据则连接B服务器。

所谓分表,就是将数据分多张表存储。分表技术有横向分表和纵向分表两种,先说说横向分表,横向分表就是将表中的多条记录分装在多个表里,比如A表存100W,B表存100万条,假如说现在有一个全国人口信息表,有14亿的数据,都存储到一张表里显然是不切实际的,这时候可以考虑分表技术,将人口按省份分表存储,比如原来的人口信息表叫personinfo_c,现在按省份来存储,我们需要针对每个省份建一张表,湖南省的人口信息存储到personinfo_hunan_c,北京市的人口信息存储到personinfo_beijing_c。这种做法,每个表存储在硬盘上的文件是不一样的,当新增人口信息的时候要进行逻辑判断,判断是哪个地方的人就存储到哪个表里去。所谓纵向分表,就是将A表中的几个字段放到一个表中,A表中的另外几个字段放到另外的一个表中,这种情况发生在当一个表中有些字段查询多,有些字段执行新增次数多的情况下。

所谓分区,就是将一张表分成多个区,比如说新浪的新闻信息都存储在一张表里,有上亿的数据,如果不分表或者分区的话,每次查询都是灾难性的,查一条数据可能得好几天才能查出来,我们可以将新闻数据按天进行分区,这样每一天的数据都会存储在硬盘上不同的文件里,查询起来会比较快,跟分表是一样的原理,只不过分区的话所有的数据还是在一个表里,分表的话就是两张表了。

b、建立索引

建立索引的好处是避免每次都进行全表扫描,当表中数据过多时,进行全表扫描是非常耗时的,建立索引有助于提升查询性能。

mysql的索引分为普通索引、唯一索引、主键索引(当给一个表建立主键时,默认就给这个表的这个字段建立了主键索引了)和组合索引四种。

什么时候使用索引呢?一般来说,在WHERE和JOIN中出现的列需要建立索引,但也不完全如此,MySQL只对<、<=、=、>、>=、BETWEEN、IN、LIKE才会使用索引。比如我的sql语句为:SELECTNAME,AGE,ADDRESSFROMUSERSWEHRENAME=’ZHANGSAN’ANDADDRESSLIKE‘bei%’,在这条语句中,由于where后面使用了name和address作为查询过滤条件,这时候,我们就可以给这两个列增加索引了。

索引的缺点:索引能够提高查询性能,但是降低了更新和删除的性能,再一个就是索引占用了磁盘空间。

使用索引的经验:

1、使用短索引(局部索引),比如说你要查询一个全世界的地理信息表,addressname字段有255的长度,但是前面的一个字符已经可以获取你的信息了,比如我要查询所有中国的地区,这时候,我like‘中%’就行了,不需要like’中华人民共和国%’,这时候我这个addressname的字段在建立索引的时候,就不需要整列都设置索引,设置前1个字符索引就行了。

2、like语句操作:尽量避免使用like,如果非要使用,不要用like‘%aaa%’的方式,而要用like‘aaa%’,因为前者不会使用索引,后者会使用到索引。

3、不要在索引列上进行计算,因为索引列上进行计算将会进行全表扫描。比如upper(name),这样写就会影响性能了。

4、优化orderby语句:SELECT[column1],[column2],....FROM[TABLE]WHERE

[columnX]=[value]ORDERBY[sort]LIMIT[offset],[LIMIT];对于上面的sql语句,最高效的方法是建立一个联合索引[columnX,sort]

c、SQL语句优化的分析方法

1、设置慢查询日志:设置一些语句,如果查询的结果在多长时间之后才出来就把它记录到一个文件中,这样我们查看这个文件时,就知道哪些sql语句性能不行了。

2、利用maatkit工具分析sql

3、使用explain、show_status、showvariables来总和分析sql语句

4、尽量避免在查询语句的where条件后面使用or来连接条件,否则将导致引擎(InnoDB或MyISAM)放弃使用索引而使用全表扫描

如果非得有or这样的关键字,可以换个方式写,比如:

selectname,agefromuserswhereid=10orid=20可以改成:

selectname,agefromuserswhereid=10

unionall

selectname,agefromuserswhereid=20;

5、尽量不要使用子查询,用表连接查询替代,一般情况下,表连接要比子查询要快。

6、Join的优化:如果你的程序中有很多join查询,你应该确认两个表中的join字段是被建过索引的。这样,mysql内部会启动为你优化join的sql语句的机制。而且这些被用来join的字段,应该是类型相同的。

7、exists代替in

8、尽量简化sql语句,比如selectcol,valfromtablewherecol=’a’,这个语句中,这个col就是多余的,后面的条件中已经指定了col=’a’了,所以,在应用中直接拿’a’做col这一列的值就可以了,不需要再从数据库中去查询了。

d、利用主从复制+读写分离来提高数据库的并发负载能力。

读写分离:将读取较为频繁的数据放到一台服务器上,将写操作较为频繁的数据放到另一台服务器上,两台服务器做集群和负载均衡,一台机器的数据更新时会同步到另外一台机器,实现数据的同步,这样能极大提升数据库整体性能。

主从复制:这个是如何复制的呢?一般分为三步?

1>.master将改变记录到二进制日志中

2>.slave将master的日志拷贝到它的中继日志

3>.slave重做中继日志中的事件,将改变反应到它自己的数据。

第九章:MongoDB

非关系型数据库中的一种,非关系型数据库特点特点是非关系型、分布式、水平可扩张的,以key-value的形式存储,主要用途用于大数据的处理,查询过程中,没有了sql语句,减少了数据库解析sql的环节,提升了系统性能。

Mongodb:是菲关系型数据库中最类似关系型数据库的数据库。

特点:

1. 支持强大而复杂的查询

2. 能建立索引,类似于RDBMS的属性索引支持,您可以直接在文档的选定属性上创建索引使用提示、解释计划和分析的查询优化特性

3.是一个面向集合、模式自由的文档型数据库

4.面向集合

集合的概念:类似于关系型数据库中表的概念,称为Collection

5.模式自由

我们不需要再集合中做各种约束,在关系型数据库中如果一个表定义完成以后,那么字段的名称、类型、约束都定义好了。在该数据库中,不需要提前给集合定义类型等。而是动态添加的。

6.文档型

我们存储的数据是键值对的集合,值可以是数据类型集合中的任意类型,包括数组和文档。

7.支持查询

8.支持复制和故障恢复,类似于MySQL的主/从复制

9.使用高效的二进制存储包括大型对象,使用GridFS的大文件存储

10.支持处理碎片和云计算层次的扩展性

11.支持大部分语言提供了相应的驱动程序

13.MongoDB查询结果存储在提供过滤、聚合和排序等一系列功能的游标中,包括limit()、skip()、sort()、count()、distinct()和group()。

14.高级聚合的map/reduce实现

15.基于集合的对象存储,在需要规范化数据时允许参考查询

16.通过自动分片功能水平扩展

17.高性能无争用并发机制的即时更新

第十章:JBPM工作流

你用过工作流啊?是啊

说一说工作流

嗯,我们项目中有个货运管理模块,一个合同信息登记完毕后,要交给公司法务部进行审核,法务部审核完毕后需要交给公司老总看,后期可能还有其他人员会看,考虑到这个业务流程是可能会变化的,为了提高系统后期的可扩展性,我们采用了JBPM工作流技术,这个目前成熟的版本是4.4,所以我们系统也采用的这个版本。这块工作是我开发的,由于之前没学习过工作流技术,所以花了一个多礼拜时间学习了一下,对工作流的常用API进行了了解、表结构进行了了解,然后做了几个小Demo,然后后来就整合到我们项目中来了。我们项目用到了spring框架,所以对于工作流的整合只需要将工作流的核心对象ProcessEngine对象交给spring容器来管理就可以了。然后需要根据具体业务设计流程图,然后将设计后的jpdl.xml文件和png图片利用RepositoryService对象的deploy方法将这两个文件部署起来,实际上是将这两个文件存到了数据库中去了。然后在销售专责填写好合同信息,选择好需要处理合同的法务办的工作人员,并提交合同时,后台调用ExecutionService的startProcessInstanceByKey方法启动工作流,这时候,可以在启动时,通过流程变量存储下一个任务的办理人。

当法务办工作人员登录后,我们弄了个弹框效果,提示当前登录用户有哪些待办事项,当法务办工作人员点击这个需要处理的任务信息后,直接进入到合同审批页面,如果法务办人员审核通过,流程流转到部门经理进行处理,这里我们还使用啦向下跳一步的操作(比如说副经理不在这时提交到部门经理处的任务就无法被完成。从而进行下一步。而这时我们采用啦+++),在此我们还使用啦 decision 节点进行啦判断,(比如说合同的涉及到的金额不是很大。恩5W一下的 部门经理就可以直接批。如果大于5W此时就需要交给总经理审批啦。)总经理处理完毕后流程结束,如果不同意,流程直接结束(流程结束可以是中间的任何一步操作不同意此时流程强制终止。如果全部同意此时流程将走到最后?最后又是怎么判断流程结束呢?这里只须判断最后那个活动有没有Transition,没有则结束啦)。

流程到最后我们使用的是fork/join(分和合活动节点)进行控制的,一边是货物已经到啦卖家手里。。而另一边卖家的剩余的钱已经打到公司账户。此时流程结束。或者说这个买卖结束啦。可以将其视为历史数据

对于销售专责,它是可以动态的看到合同的审批进程的,每次销售专责登录后,进入到合同报审的页面,能够看到每个合同的审核结果,点击一个合同后面的流程进度查询,可以在流程图上看到具体的进度,这里我们是通过获取流程图中每个节点的坐标,通过来控制一个层的位置覆盖到当前处理的节点上,这样就能够让当前处理的节点显示高亮效果。

第十一章:WebService

1、webservice是个什么东西?webservice就是实现远程调用的一种技术,它可以实现跨平台、跨语言的调用,比如常见的天气预报信息调用、手机号码归属地查询等。

2、WSDL是什么:webservicedescriptionlanguage,web服务描述语言,它是描述webservice的一个xml文件,通过这个文件,我们可以知道这个webservice服务的调用地址、方法名称、方法需要传递的参数、方法的返回值等信息。

3、SOAP是什么:simpleobjectaccessprotocal,简单对象访问协议,它是作为一个基于xml格式的协议,用于在网络上传输数据。底层是基于http协议的,可以这么理解:soap=http+xml,而http协议的底层又是基于TCP/IP协议的。soap现有两个版本1.1和1.2。

4、SOAP的组成如下:

Envelope–必须的部分。以XML的根元素出现。

Headers–可选的。

Body–必须的。在body部分,包含要执行的服务器的方法。和发送到服务器的数据。

5、第一种:调用webserivce的四种方式

1>.利用wsimport命令生成客户端调用的java代码

2>.利用HttpUrlConnection对象,手工拼接soap协议报文,向服务器发送请求获取数据。

3>.通过ajax调用js+xml跨域请求,这个浏览器是不支持的,但是我们可以绕过去

4>.通过Service客户端编程

第二种:cxf提供的类发布webservice

1.ServerFactoryBean

2.JaxWsServerFactoryBean

3.通过配置文件发布(Spring)

客户端:

4:ClientProxyFactoryBean调用

调用原则:ServerFactoryBean---ClientProxyFactoryBean

5:JaxwsProxyFactoryBean调用

调用原则:JaxWsServerFactoryBean-----JaxwsProxyFactoryBean

6:wsdl2java生成本地代码调用

7:通过配置的文件的方式调用

8:通过jquery调用

第十二章:成都杰信贸易综合管理系统

面试题:说一下你最近做的一个系统。

最近我们开发的一套系统是给成都杰信贸易有限公司公司开发的,这家公司主要从事纺织服装进出口贸易,是一家加工生产及销售为一体的服装公司,最近几年业务做到海外去了,随着他们公司业务的不断壮大,原来那套系统已经没办法满足他们的发展需要了,所以他们公司领导就想搞一套物流系统,提高他们的办公效率。整个系统有仓储管理(包括:采购单、仓库、货物、条形码、入库、出库、退货、盘点、库存、库存上限报警、统计查询)、展会管理(包括:展会管理、出单管理)、货运全流程管理,包括购销合同、出货表月统计、出口报运、装箱单、海运委托单、发票、财务统计、决策分析(包括:成本分析图、销售情况统计、重点客户、经营情况同期比对统计、工作绩效等)这么些功能。我在这个项目中,负责货运管理部分模块的开发以及决策分析报表的开发。

货运管理模块里,我负责开发合同管理、报运管理、装箱管理、生产厂家模块。这三个模块之间是紧密联系的,所谓合同管理就是对成都杰信贸易公司所有的合同进行CRUD的操作、合同下的货物管理、货物下的附件管理。在这个模块里,最复杂的地方是需要理清合同、货物、附件、生产厂家之间的关系以及货物信息的导出处理。一个合同包含多个货物,一个货物可以有多个附件,一个生产厂家可以生产多个货物,所以合同跟货物之间是一对多的关系,货物跟附件是一对多的关系,生产厂家跟货物之间是一对多的关系。理清了这一层关系后,开发起来就简单了。

在我们物流项目中,有很多的设计技巧和开发亮点,比如说:

1、在操作货物信息和附件信息的时候,在合同列表中,为了方便用户录入货物信息,我们在每条合同信息后面,加了一个货物的超链接,点击货物的超链接,可以进入货物信息管理页面,对货物进行CRUD操作,由于货物信息每次录入的比较多,为了方便用户快速录入,每次录入一条货物信息后,我们还是跳转到该货物信息录入界面,同时,了解到用户每次录入货物信息的时候都是一次性录入多个厂家的多个信息,所以我们在跳到该页面的时候,进行了生产厂家等信息的回显,这样极大的提高了用户操作效率。

2、在录入附件信息的时候,用户以往的系统是点击一条合同信息进入到该合同对应的货物列表页面,再点击货物列表中的一个超链接进入到附件列表页面,当用户想直接录入附件信息的时候,需要点几次才能到达附件页面,所以我们在设计这个的时候,直接在合同列表页面加了一个附件按钮,点击这个超链接直接进入到附件录入页面,在这个录入页面,给用户提供一个货物信息的下拉框进行选择,这样又方便了用户的附件信息的录入了。

3、在合同管理界面,我们提供了合同的批量复制功能。

4、在导出出货表的时候,为了避免多线程安全问题,后下载的文件覆盖前下载的文件,我们采用了按照时间点自动分目录的方式,文件名采用UUID算法命名。

5、当系统上线时间长了,系统的历史合同数据、历史货物信息、历史附件信息数据越来越多,严重影响了系统性能,我们对系统提供了历史数据归档功能,当用户点击归档按钮的时候,将每年数百万的历史数据导出到excel文件中,同时移动数据到历史表中。

6、在生产厂家信息维护界面,为了方便用户录入,我们采用了自定义的一个js控件进行了批量新增和批量修改,这样加快了用户操作的速度。

7、系统上线后,出现了很多性能问题,反应速度不是很快,用户不太满意,为此,我们做了一个系统性能的分析,利用struts2的拦截器,在拦截器中,对所有用户访问的哪个类的哪个方法、方法执行消耗的时间等进行记录,并存储到数据库中,然后用amFlash技术做性能分析报表,找到系统的性能瓶颈,然后针对性的进行优化,两个礼拜后,我们对系统的性能报告进行分析,发现,用户主要访问的模块在上午8:30-9:30,主要访问的模块是货物信息录入、查询以及附件信息的录入查询,因为这个点是上班时间点,而且录入货物信息和附件信息较多,所以,针对这几个方法,我们采取了以下优化策略:

1>、利用hibernate抓取策略进行优化,尽量减少增加、和查询的sql语句;

2>、报表查询时,采用原生态的sql语句,不用hibernate的hql语句,使用Spring的JdbcTemplate模版,为此,我们单独又写了一个spring配置文件,这个配置文件的作用是配置数据库连接池和给JdbcTemplate模版注入属性,对于加载Spring配置文件的这个类,我们采用单例设计模式,避免多次创建对象实例,做到了性能最优和线程安全。

3>、对数据字典进行二级缓存的配置,避免多次与数据库的交互。

8、在这个项目中,我们还用到了JBPM工作流技术,在合同录入完毕后,需要成都杰信贸易公司的法务部进行审核,然后提交到总经理进行审核,这是一个典型的工作流程。

9、导出出货表的技术我们使用了POI并且用模板技术实现分页功能,能够导出图文并茂的出货表,还能够对商品价格进行自动计算,不需要购买第三方报表,给用户省去了买报表的钱,得到了用户的肯定。

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

发表回复