实习记录
公司项目源码学习
鉴权模块
思路
- 验证token
核心也是根据token进行验证,如果是debug模式则跳过验证,如果不是映射到方法也直接跳过验证。若是则判断是否有Authorization注解,其中Authorization是一个自定义注解,使用此注解会在访问方法时验证token。若返回值为空则直接跳过验证。接下来就是从request中取出token判断是否为空,不为空则与数据库中的用户信息进行比较继续后续的验证。若用户存在则在redis中更新token和超时时间。
-
判断是否是映射到方法 :instanceof
java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。
项目中是传入一个Object类的handler,判断它是否是HandlerMethod的一个实例,即如果不是映射到方法的就直接通过验证
-
判断是否有注解的方法:findAnnotation 原理是可以通过findAnnotation方法查找指定类在指定方法中的上下文引用情况,返回值为空则没有使用。
LocalDateTime
简介
LocalDateTime是java.time包是由Joda的作者进行操刀,在Java8新引入的日期操作API。旧版本的Date类有线程不安全等弊端,同时若不进行封装,在每次使用时特别麻烦,新版本的java.time包线程安全、简易、高可靠,数据库也支持LocalDateTime类型,存储也很方便。总共包括三个相关的时间类型:LocalDateTime年月日十分秒;LocalDate日期;LocalTime时间;三个包的方法都差不多。
使用过程中遇到的坑
- SpringBoot项目中,用@DateTimeFormat对类成员变量进行注解时,要加上(pattern = "yyyy-MM-dd HH:mm:ss")
- 对于LocalDateTime类型,注解里面的时分秒不能省略,前端也必须传进来,传的时候必须是双位数!如果没有,就要用00:00:00表示
- LocalDate 类型的注解也可以加上时分秒,但是年月日后面的不会被接收和显示。
LocalDateTime转为Date
LocalDateTime now = LocalDateTime.now() //获取当前时间
ZoneId zoneid = ZoneId.systemDefault(); //获取当前系统所在的时区
ZoneDateTime zoneDateTime = now.atZone(zoneid);// 获取该时间点在该时区上的时间日期信息
ZonedDateTime zonedDateTime = now.atZone(zoneId);
Date newDate = Date.form(zonedDateTime); //
Date转为LocalDateTime
Date date = new Date(); Instant instant = date.toInstant(); oneId zoneId = ZoneId.systemDefault();关于时间加减LocalDateTime提供了plus和minus的各种方法,需要的时候根据提示找对应的API即可。
时间格式化
LocalDateTime now = LocalDateTime.now(); DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:ss:mm"); String format = df.format(now);
字符串解析
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:ss:mm"); LocalDateTime date = LocalDateTime.from(df.parse("2017-10-11 22:22:22"));
@ApiParam
简介
@Apiparam 顾名思义,是注解api的参数,也就是用于swagger提供开发者文档,文档中生成的注释内容
hidden = true 用于隐藏请求参数
其他swagger注解
常用注解:
- @Api()用于类; 表示标识这个类是swagger的资源
- @ApiOperation()用于方法; 表示一个http请求的操作
- @ApiParam()用于方法,参数,字段说明; 表示对参数的添加元数据(说明或是否必填等)
- @ApiModel()用于类 表示对类进行说明,用于参数用实体类接收
- @ApiModelProperty()用于方法,字段 表示对model属性的说明或者数据操作更改
- @ApiIgnore()用于类,方法,方法参数 表示这个方法或者类被忽略
- @ApiImplicitParam() 用于方法 表示单独的请求参数
- @ApiImplicitParams() 用于方法,包含多个 @ApiImplicitParam
自定义注解
元注解
元注解是指注解的注解,包括@Retention @Target @Document @Interface四种
@Retention和@Target注解
- @Retention 定义注解的保留策略 @Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含 @Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得, @Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解。
- @Target注解 定义注解的作用目标
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
@Target(ElementType.TYPE) //接口、类、枚举、注解 @Target(ElementType.FIELD) //字段、枚举的常量 @Target(ElementType.METHOD) //方法 @Target(ElementType.PARAMETER) //方法参数 @Target(ElementType.CONSTRUCTOR) //构造函数 @Target(ElementType.LOCAL_VARIABLE)//局部变量 @Target(ElementType.ANNOTATION_TYPE)//注解 @Target(ElementType.PACKAGE) ///包
每日一题
题目
在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。 如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。 说明: 如果题目有解,该答案即为唯一答案。 输入数组均为非空数组,且长度相同。 输入数组中的元素均为非负数。 示例 1: 输入: gas = [1,2,3,4,5] cost = [3,4,5,1,2]
思路1
假设从第0个加油站出发,判断能否到达下一个点,如果可以,则递归处理狭义点,如果行驶距离大于一圈的长度则表示可以环绕一圈,若不能则从下一个点开始。
代码
public int canCompleteCircuit(int[] gas, int[] cost) { int n = gas.length; int result = -1; int sum =0; for(int a : gas) { sum+= a; } for(int i = 0; i < n ; i++) { result = util(i, gas, cost, sum,0,0); if(result != -1) { result = i ; break; } } return result; }
public static int util(int now, int[] gas, int[] cost, int sum, int ga, int miles) {
/*
* ga 表示到达此加油站时邮箱还有的油
* miles表示已行进的路程
* sum表示一圈的路
*
* */
int longway = gas[now];
if(miles + longway + ga - cost[now] >= sum) return 1;
else if ( ga + longway - cost[now] >= 0){ // 如果能到下一个点
int index = now +1;
if(index >= gas.length) index = index - gas.length ;
return util(index, gas, cost, sum, ga +gas[now] - cost[now] , miles + cost[now]);
}
return -1;
}
```
代码2
public int canCompleteCircuit(int[] gas, int[] cost) {
int rest = 0, run = 0, start = 0;
for (int i = 0; i < gas.length; ++i){
run += (gas[i] - cost[i]);
rest += (gas[i] - cost[i]);
if (run < 0){
start = i + 1;
run = 0;
}
}
return rest < 0 ? -1: start;
}