1、接口不能继承抽象类;接口可以继承接口;抽象类可以实现接口;
- 接口里的方法是不能有方法身体的,但抽象类的方法是可以有方法体的,继承后,在这一点上就会产生矛盾. 抽象类的方法体无法存在了呀;所以接口不能继承抽象类;
- 接口是可以被接口继承的;即通过关键字extends声明一个接口是另一个接口的子接口。由于接口中的方法和常量都是public,子接口将继承父接口中的全部方法和常量。
- 抽象类可以实现接口,当一个类声明实现一个接口而没有实现接口中所有的方法,那么这个必须是抽象类,即abstract类。
2、shiro权限过滤配置不拦截;
<!-- Shiro权限过滤过滤器定义 -->
<bean name="shiroFilterChainDefinitions" class="java.lang.String">
<constructor-arg>
<value>
/static/** = anon
/portal/** = anon
/userfiles/** = anon
${adminPath}/uploadThemePicture = anon
${adminPath}/sys/systemConfig/clearCache = anon
${adminPath}/mms/account/mmsMaterialAccount/mmscountJsonP = anon
<!-- MMS stack -->
${adminPath}/mms/inlib/mmsStackManage/stationData = anon
<!-- MMS cang -->
${adminPath}/mms/inlib/mmsStackManage/mmStackManageJsonP = anon
${adminPath}/**/content = anon
${adminPath}/**/saveContentFile = anon
${adminPath}/**/deleteTempFile = anon
${adminPath}/** = user
/act/rest/service/editor/** = perms[act:model:edit]
/act/rest/service/model/** = perms[act:model:edit]
/act/rest/service/** = user
/ReportServer/** = user
</value>
</constructor-arg>
</bean>
遇到的问题是:A系统通过httpClient跨域调用了B系统中的接口,结果调用失败,就是因为没有在A系统中放行接口的url;shiro进行了拦截;
3、restful:表现层状态转移;即用URL定位资源,用HTTP动词(GET,POST,DELETE,DETC)描述操作。
restful中的几种请求方式如何看是否安全(脏读、幻读、不可重复读)和
幂等(多次操作成功的条件下,是否会对数据库造成不好的影响)?
post(insert)不安全不幂等;
get(select)安全且幂等;
- get:查询,安全且幂等;查找朋友,uri: test.cn/v1/friends
- post:新增,不安全且不幂等;增加一个朋友,uri: test.cn/v1/friends
- put:更新,不安全且幂等;修改一个朋友,uri: test.cn/v1/friends
- delete:删除,不安全且幂等;删除一个朋友,uri: test.cn/v1/friends
4、cors(跨域资源共享)可解决跨域问题;
- 跨域:域名不同/端口不同/协议不同;
- ajax同源策略:请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同;
- 其他解决方案:jsonp;httpclient;nginx;
5、悲观锁
- 解释:悲观的认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改;
- 实例:关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁;synchronized、Lock就是悲观锁的实现;
- 使用场景:适合写操作多的情况,先加锁可以保证写操作时数据正确;
6、乐观锁
- 解释:乐观的认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重试);
- 实现:版本号机制或者CAS算法(Compare and Swap,比较与交换,是一种无锁算法);《cas使得乐观锁不锁定资源也可以实现线程同步》
- 实例:java.util.concurrent包;
- 使用场景:适合读操作多的情况,不加锁可以提高读操作的性能;
7、二叉查找树(Binary Search Tree)
- 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 任意节点的左、右子树也分别为二叉查找树;
- 没有键值相等的节点(no duplicate nodes);
8、2-3查找树(2-3 Search Tree)
- 对于2节点,该节点保存一个key及对应value,以及两个指向左右节点的节点,左节点也是一个2-3节点,所有的值都比key有效,有节点也是一个2-3节点,所有的值比key要大。
- 对于3节点,该节点保存两个key及对应value,以及三个指向左中右的节点。左节点也是一个2-3节点,所有的值均比两个key中的最小的key还要小;中间节点也是一个2-3节点,中间节点的key值在两个跟节点key值之间;右节点也是一个2-3节点,节点的所有key值比两个key中的最大的key还要大。
- 如果中序遍历2-3查找树,就可以得到排好序的序列。在一个完全平衡的2-3查找树中,根节点到每一个为空节点的距离都相同。
9、StringUtils.isNumeric(str);//判断字符串是否全部为数字,返回boolean,如果是空字符串,返回true;
10、通过String类的format函数实现保留两位小数:String.format("%.2f", d);
11、//json对象/json数组对象,多次经过json序列化后仍然是json,不可以向需要转换成json的map中放入json的字符串,否则他就是一个字符串了,不是json数据了!
JSONArray jsonArray = JSON.parseArray(treeData);//把从中间表中查询出来的json字符串转换成json数组对象
hashMapHeader.put("data", jsonArray);//把json对象放到data健对应的值中(hashMapHeader需要转为json格式)
12、oracle中存储大文本数据
- 在oracle中用clob类型表示大文本类型(mysql中用text);
- oracle中,如果一个列的类型为varchar2,那么它不能直接转换为clob类型;
- 通常像图片、文件、音乐等信息就用BLOB字段来存储,先将文件转为二进制再存储进去;而像文章或者是较长的文字,就用CLOB存储;
- 导出表的时候,若表结构中有blob、clob字段,则不能导出为sql语句,只能导出为dmp文件;
13、类的修饰符只有public、abstract、final;
如果不写的话,默认为包访问权限,也就是同一个包的其他类可以访问该类;
他的子类肯定可以访问他,因为如果不在一个包中,都不能继承他;
14、关于事物的注解
- @Transactional 注解应该只被应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
- 注解不会被继承,所以建议把注解用到具体的类以及方法上,而不是用在接口以及方法声明上;
- xml中配置annotation-driven使得注解生效;并且需要配置id为transactionManager的bean;
15、mysql分页用limit关键字;
- Limit m,n语句:参数m是起始下标,它从0开始;参数n是返回的记录数。
16、oracle借助于rownum进行分页;
- Rownum表示一条记录的行号,值得注意的是它在获取每一行后才赋予.因此,想指定rownum的区间来取得分页数据在一层查询语句中是无法做到的,要分页还要进行一次查询;
//最内层的查询SELECT * FROM TABLE_NAME表示不进行翻页的原始查询语句。
//ROWNUM <= 40和RN >= 21控制分页查询的每页的范围---效率高
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
WHERE ROWNUM <= 40
)
WHERE RN >= 21
//在查询的最外层控制分页的最小值和最大值---效率低
SELECT * FROM
(
SELECT A.*, ROWNUM RN
FROM (SELECT * FROM TABLE_NAME) A
)
WHERE RN BETWEEN 21 AND 40
/**这是由于CBO优化模式下,Oracle可以将外层的查询条件推到内层查询中,以提高内层查询的
执行效率。对于第一个查询语句,第二层的查询条件WHERE ROWNUM <= 40就可以被Oracle
推入到内层查询中,这样Oracle查询的结果一旦超过了ROWNUM限制条件,就终止查询将结果
返回了。
而第二个查询语句,由于查询条件BETWEEN 21 AND 40是存在于查询的第三层,而Oracle
无法将第三层的查询条件推到最内层(即使推到最内层也没有意义,因为最内层查询不知道
RN代表什么)。因此,对 于第二个查询语句,Oracle最内层返回给中间层的是所有满足条
件的数据,而中间层返回给最外层的也是所有数据。数据的过滤在最外层完成,显然这个
效率 要比第一个查询低得多。**/
17、一次性的从数据库读取过多的数据,会引起内存溢出的error,上线前数据量小不容易出现这个问题,但是上线后数据量大了可能就有了,所以尽量使用分页查询,这样的话,数据量再多,也只是查询了其中的一部分!
18、如果一次需要查询到的数据量过大的话,需要考虑需求是否合理,
对于千万级数据,应该避免全表扫描;
19、"SQL state [null],error code [17004]无效的列类型"错误的几种情况
a、类型不匹配:
sql片段中#{}中的参数应该加上jdbc的类型:#{student.name,jdbcType=VARCHAR};
注意:MyBatis 插入空值时,需要指定JdbcType,否则报错“无效的列类型: 1111”;
(拼写错误也会报该错误)
b、字段不匹配:
传递到dao的实体中的字段,与mybatis中sql语句不匹配,缺少对应的列,对比检查;
20、token管理机制:
(1)当用户第一次登录后,服务器生成一个token并将此token返回给客户端,客户端保存,发
送请求时带上这个token;服务器验证token,并生成新的token2保存并发给客户端,客户端保存,
发送请求时带上这个token2......
(2)当发客户端发送多个请求,服务器响应请求1验证token1,并生成新的token2时,
请求2正携带token1请求服务器,这样会出错。故可以为token设置一个有效期。
21、