(此题是我的一个朋友今年9月份去华为面试的笔试题,三年真实开发经验,面试的岗位是JAVA开发工程师,答案是我自己附上去的,略有不足,,,)
1.spring实现代理的两种方式是什么,应用场景有哪些?实现原理分别是什么?
jdk动态代理,cglb动态代理
答案:
1。若目标对象实现了若干接口,spring使用JDK的java.lang.reflect.Proxy类代理。
优点:因为有接口,所以使系统更加松耦合
缺点:为每一个目标类创建接口
2。若目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类。
优点:因为代理类与目标类是继承关系,所以不需要有接口的存在。
缺点:因为没有使用接口,所以系统的耦合性没有使用JDK的动态代理好。
总结:1、因为利用JDKProxy生成的代理类实现了接口,所以目标类中所有的方法在代理类中都有。
2、生成的代理类的所有的方法都拦截了目标类的所有的方法。而拦截器中invoke方法的内容正好就是代理类的各个方法的组成体。
3、利用JDKProxy方式必须有接口的存在。
4、invoke方法中的三个参数可以访问目标类的被调用方法的API、被调用方法的参数、被调用方法的返回类型。
cglib动态代理:
1、 CGlib是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
2、 用CGlib生成代理类是目标类的子类。
3、 用CGlib生成 代理类不需要接口
4、 用CGLib生成的代理类重写了父类的各个方法。
5、 拦截器中的intercept方法内容正好就是代理类中的方法体
2.数据库优化怎么实现?
Sql优化与分库分表
答案:1、对语句的优化
①用程序中,保证在实现功能的基础上,尽量减少对数据库的访问次数;
通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担;
②能够分开的操作尽量分开处理,提高每次的响应速度;在数据窗口使用SQL时,尽量把使用的索引放在选择的首列;算法的结构尽量简单;
③在查询时,不要过多地使用通配符如SELECT * FROM T1语句,要用到几列就选择几列如:SELECT COL1,COL2 FROM T1;
④在可能的情况下尽量限制尽量结果集行数如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,因为某些情况下用户是不需要那么多的数据的。
⑤不要在应用中使用数据库游标,游标是非常有用的工具,但比使用常规的、
面向集的SQL语句需要更大的开销;按照特定顺序提取数据的查找。
2、 避免使用不兼容的数据类型。
例如float和int、char和varchar、binary和varbinary是不兼容的。
数据类型的不兼容可能使优化器无法执行一些本来可以进行的优化操作。
3、尽量避免在WHERE子句中对字段进行函数或表达式操作。
若进行函数或表达式操作,将导致引擎放弃使用索引而进行全表扫描。
4、 避免使用!=或<>、IS NULL或IS NOT NULL、IN ,NOT IN等这样的操作符
因为这会使系统无法使用索引,而只能直接搜索表中的数据。
5、 尽量使用数字型字段
一部分开发人员和数据库管理人员喜欢把包含数值信息的字段设计为字符型,这会降低查询和连接的性能,
分库分表:
答案:1,把一个实例中的多个数据库拆分到不同的实例
比如:Mysql节点一中有:订单,用户,促销三个模块
通过拆分,分成:mysql节点一中订单,借点儿中用户,节点三中促销
节点:mysql数据库一主多从的数据库集群(数据一致),所以用节点表示
重新对数据库连接进行配置就行
优点:数据库拆分比较简单,尤其适合没有跨库查询的情况下
缺点:如果写操作主要在订单表,那就分库分表的作用不是很大了
2,一个库中的表分离到不同的数据库中
比如:数据库中有订单,商品,购物车三个表,拆分:每个表给他分一个数据库
3,对一个库中的相关表进行水平拆分到不同实例的数据库中
比如:一个数据库中有一个订单表,拆分数据库1订单表,数据库2订单表;
分库分表三:水平拆分(分片->不同物理节点)
类似分区表(不同:一个节点:数据库),分片很容易出现问题,难以维护,慎重
3.doubbo与doubbox的区别
答案:Dubbo源于阿里的淘宝网开源的分布式的服务架构,致力于提供高性能和透明化的RPC远程服务调用方案,是SOA服务化治理方案的核心框架。淘宝网将其开源之后,得到了很多的拓展和支持(比较出名的有:当当网的扩展版本dubbox,京东的扩展版本jd-hydra等)
Dubbox(即Dubbo eXtensions)是当当网Fork基于dubbo2.x的升级版本,兼容原有的dubbox。其中升级了zookeeper和spring版本,并且支持restfull风格的远程调用。。
版本:
Dubbo目前已停止更新;
Dubbox目前还在更新。
说明:dubbox和dubbo 2.x是兼容的,
没有改变dubbo的任何已有的功能和配置方式(除了升级了Spring之类的版本)。
4.分布式中qz是否存在重复执行问题
答案:存在,
我们先是用了一个临时的解决方案,就是让任务的执行有幂等性。任务是拉去一部分数据到 MySQL 数据库中,那么就在数据库建立一些 Uniqe 索引,后面重复执行的任务放不进去。这样的做法显然会浪费一些资源,但是从结果上看是可以保证正确的,数据肯定不会被重复存储。缺点是每个任务都要考虑到同步的问题,或是类似的唯一索引,或是加锁。
5.数据库数据并发访问:
短是指路径要短:
典型的mvc结构是请求->controller->model->dao->view,然后把页面返回给用户。要想短的话,
1,页面静态化- 用户可以直接获取页面,不用走那么多流程,比较适用于页面不频繁更新。
2,使用缓存- 第一次获取数据从数据库准提取,然后保存在缓存中,以后就可以直接从缓存提取数据。不过需要有机制维持缓存和数据库的一致性。
3,使用储存过程-那些处理一次请求需要多次访问数据库的操作,可以把操作整合到储存过程,这样只要一次数据库访问就可以了。
4,批量读取 - 高并发情况下,可以把多个请求的查询合并到一次进行,以减少数据库的访问次数
5,延迟修改 - 高并发情况下,可以把多次修改请求,先保存在缓存中,然后定时将缓存中的数据保存到数据库中,风险是可能会断电丢失缓存中的数据,
6, 使用索引 - 索引可以看作是特殊的缓存,尽量使用索引就要求where字句中精确的给出索引列的值。
**少是指查询的数据要少:**
1,分表 - 把本来同一张表的内容,可以按照地区,类别等分成多张表,很简单的一个思路,但是要尽量避免分出来的多表关联查询。
2,分离活跃数据 - 例如登录用户业务,注册用户很多,但是活跃的登录用户很少,可以把活跃用户专门保存一张表,查询是先查询活跃表,没有的话再查总表,这也类似与缓存啦。
3, 分块 - 数据库层面的优化,对程序是透明的,查询大数据只用找到相应块就行。
**分流三种:**
1,集群 - 将并发请求分配到不同的服务器上,可以是业务服务器,也可以是数据库服务器。
2,分布式 - 分布式是把单次请求的多项业务逻辑分配到多个服务器上,这样可以同步处理很多逻辑,一般使用与特别复杂的业务请求。
3,CDN - 在域名解析层面的分流,例如将华南地区的用户请求分配到华南的服务器,华中地区的用户请求分配到华中的服务器。
6.Distinct去重查询优化
答案:distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用 它来返回不重复记录的条数,而不是用它来返回不重记录的所有值。其原因是distinct只有用二重循环查询来解决,而这样对于一个数据量非常大的站来说,无疑是会直接影响到效率的。
1.单独的distinct只能放在开头,否则报错,语法错误
2.在count计算不重复的记录的时候能用到
比如SELECT COUNT( DISTINCT player_id ) FROM task;
就是计算talbebname表中id不同的记录有多少条
7.文件上传时,路径问题
答案:在上传文件到服务器上时,上传到服务器的文件不能在指定目录下获取,主要是在java代码中设置的文件路径问题。
获取本地路径的几种方式
1.项目目录下建立excel文件夹存入上传文件
1.1得到当前的classpath的绝对路径的URI表示法。
1.2获得用户的根目录
默认定位到的当前用户目录(“user.dir”)(即工程根目录)
JVM就可以据"user.dir" + “你自己设置的目录” 得到完整的路径(即绝对路径)
但是工程必须不是web项目,不然,这个返回值就不是项目的根目录啦,而是tomcat的bin目录。
8.shiro的组成结构
答案:subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主题进行验证、授权
securityManager:安全管理器,主体进行认证和授权都是通过securityManager进行
authenticator:认证器,主体进行认证最终通过authenticator进行
authorizer:授权器,主体进行授权最终通过zuthorizer进行
sessionManager:web应用中一般是用web容器对session进行管理,shiro也提供一套session管理的方式
sessionDao:通过sessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao
cacheManager:缓存管理器,主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理
realm:域,相当于数据源,通过realm存取认证、授权相关数据
cryptography:密码管理,提供了一套加密/解密的组件,比如提供常用的散列、加/解密等功能
认证执行流程:
认证执行流程
1.通过ini配置文件创建securityManager
2.调用subject.login()方法主体提交认证(token)
3.securityManager进行认证,securityManager最终由ModularRealmAuthenticator进行认证
4.ModularRealmAuthenticator调用IniRealm(给realm传入token)去ini配置文件中查询用户信息
5.IniRealm根据输入的token从shiro.ini查询用户信息,根据账号查询用户信息
如果查询到用户信息,就给ModularRealmAuthenticator返回用户信息
如果查询不到,就给ModularRealmAuthenticator返回null
6.ModularRealmAuthenticator接受IniRealm返回Authentication认证信息
如果返回的认证信息是null,ModularRealmAuthenticator抛出异常
如果返回的认证信息不是null(说明inirealm找到了用户),对IniRealm返回用户密码 (在ini文件中存在)和 token中的密码 进行对比,如果不一致抛出异常
授权执行流程:
1.对subject进行授权,调用方法isPermitted(“permission串”)
2.securityManager执行授权,通过ModularRealmAuthorizer执行授权
3.ModularRealmAuthorizer执行realm(自定义realm)从数据库查询权限数据
调用realm的授权方法:doGetAuthorizationInfo
4、realm从数据库查询权限数据,返回ModularRealmAuthorizer
5、ModularRealmAuthorizer调用PermissionResolver进行权限串比对
6、如果比对后,isPermitted中"permission串"在realm查询到权限数据中,说明用户访问permission串有权限,否则,没有权限,抛出异常。
9.分布式系统中Session跨域问题
答案:
实际上实现Session共享的方案很多,其中一种常用的就是使用Tomcat、Jetty等服务器提供的Session共享功能,将Session的内容统一存储在一个数据库(如MySQL)或缓存(如Redis)中。
10.Jstl标签:
答案:引用标签库:
<%@ taglib prefix=“c”
uri=“http://java.sun.com/jsp/jstl/core” %>
常见:
c:import> 检索一个绝对或相对 URL,然后将其内容暴露给页面