JAVA学习记录
JAVA三种IO理解
BIO,阻塞IO,最常用的Java IO API,提供一般的流的读写功能。
BIO是一种阻塞IO,服务器端使用BIO进行数据读写时,一般都是采用了一个socket请求对应一个Thread 的方式。可采用线程池方案。
NIO,非阻塞IO,在JDK1.4中开始出现,大量应用与服务器端编程,用于提高并发访问的性能,常用的NIO框架有Netty,Mina。
AIO,异步IO,在JDK1.7开始出现。
JAVA中过滤器、拦截器的区别
1.过滤器和拦截器区别:
a.拦截器是基于java的反射机制,过滤器是基于函数回调
b.过滤器依赖于servlet容器,而拦截器不依赖于servlet容器
c.拦截器只能对action请求起作用,而过滤器则几乎对所有请求(包括静态资源)
d.在action的生命周期中,拦截器可以多次被调用,而过滤器则只能在容器初始化时被调用一次
拦截器 :是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。
过滤器:是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet的 action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet的action前统一设置字符集,或者去除掉一些非法字符。
quartz动态调度
CronExpression 语法介绍
CronTrigger 配置完整格式为: [秒] [分] [小时] [日] [月] [周] [年]
-说明- | -是否必填- | -允许范围- | -允许的通配符- |
---|---|---|---|
秒 | 是 | 0-59 | ,- * / |
分 | 是 | 0-59 | ,- * / |
时 | 是 | 0-59 | ,- * / |
日 | 是 | 1-31 | ,- * ? /L W |
月 | 是 | 1-12 或者 JAN-DEC | , - * / |
周 | 是 | 1-7 或者 sum-sat | , - * ? / L # |
年 | 否 | empty 或者 1970-2099 | , - * / |
3.通配符说明
-
表示所有值,例如:在分的字段上设置“”,表示每一分钟都会触发。
-
? 表示不指定值。使用的场景为不需要关心当前设置这个字段的值,例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为“?” 具体设置为 00010* ? - 表示区间。例如 在小时上设置”10-12”,表示10,11,12点都会触发
-
… 表示 指定多个值,例如在周字段上设置”MON,WED,FRI ” 表示周一,周三和周五触发
-
/用于递增触发,如在秒删改你设置”5/15” 表示从 5秒 开始,每增15秒触发(5,30,35,50)。在月字段上设置”1 / 3” 所示每月1号开始,每隔3天触发一次。
-
L 表示最后的意思,在日字段设置上,表示当月的最后一天(依据当前月份,如果是二月还会依据是否是闰年,在周字段上表示星期六,相当于”7”或“SAT”。如果在“L”前加上数字,则表示该数据的最后一个。例如在周字段上设置”6L”这样的格式,则表示“本月最后一个星期五”)
-
W 表示离指定日期的最近那个工作日(周一至周五),例如在日字段上设置“15W”,表示离每月15号最近的那个工作日触发。如果15号正好是周六,则找最近的周五(14号)触发,如果15号是周末,则找最近的下周一(16号触发),如果15号正好在工作日(周一至周五),则就在改天触发,如果指定格式为”1W”,它则表示每月1号往后最近的工作日触发,如果1号正是周六,则将在3号下周一触发。(注: “W” 前只能设置具体的数字,不允许区间”-”).
-
#序号(表示每月的第几个周几),例如在周字段上设置”6#3“表示每月的第三个周六,注意如果指定”#5”,正好第五周没有周六,则不会触发该配置(用在父亲节和母亲节较好)
-
小提示:”L“ 和 “W” 可以一组合使用,如果在日字段上设置”LW”,则表示在本月的最后一个工作日触发;周字段的设置,若使用英文字母是不区分大小写的,即MON与mon相同
-
举例
[秒] [分] [小时] [日] [月] [周] [年]
0 0 12 * * ?每天12点触发
0 15 10 ? * * 每天10点15分触发
0 15 10 * * ? 每天10点15分触发
0 15 10 * * ? * 每天10点15分触发
0 15 10 * * ? 2005 2005年每天10点15分触发
0 * 14 * * ? 每天下午的2点到2点59分每分触发
0 0/5 14 * * ? 每天下午的2点到2点59分(整点开始,每隔5分触发)
0 0/5 14,18 * * ? 每天下午的2点到2点59分,18点到18点59分(整点开始,每隔5分触发)
0 0-5 14 * * ? 每天下午的2点到2点05分每分触发
0 15 10 15 * ? 每月15号的上午10点15分触发
0 15 10 L * ? 每月最后一天的10点15分触发
0 15 10 ?*6L每月最后一周的星期五的10点15分触发
0 1510? 6L 2002-2005从2002年到2005每月最后一周的星期五的10点15分触发
01510? * 6#3每月的第三周的星期五开始chufa
00121/5? 每月的第一个中午开始每隔5天触发一次
011111111? 每年的11月11号11点11分触发
JobDetail
Quartz 在每次执行job时,都重新创建一个Job实例 所以,quartz不是接受一个job实例 ,而是一个Job实现类,在运行时,通过newInstance()的反射调度机制实例化Job。因此,需要通过一个对象来描述Job的实现类及一些静态信息,如Job名称,组名,关联监听器等
Trigger
Trigger 描述触发job执行的时间规则,有SimpleTrigger和 CronTrigger 这两个子类。SimpleTrigger 主要用于触发一次或者固定频率触发;CronTrigger 则可以通过 Cron 表达式定义各种复杂的触发时间,如每周一上午10点执行,每月的最后一个星期日执行,这个跟Linux种的cron 定时任务一样的
Calendar
有时每月的最后一个星期日执行任务,但是如果遇到中秋节,春节就不执行了,这种需求就用到了Calendar 。也就是说 ,从tigger 中排除若干个特殊日期 ,使用的就是Calendar。一个trigger可以和多Calendar 配合使用。
Scheduler
Schedulaer 代表一个Quartz 独立运行的容器 ,Trigger 和JobDetail 可以注册到Scheduler 中,两者在Schedulaer 中拥有各自的组和名称 ,组和名称是在Scheduler中定位一个对象的依据
自定义注解
特性:
1.注解方法不能带有参数;
2.注解方法返回值类型限定为:基本类型、String、Enums、Annotation或者是这些类型的数组;
3.注解方法可以有默认值;
4.注解本身能够包含元注解,元注解被用来注解其它注解。
四种元注解:
- @Documented —— 指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明的类型。如果一种声明使用Documented进行注解,这种类型的注解被作为被标注的程序成员的公共API。
-
@Target——指明该类型的注解可以注解的程序元素的范围。该元注解的取值可以为TYPE,METHOD,CONSTRUCTOR,FIELD等。如果Target元注解没有出现,那么定义的注解可以应用于程序的任何元素。默认ANNOTATION_TYPE。
ElementType:
CONSTRUCTOR:构造器的声明
LOCAL_VARIABLE:局部变量声明
METHOD:方法声明
PACKAGE:包声明 PARAMETER:参数声明
TYPE:类、接口(包括注解类型)或enum声明 -
@Inherited——指明该注解类型被自动继承。如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行知道这个标注类型被找到,或者是查询到顶层的父类。
4.@Retention——指明了该Annotation被保留的时间长短。RetentionPolicy取值为SOURCE,CLASS,RUNTIME。
SOURCE:注解将被编译器丢弃
CLASS:注解在class文件中可用,但会被VM丢弃
RUNTIME:VM将在运行期间保留注解,因此可以通过反射机制读取注解的信息。(常用)
三种内建注解:
- @Override——当我们想要复写父类中的方法时,我们需要使用该注解去告知编译器我们想要复写这个方法。这样一来当父类中的方法移除或者发生更改时编译器将提示错误信息。
- @Deprecated——当我们希望编译器知道某一方法不建议使用时,我们应该使用这个注解。Java在javadoc 中推荐使用该注解,我们应该提供为什么该方法不推荐使用以及替代的方法。
- @SuppressWarnings——这个仅仅是告诉编译器忽略特定的警告信息,例如在泛型中使用原生数据类型。它的保留策略是SOURCE(译者注:在源文件中有效)并且被编译器丢弃。
例子
通过反射获取类上面注解的值
通过反射获取方法上注解的值
shrio学习
Authentication :身份认证/登录,验证用户是不是拥有相应的身份;
Authorization: 授权,即权限验证,验证某个已认证的用户是否拥有某个权限
Session Manager:会话管理,即用户登录后就是一次会话,在用户没有退出账户之前,它的所有信息都在会话中;
Cryptography:加密,保护数据的安全性
Web Support :web支持,可以非常容易的集成到web环境;
Caching:缓存,可用于当用户登录完成后,所属的角色,拥有的权限和资源可存入缓存中,降低数据库的访问压力。
Concurrency: shrio支持多线程并发验证,例如在一个线程中开启另一个线程权限可自动传播。
Testing:提供测试支持
Run As:允许一个用户假装为另一个用户的身份进行访问(他们允许的情况下)
Remember Me:当我第一次登录后,下次再访问的话就不需要登录了。
**Subject:**主体,代表了当前用户,即与当前应用交互的任何东西都是Subject,所有Subject都绑定到SecurityManager上,SecurityManager帮subject完成所有的交互,即SecurityManager是实际的执行者,subject是一个门面。
SecurityManager:安全管理器,它是shrio的核心。所有关于安全的交互都要经过它,它掌管着所有subject。它负责与其他组件交互。我们可以把它当做springMVC里面的dispatchServlet。
Realm:域,也称为安全数据源(DataSource),即SecurityManager验证用户身份,需要从Realm里面获取数据,判断用户是否合法。也需要从realm中获取用户相对应的角色/权限进行验证用户是否能进行操作。
身份认证流程:
- 首先调用 Subject.login(token) 进行登录,其会自动委托给 Security Manager,调用之前必须通过 SecurityUtils.setSecurityManager() 设置;
- SecurityManager 负责真正的身份验证逻辑;它会委托给 Authenticator 进行身份验证;
- Authenticator 才是真正的身份验证者,Shiro API 中核心的身份认证入口点,此处可以自定义插入自己的实现;
- Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证,默认 ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm 身份验证;
- Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息,如果没有返回 / 抛出异常表示身份验证失败了。此处可以配置多个 Realm,将按照相应的顺序及策略进行访问。